From 5f0775e9d9a5e439e24ae9b7222e381c678ec730 Mon Sep 17 00:00:00 2001 From: wuliaokanke Date: Mon, 5 Dec 2022 10:51:39 +0800 Subject: [PATCH] add uadk 2.3.38 --- README.md | 1 + build.sh | 0 uadk/.gitignore | 184 + uadk/ChangeLog | 35 + uadk/INSTALL | 179 + uadk/LICENSE | 201 + uadk/Makefile.am | 131 + uadk/NEWS | 1 + uadk/README | 40 + uadk/autogen.sh | 3 + uadk/cleanup.sh | 20 + uadk/conf.sh | 20 + uadk/configure.ac | 113 + uadk/docs/maintenance.md | 130 + uadk/docs/perf.rst | 123 + uadk/docs/sched_diagram.png | 0 uadk/docs/wd_comp_async2.png | Bin 0 -> 14788 bytes uadk/docs/wd_comp_sync.png | Bin 0 -> 9368 bytes uadk/docs/wd_design.md | 675 ++ uadk/docs/wd_environment_variable | 59 + uadk/docs/wd_overview.png | Bin 0 -> 14618 bytes uadk/docs/wd_sched.rst | 33 + uadk/drv/hisi_comp.c | 1069 ++ uadk/drv/hisi_hpre.c | 2438 ++++ uadk/drv/hisi_qm_udrv.c | 1022 ++ uadk/drv/hisi_sec.c | 2615 ++++ uadk/include/drv/wd_aead_drv.h | 99 + uadk/include/drv/wd_cipher_drv.h | 85 + uadk/include/drv/wd_comp_drv.h | 91 + uadk/include/drv/wd_dh_drv.h | 59 + uadk/include/drv/wd_digest_drv.h | 87 + uadk/include/drv/wd_ecc_drv.h | 211 + uadk/include/drv/wd_rsa_drv.h | 84 + uadk/include/hisi_qm_udrv.h | 213 + uadk/include/uacce.h | 44 + uadk/include/wd.h | 532 + uadk/include/wd_aead.h | 227 + uadk/include/wd_alg_common.h | 117 + uadk/include/wd_cipher.h | 196 + uadk/include/wd_common.h | 23 + uadk/include/wd_comp.h | 226 + uadk/include/wd_dh.h | 80 + uadk/include/wd_digest.h | 245 + uadk/include/wd_ecc.h | 531 + uadk/include/wd_ecc_curve.h | 353 + uadk/include/wd_rsa.h | 227 + uadk/include/wd_sched.h | 67 + uadk/include/wd_util.h | 380 + uadk/lib/libwd.pc.in | 20 + uadk/lib/libwd_comp.pc.in | 21 + uadk/lib/libwd_crypto.pc.in | 21 + uadk/sample/Makefile.am | 16 + uadk/sample/uadk_comp.c | 505 + uadk/test/Makefile.am | 24 + uadk/test/hisi_hpre_test/Makefile.am | 15 + uadk/test/hisi_hpre_test/hpre_test_sample.h | 1555 +++ uadk/test/hisi_hpre_test/test_hisi_hpre.c | 9318 ++++++++++++++ uadk/test/hisi_hpre_test/test_hisi_hpre.h | 85 + uadk/test/hisi_sec_test/Makefile.am | 15 + uadk/test/hisi_sec_test/test_hisi_sec.c | 4360 +++++++ uadk/test/hisi_sec_test/test_hisi_sec.h | 1843 +++ uadk/test/hisi_zip_test/Makefile.am | 23 + uadk/test/hisi_zip_test/test_lib.c | 1875 +++ uadk/test/hisi_zip_test/test_lib.h | 351 + uadk/test/hisi_zip_test/test_sva_perf.c | 524 + uadk/test/hisi_zip_test/testsuit.c | 1372 +++ uadk/test/list_loader.py | 139 + uadk/test/sanity_test.sh | 481 + uadk/test/wd_mempool_test.c | 989 ++ uadk/uadk_tool/Makefile.am | 43 + uadk/uadk_tool/benchmark/hpre_protocol_data.h | 1667 +++ .../uadk_tool/benchmark/hpre_uadk_benchmark.c | 2433 ++++ .../uadk_tool/benchmark/hpre_uadk_benchmark.h | 6 + uadk/uadk_tool/benchmark/hpre_wd_benchmark.c | 2553 ++++ uadk/uadk_tool/benchmark/hpre_wd_benchmark.h | 6 + uadk/uadk_tool/benchmark/include/fse.h | 51 + uadk/uadk_tool/benchmark/sec_soft_benchmark.c | 990 ++ uadk/uadk_tool/benchmark/sec_soft_benchmark.h | 8 + uadk/uadk_tool/benchmark/sec_uadk_benchmark.c | 1074 ++ uadk/uadk_tool/benchmark/sec_uadk_benchmark.h | 6 + uadk/uadk_tool/benchmark/sec_wd_benchmark.c | 1188 ++ uadk/uadk_tool/benchmark/sec_wd_benchmark.h | 8 + uadk/uadk_tool/benchmark/uadk_benchmark.c | 743 ++ uadk/uadk_tool/benchmark/uadk_benchmark.h | 186 + uadk/uadk_tool/benchmark/zip_uadk_benchmark.c | 1200 ++ uadk/uadk_tool/benchmark/zip_uadk_benchmark.h | 6 + uadk/uadk_tool/benchmark/zip_wd_benchmark.c | 1257 ++ uadk/uadk_tool/benchmark/zip_wd_benchmark.h | 6 + uadk/uadk_tool/dfx/uadk_dfx.c | 253 + uadk/uadk_tool/dfx/uadk_dfx.h | 7 + uadk/uadk_tool/uadk_tool.c | 45 + uadk/v1/LICENSE | 201 + uadk/v1/drv/dummy_drv.c | 174 + uadk/v1/drv/dummy_drv.h | 35 + uadk/v1/drv/hisi_hpre_udrv.c | 2483 ++++ uadk/v1/drv/hisi_hpre_udrv.h | 88 + uadk/v1/drv/hisi_qm_udrv.c | 819 ++ uadk/v1/drv/hisi_qm_udrv.h | 206 + uadk/v1/drv/hisi_rng_udrv.c | 162 + uadk/v1/drv/hisi_rng_udrv.h | 41 + uadk/v1/drv/hisi_sec_udrv.c | 2735 +++++ uadk/v1/drv/hisi_sec_udrv.h | 546 + uadk/v1/drv/hisi_zip_udrv.c | 887 ++ uadk/v1/drv/hisi_zip_udrv.h | 137 + uadk/v1/drv/wd_drv.h | 22 + uadk/v1/internal/dummy_hw_usr_if.h | 57 + uadk/v1/internal/wd_dummy_usr_if.h | 45 + uadk/v1/internal/wd_ecc_curve.h | 303 + uadk/v1/test/Makefile.am | 16 + uadk/v1/test/bmm.c | 172 + uadk/v1/test/bmm.h | 25 + uadk/v1/test/bmm_test/Makefile.am | 13 + uadk/v1/test/bmm_test/bmm_test.c | 178 + uadk/v1/test/bmm_test/bmm_test.h | 20 + uadk/v1/test/hisi_hpre_test/Makefile.am | 23 + .../v1/test/hisi_hpre_test/hpre_test_sample.h | 1497 +++ uadk/v1/test/hisi_hpre_test/hpre_test_tools.c | 1977 +++ uadk/v1/test/hisi_hpre_test/test_hisi_hpre.c | 10055 ++++++++++++++++ uadk/v1/test/hisi_hpre_test/test_hisi_hpre.h | 100 + .../hisi_hpre_test/test_hisi_hpre_times.c | 4909 ++++++++ uadk/v1/test/hisi_sec_test/Makefile.am | 14 + uadk/v1/test/hisi_sec_test/test_hisi_sec.c | 2372 ++++ uadk/v1/test/hisi_sec_test/test_hisi_sec.h | 1588 +++ uadk/v1/test/hisi_sec_test_sgl/Makefile.am | 14 + .../hisi_sec_test_sgl/test_hisi_sec_sgl.c | 2809 +++++ .../hisi_sec_test_sgl/test_hisi_sec_sgl.h | 1566 +++ uadk/v1/test/hisi_trng_test/Makefile.am | 20 + uadk/v1/test/hisi_trng_test/test_hisi_trngk.c | 155 + uadk/v1/test/hisi_trng_test/test_hisi_trngp.c | 137 + uadk/v1/test/hisi_trng_test/test_hisi_trngu.c | 624 + uadk/v1/test/hisi_zip_test/Makefile.am | 38 + uadk/v1/test/hisi_zip_test/test_hisi_zip.c | 350 + .../test/hisi_zip_test/test_hisi_zip_perf.c | 950 ++ uadk/v1/test/hisi_zip_test/test_hisi_zlib.c | 76 + uadk/v1/test/hisi_zip_test/wd_zip_test.c | 617 + uadk/v1/test/hisi_zip_test/wd_zip_test_1630.c | 1106 ++ uadk/v1/test/hisi_zip_test/zconf.h | 534 + uadk/v1/test/hisi_zip_test/zip_alg.c | 1099 ++ uadk/v1/test/hisi_zip_test/zip_alg.h | 69 + uadk/v1/test/hisi_zip_test/zlib.h | 1912 +++ uadk/v1/test/hisi_zip_test_sgl/Makefile.am | 14 + uadk/v1/test/hisi_zip_test_sgl/sgl_test.c | 547 + uadk/v1/test/hisi_zip_test_sgl/sgl_test.h | 4 + uadk/v1/test/hisi_zip_test_sgl/wd_sched_sgl.c | 353 + uadk/v1/test/hisi_zip_test_sgl/wd_sched_sgl.h | 71 + .../test/hisi_zip_test_sgl/wd_zip_test_sgl.c | 703 ++ uadk/v1/test/hisi_zip_test_sgl/zip_alg_sgl.c | 1194 ++ uadk/v1/test/hisi_zip_test_sgl/zip_alg_sgl.h | 68 + uadk/v1/test/smm.c | 201 + uadk/v1/test/smm.h | 31 + uadk/v1/test/test_dummy.c | 126 + uadk/v1/test/test_mm/Makefile.am | 11 + uadk/v1/test/test_mm/test_wd_mem.c | 541 + uadk/v1/test/test_mm/test_wd_mem.h | 80 + uadk/v1/test/wd_sched.c | 309 + uadk/v1/test/wd_sched.h | 71 + uadk/v1/uacce.h | 86 + uadk/v1/wd.c | 904 ++ uadk/v1/wd.h | 214 + uadk/v1/wd_adapter.c | 289 + uadk/v1/wd_adapter.h | 75 + uadk/v1/wd_aead.c | 698 ++ uadk/v1/wd_aead.h | 213 + uadk/v1/wd_bmm.c | 425 + uadk/v1/wd_bmm.h | 50 + uadk/v1/wd_cipher.c | 567 + uadk/v1/wd_cipher.h | 166 + uadk/v1/wd_comp.c | 358 + uadk/v1/wd_comp.h | 256 + uadk/v1/wd_dh.c | 455 + uadk/v1/wd_dh.h | 91 + uadk/v1/wd_digest.c | 485 + uadk/v1/wd_digest.h | 168 + uadk/v1/wd_ecc.c | 2493 ++++ uadk/v1/wd_ecc.h | 273 + uadk/v1/wd_rng.c | 289 + uadk/v1/wd_rng.h | 76 + uadk/v1/wd_rsa.c | 1113 ++ uadk/v1/wd_rsa.h | 148 + uadk/v1/wd_sgl.c | 978 ++ uadk/v1/wd_sgl.h | 74 + uadk/v1/wd_util.c | 168 + uadk/v1/wd_util.h | 393 + uadk/wd.c | 824 ++ uadk/wd_aead.c | 734 ++ uadk/wd_cipher.c | 644 + uadk/wd_comp.c | 777 ++ uadk/wd_dh.c | 548 + uadk/wd_digest.c | 633 + uadk/wd_ecc.c | 2254 ++++ uadk/wd_mempool.c | 1016 ++ uadk/wd_rsa.c | 1148 ++ uadk/wd_sched.c | 562 + uadk/wd_util.c | 1779 +++ 194 files changed, 121281 insertions(+) create mode 100644 README.md create mode 100644 build.sh create mode 100644 uadk/.gitignore create mode 100644 uadk/ChangeLog create mode 100644 uadk/INSTALL create mode 100644 uadk/LICENSE create mode 100644 uadk/Makefile.am create mode 100644 uadk/NEWS create mode 100644 uadk/README create mode 100644 uadk/autogen.sh create mode 100644 uadk/cleanup.sh create mode 100644 uadk/conf.sh create mode 100644 uadk/configure.ac create mode 100644 uadk/docs/maintenance.md create mode 100644 uadk/docs/perf.rst create mode 100644 uadk/docs/sched_diagram.png create mode 100644 uadk/docs/wd_comp_async2.png create mode 100644 uadk/docs/wd_comp_sync.png create mode 100644 uadk/docs/wd_design.md create mode 100644 uadk/docs/wd_environment_variable create mode 100644 uadk/docs/wd_overview.png create mode 100644 uadk/docs/wd_sched.rst create mode 100644 uadk/drv/hisi_comp.c create mode 100644 uadk/drv/hisi_hpre.c create mode 100644 uadk/drv/hisi_qm_udrv.c create mode 100644 uadk/drv/hisi_sec.c create mode 100644 uadk/include/drv/wd_aead_drv.h create mode 100644 uadk/include/drv/wd_cipher_drv.h create mode 100644 uadk/include/drv/wd_comp_drv.h create mode 100644 uadk/include/drv/wd_dh_drv.h create mode 100644 uadk/include/drv/wd_digest_drv.h create mode 100644 uadk/include/drv/wd_ecc_drv.h create mode 100644 uadk/include/drv/wd_rsa_drv.h create mode 100644 uadk/include/hisi_qm_udrv.h create mode 100644 uadk/include/uacce.h create mode 100644 uadk/include/wd.h create mode 100644 uadk/include/wd_aead.h create mode 100644 uadk/include/wd_alg_common.h create mode 100644 uadk/include/wd_cipher.h create mode 100644 uadk/include/wd_common.h create mode 100644 uadk/include/wd_comp.h create mode 100644 uadk/include/wd_dh.h create mode 100644 uadk/include/wd_digest.h create mode 100644 uadk/include/wd_ecc.h create mode 100644 uadk/include/wd_ecc_curve.h create mode 100644 uadk/include/wd_rsa.h create mode 100644 uadk/include/wd_sched.h create mode 100644 uadk/include/wd_util.h create mode 100644 uadk/lib/libwd.pc.in create mode 100644 uadk/lib/libwd_comp.pc.in create mode 100644 uadk/lib/libwd_crypto.pc.in create mode 100644 uadk/sample/Makefile.am create mode 100644 uadk/sample/uadk_comp.c create mode 100644 uadk/test/Makefile.am create mode 100644 uadk/test/hisi_hpre_test/Makefile.am create mode 100644 uadk/test/hisi_hpre_test/hpre_test_sample.h create mode 100644 uadk/test/hisi_hpre_test/test_hisi_hpre.c create mode 100644 uadk/test/hisi_hpre_test/test_hisi_hpre.h create mode 100644 uadk/test/hisi_sec_test/Makefile.am create mode 100644 uadk/test/hisi_sec_test/test_hisi_sec.c create mode 100644 uadk/test/hisi_sec_test/test_hisi_sec.h create mode 100644 uadk/test/hisi_zip_test/Makefile.am create mode 100644 uadk/test/hisi_zip_test/test_lib.c create mode 100644 uadk/test/hisi_zip_test/test_lib.h create mode 100644 uadk/test/hisi_zip_test/test_sva_perf.c create mode 100644 uadk/test/hisi_zip_test/testsuit.c create mode 100644 uadk/test/list_loader.py create mode 100644 uadk/test/sanity_test.sh create mode 100644 uadk/test/wd_mempool_test.c create mode 100644 uadk/uadk_tool/Makefile.am create mode 100644 uadk/uadk_tool/benchmark/hpre_protocol_data.h create mode 100644 uadk/uadk_tool/benchmark/hpre_uadk_benchmark.c create mode 100644 uadk/uadk_tool/benchmark/hpre_uadk_benchmark.h create mode 100644 uadk/uadk_tool/benchmark/hpre_wd_benchmark.c create mode 100644 uadk/uadk_tool/benchmark/hpre_wd_benchmark.h create mode 100644 uadk/uadk_tool/benchmark/include/fse.h create mode 100644 uadk/uadk_tool/benchmark/sec_soft_benchmark.c create mode 100644 uadk/uadk_tool/benchmark/sec_soft_benchmark.h create mode 100644 uadk/uadk_tool/benchmark/sec_uadk_benchmark.c create mode 100644 uadk/uadk_tool/benchmark/sec_uadk_benchmark.h create mode 100644 uadk/uadk_tool/benchmark/sec_wd_benchmark.c create mode 100644 uadk/uadk_tool/benchmark/sec_wd_benchmark.h create mode 100644 uadk/uadk_tool/benchmark/uadk_benchmark.c create mode 100644 uadk/uadk_tool/benchmark/uadk_benchmark.h create mode 100644 uadk/uadk_tool/benchmark/zip_uadk_benchmark.c create mode 100644 uadk/uadk_tool/benchmark/zip_uadk_benchmark.h create mode 100644 uadk/uadk_tool/benchmark/zip_wd_benchmark.c create mode 100644 uadk/uadk_tool/benchmark/zip_wd_benchmark.h create mode 100644 uadk/uadk_tool/dfx/uadk_dfx.c create mode 100644 uadk/uadk_tool/dfx/uadk_dfx.h create mode 100644 uadk/uadk_tool/uadk_tool.c create mode 100644 uadk/v1/LICENSE create mode 100644 uadk/v1/drv/dummy_drv.c create mode 100644 uadk/v1/drv/dummy_drv.h create mode 100644 uadk/v1/drv/hisi_hpre_udrv.c create mode 100644 uadk/v1/drv/hisi_hpre_udrv.h create mode 100644 uadk/v1/drv/hisi_qm_udrv.c create mode 100644 uadk/v1/drv/hisi_qm_udrv.h create mode 100644 uadk/v1/drv/hisi_rng_udrv.c create mode 100644 uadk/v1/drv/hisi_rng_udrv.h create mode 100644 uadk/v1/drv/hisi_sec_udrv.c create mode 100644 uadk/v1/drv/hisi_sec_udrv.h create mode 100644 uadk/v1/drv/hisi_zip_udrv.c create mode 100644 uadk/v1/drv/hisi_zip_udrv.h create mode 100644 uadk/v1/drv/wd_drv.h create mode 100644 uadk/v1/internal/dummy_hw_usr_if.h create mode 100644 uadk/v1/internal/wd_dummy_usr_if.h create mode 100644 uadk/v1/internal/wd_ecc_curve.h create mode 100644 uadk/v1/test/Makefile.am create mode 100644 uadk/v1/test/bmm.c create mode 100644 uadk/v1/test/bmm.h create mode 100644 uadk/v1/test/bmm_test/Makefile.am create mode 100644 uadk/v1/test/bmm_test/bmm_test.c create mode 100644 uadk/v1/test/bmm_test/bmm_test.h create mode 100644 uadk/v1/test/hisi_hpre_test/Makefile.am create mode 100644 uadk/v1/test/hisi_hpre_test/hpre_test_sample.h create mode 100644 uadk/v1/test/hisi_hpre_test/hpre_test_tools.c create mode 100644 uadk/v1/test/hisi_hpre_test/test_hisi_hpre.c create mode 100644 uadk/v1/test/hisi_hpre_test/test_hisi_hpre.h create mode 100644 uadk/v1/test/hisi_hpre_test/test_hisi_hpre_times.c create mode 100644 uadk/v1/test/hisi_sec_test/Makefile.am create mode 100644 uadk/v1/test/hisi_sec_test/test_hisi_sec.c create mode 100644 uadk/v1/test/hisi_sec_test/test_hisi_sec.h create mode 100644 uadk/v1/test/hisi_sec_test_sgl/Makefile.am create mode 100644 uadk/v1/test/hisi_sec_test_sgl/test_hisi_sec_sgl.c create mode 100644 uadk/v1/test/hisi_sec_test_sgl/test_hisi_sec_sgl.h create mode 100644 uadk/v1/test/hisi_trng_test/Makefile.am create mode 100644 uadk/v1/test/hisi_trng_test/test_hisi_trngk.c create mode 100644 uadk/v1/test/hisi_trng_test/test_hisi_trngp.c create mode 100644 uadk/v1/test/hisi_trng_test/test_hisi_trngu.c create mode 100644 uadk/v1/test/hisi_zip_test/Makefile.am create mode 100644 uadk/v1/test/hisi_zip_test/test_hisi_zip.c create mode 100644 uadk/v1/test/hisi_zip_test/test_hisi_zip_perf.c create mode 100644 uadk/v1/test/hisi_zip_test/test_hisi_zlib.c create mode 100644 uadk/v1/test/hisi_zip_test/wd_zip_test.c create mode 100644 uadk/v1/test/hisi_zip_test/wd_zip_test_1630.c create mode 100644 uadk/v1/test/hisi_zip_test/zconf.h create mode 100644 uadk/v1/test/hisi_zip_test/zip_alg.c create mode 100644 uadk/v1/test/hisi_zip_test/zip_alg.h create mode 100644 uadk/v1/test/hisi_zip_test/zlib.h create mode 100644 uadk/v1/test/hisi_zip_test_sgl/Makefile.am create mode 100644 uadk/v1/test/hisi_zip_test_sgl/sgl_test.c create mode 100644 uadk/v1/test/hisi_zip_test_sgl/sgl_test.h create mode 100644 uadk/v1/test/hisi_zip_test_sgl/wd_sched_sgl.c create mode 100644 uadk/v1/test/hisi_zip_test_sgl/wd_sched_sgl.h create mode 100644 uadk/v1/test/hisi_zip_test_sgl/wd_zip_test_sgl.c create mode 100644 uadk/v1/test/hisi_zip_test_sgl/zip_alg_sgl.c create mode 100644 uadk/v1/test/hisi_zip_test_sgl/zip_alg_sgl.h create mode 100644 uadk/v1/test/smm.c create mode 100644 uadk/v1/test/smm.h create mode 100644 uadk/v1/test/test_dummy.c create mode 100644 uadk/v1/test/test_mm/Makefile.am create mode 100644 uadk/v1/test/test_mm/test_wd_mem.c create mode 100644 uadk/v1/test/test_mm/test_wd_mem.h create mode 100644 uadk/v1/test/wd_sched.c create mode 100644 uadk/v1/test/wd_sched.h create mode 100644 uadk/v1/uacce.h create mode 100644 uadk/v1/wd.c create mode 100644 uadk/v1/wd.h create mode 100644 uadk/v1/wd_adapter.c create mode 100644 uadk/v1/wd_adapter.h create mode 100644 uadk/v1/wd_aead.c create mode 100644 uadk/v1/wd_aead.h create mode 100644 uadk/v1/wd_bmm.c create mode 100644 uadk/v1/wd_bmm.h create mode 100644 uadk/v1/wd_cipher.c create mode 100644 uadk/v1/wd_cipher.h create mode 100644 uadk/v1/wd_comp.c create mode 100644 uadk/v1/wd_comp.h create mode 100644 uadk/v1/wd_dh.c create mode 100644 uadk/v1/wd_dh.h create mode 100644 uadk/v1/wd_digest.c create mode 100644 uadk/v1/wd_digest.h create mode 100644 uadk/v1/wd_ecc.c create mode 100644 uadk/v1/wd_ecc.h create mode 100644 uadk/v1/wd_rng.c create mode 100644 uadk/v1/wd_rng.h create mode 100644 uadk/v1/wd_rsa.c create mode 100644 uadk/v1/wd_rsa.h create mode 100644 uadk/v1/wd_sgl.c create mode 100644 uadk/v1/wd_sgl.h create mode 100644 uadk/v1/wd_util.c create mode 100644 uadk/v1/wd_util.h create mode 100644 uadk/wd.c create mode 100644 uadk/wd_aead.c create mode 100644 uadk/wd_cipher.c create mode 100644 uadk/wd_comp.c create mode 100644 uadk/wd_dh.c create mode 100644 uadk/wd_digest.c create mode 100644 uadk/wd_ecc.c create mode 100644 uadk/wd_mempool.c create mode 100644 uadk/wd_rsa.c create mode 100644 uadk/wd_sched.c create mode 100644 uadk/wd_util.c diff --git a/README.md b/README.md new file mode 100644 index 0000000..cf02b10 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +kae2 diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..e69de29 diff --git a/uadk/.gitignore b/uadk/.gitignore new file mode 100644 index 0000000..e220fc7 --- /dev/null +++ b/uadk/.gitignore @@ -0,0 +1,184 @@ +# +# NOTE! Don't add files that are generated in specific +# subdirectories here. Add them in the ".gitignore" file +# in that subdirectory instead. +# +# NOTE! Please use 'git ls-files -i --exclude-standard' +# command after changing this file, to see if there are +# any tracked files which get ignored after the change. +# +# Normal rules (sorted alphabetically) +# +.* +*.a +*.asn1.[ch] +*.bin +*.bz2 +*.c.[012]*.* +*.dtb +*.dtb.S +*.dwo +*.elf +*.gcno +*.gz +*.i +*.ko +*.la +*.lex.c +*.ll +*.lst +*.lz4 +*.lzma +*.lzo +*.mod.c +*.o +*.o.* +*.order +*.patch +*.s +*.so +*.so.dbg +*.su +*.symtypes +*.tab.[ch] +*.tar +*.xz +*.scan +*.log +Module.symvers +modules.builtin + +# +# Top-level generic files +# +/tags +/TAGS +/linux +/vmlinux +/vmlinux.32 +/vmlinux-gdb.py +/vmlinuz +/System.map +/Module.markers + +# +# RPM spec file (make rpm-pkg) +# +/*.spec + +# +# Debian directory (make deb-pkg) +# +/debian/ + +# +# Snap directory (make snap-pkg) +# +/snap/ + +# +# tar directory (make tar*-pkg) +# +/tar-install/ + +# +# git files that we don't want to ignore even if they are dot-files +# +!.gitignore +!.mailmap +!.cocciconfig +!.clang-format + +# +# Generated include files +# +include/config +include/generated +include/ksym +arch/*/include/generated + +# stgit generated dirs +patches-* + +# quilt's files +patches +series + +# cscope files +cscope.* +ncscope.* + +# gnu global files +GPATH +GRTAGS +GSYMS +GTAGS + +# id-utils files +ID + +*.orig +*~ +\#*# + +# +# Leavings from module signing +# +extra_certificates +signing_key.pem +signing_key.priv +signing_key.x509 +x509.genkey + +# Kconfig presets +all.config + +# Kdevelop4 +*.kdev4 + +#autogen files +Makefile +Makefile.in +aclocal.m4 +ar-lib +autom4te.cache/ +compile +config.guess +config.h +config.h.in +config.log +config.status +config.sub +configure +depcomp +*.lo +install-sh +libtool +libwd.la +ltmain.sh +m4/ +missing +sample/uadk_comp +stamp-h1 +test/test_dummy +test/test_hisi_zip +test/test_hisi_zlib +test/test_bind_api +test/hisi_hpre_test/test_hisi_hpre +test/hisi_sec_test/test_hisi_sec +test/hisi_zip_test/zip_sva_perf +test/wd_mempool_test +uadk_tool/uadk_tool +v1/test/hisi_zip_test/test_hisi_zip +v1/test/hisi_zip_test/test_hisi_zip_perf +v1/test/hisi_zip_test/test_hisi_zlib +v1/test/hisi_zip_test/wd_zip_test +v1/test/hisi_zip_test/wd_zip_test_1630 +v1/test/hisi_zip_test_sgl/sgl_test +v1/test/hisi_zip_test_sgl/wd_zip_test_sgl +v1/test/test_mm/test_wd_mem +*.gcda +*.ut + +# pkg-config file +lib/*.pc diff --git a/uadk/ChangeLog b/uadk/ChangeLog new file mode 100644 index 0000000..0cf3051 --- /dev/null +++ b/uadk/ChangeLog @@ -0,0 +1,35 @@ +UADK 2.3.11, Released Jul 9th, 2021 + + Feature list: + + Support SVA on ZIP/SEC/HPRE accelerator on kunpeng930. + + Support of user space algorithm API layer of Warpdrive. + + Offload Warpdrive WCRYPTO asymmetric algorithms with HPRE DH/RSA + on kunpeng920/930. + + Offload elliptic curve EC algorithms SM2/ECDH/ECDSA/X25519/X448 on + kunpeng930 HPRE in user space. + + Offload Warpdrive WCRYPTO symmetric algorithms AES/SM4/SM3/AEAD .etc + algorithms. + + Offload Warpdrive WCRYPTO COMP by ZIP's zlib/gzib/zstd/deflate + algorithms. + + Offload Warpdrive WCRYPTO TRNG's DRBG/TRNG algorithms. + + Support of poll in user space process as using queues. + + Support container such as Docker with Warpdrive. + + WD supports burst APIs such as cipher/digest/aead algorithms. + + Support DMA memory management in Warpdrive in user space. + + Support of SGL in user space Warpdrive. + + Isolation of (bad) accelerator device. + + Support of RAS recovery diff --git a/uadk/INSTALL b/uadk/INSTALL new file mode 100644 index 0000000..a6f53d9 --- /dev/null +++ b/uadk/INSTALL @@ -0,0 +1,179 @@ +Deploying UADK + +UADK is a framekwork for user application to access hardware, and it depends +UACCE in kernel. + + +1. Kernel Requirement + +User needs to make sure that UACCE is already supported in Linux kernel. The +kernel version should be at least v5.9 with SVA (Shared Virtual Addressing) +enabled. + + +2. Kernel Configuration + +UACCE could be built as module or built-in. + +Here's an example to enable UACCE with hardware accelerator in Hisilicon +platform. + + CONFIG_IOMMU_SVA_LIB=y + CONFIG_ARM_SMMU=y + CONFIG_ARM_SMMU_V3=y + CONFIG_ARM_SMMU_V3_SVA=y + CONFIG_PCI_PASID=y + CONFIG_UACCE=y + CONFIG_CRYPTO_DEV_HISI_SEC2=y + CONFIG_CRYPTO_DEV_HISI_QM=y + CONFIG_CRYPTO_DEV_HISI_ZIP=y + CONFIG_CRYPTO_DEV_HISI_HPRE=y + +Make sure all these above kernel configurations are selected. + +Build kernel and install the kernel image on Hisilicon platform. + + +3. Build UADK in native environment + +Configure UADK + + $ ./cleanup.sh + + Make sure that all generated files could be removed. + + $ ./autogen.sh + $ ./conf.sh + + UADK could be configured as either static or dynamic library by conf.sh. + By default, it's configured as dynamic library. + + $ make + $ sudo make install + + Both dynamic and static libraries would be installed in /usr/local/lib + directory. And all head files would be installed in /usr/local/include/uadk + directory. + + +4. Set proper permission on device nodes + +Harware accelerators register in UADK. So char devices are created in dev +directory. In order to make user access resources on hardware accelerators, +write permission should be opened to user. + + $ sudo chmod 777 /dev/hisi_hpre-* + $ sudo chmod 777 /dev/hisi_sec-* + $ sudo chmod 777 /dev/hisi_zip-* + + +5. Run test applications + +Test on zip hardware accelerator + + Synchronous mode + $ zip_sva_perf -b 8192000 -l 1000 -v -m 0 + Asynchronous mode + $ zip_sva_perf -b 8192000 -l 1000 -v -m 1 + +Test on sec hardware accelerator + + Synchronous mode + $ test_hisi_sec --cipher 0 --optype 0 --pktlen 16 --keylen 16 --times 1 --sync --multi 1 + $ test_hisi_sec --digest 0 --optype 0 --pktlen 16 --keylen 16 --times 1 --sync --multi 1 + Asynchronous mode + $ test_hisi_sec --cipher 0 --optype 0 --pktlen 16 --keylen 16 --times 1 --async --multi 1 + $ test_hisi_sec --digest 0 --optype 0 --pktlen 16 --keylen 16 --times 1 --async --multi 1 + +Test on hpre hardware accelerator + + Synchronous mode + $ test_hisi_hpre --trd_mode=sync + Asynchronous mode + $ test_hisi_hpre --trd_mode=async + + +6. (Optional) Build UADK by cross compiler + + Since some libraries are used in UADK library and test cases, these + libraries should be built first and installed into the path of cross + compiler. + + ${LIBROOT} and ${CROSSTOOLCHAIN} is a directory that should be defined + by user. linaro-gcc-7.2.1 is used for reference at here. + + a) Build NUMA library + + $git clone https://github.com/numactl/numactl.git + $cd numactl + $./autogen.sh + $autoconf -i + $CC=aarch64-linux-gnu-gcc ./configure --host=i386-linux-gnu --target=aarch64-linux-gnu --prefix=${LIBROOT}/usr/local + $make + $make install + + Install head files and libraries into the path of cross compiler by manual. + $sudo cp ${LIBROOT}/usr/local/include/numa*.h ${CROSSTOOLCHAIN}/aarch64-linux-gnu/libc/usr/include/ + $sudo cp ${LIBROOT}/usr/local/lib/libnuma.a ${CROSSTOOLCHAIN}/lib/gcc/aarch64-linux-gnu/7.2.1/ + $sudo cp ${LIBROOT}/usr/local/lib/libnuma.so.1.0.0 ${CROSSTOOLCHAIN}/lib/gcc/aarch64-linux-gnu/7.2.1/ + $cd ${CROSSTOOLCHAIN}/lib/gcc/aarch64-linux-gnu/7.2.1 + $sudo ln -sf libnuma.so.1.0.0 libnuma.so.1 + $sudo ln -sf libnuma.so.1 libnuma.so + + b) Build OpenSSL library + + $git clone https://github.com/openssl/openssl.git + $cd openssl + $git checkout OpenSSL_1_1_1a + $./Configure linux-aarch64 --cross-compile-prefix=aarch64-linux-gnu- -D__ARCH_MAX_ARCH__=8 --prefix=${LIBROOT}/usr/local --shared + $make + $make install + + $sudo cp -a ${LIBROOT}/usr/local/include/openssl ${CROSSTOOLCHAIN}/aarch64-linux-gnu/libc/usr/include/ + $cd ${CROSSTOOLCHAIN}/lib/gcc/aarch64-linux-gnu/7.2.1 + $sudo cp ${LIBROOT}/usr/local/lib/libcrypto.a . + $sudo cp ${LIBROOT}/usr/local/lib/libcrypto.so.3 . + $sudo cp ${LIBROOT}/usr/local/lib/libssl.a . + $sudo cp ${LIBROOT}/usr/local/lib/libssl.so.3 . + $sudo ln -sf libcrypto.so.3 libcrypto.so + $sudo ln -sf libssl.so.3 libssl.so + + c) Build zlib library + + $git clone https://github.com/madler/zlib + $cd zlib + $CC=aarch64-linux-gnu-gcc \ + AR=aarch64-linux-gnu-ar \ + RANLIB=aarch64-linux-gnu-ranlib \ + ./configure --prefix=${LIBROOT}/usr/local + $CC=aarch64-linux-gnu-gcc \ + AR=aarch64-linux-gnu-ar \ + RANLIB=aarch64-linux-gnu-ranlib \ + make + $make install + + $sudo cp ${LIBROOT}/usr/local/include/zconf.h ${CROSSTOOLCHAIN}/aarch64-linux-gnu/libc/usr/include/ + $sudo cp ${LIBROOT}/usr/local/include/zlib.h ${CROSSTOOLCHAIN}/aarch64-linux-gnu/libc/usr/include/ + $cd ${CROSSTOOLCHAIN}/lib/gcc/aarch64-linux-gnu/7.2.1 + $sudo cp ${LIBROOT}/usr/local/lib/libz.a . + $sudo cp ${LIBROOT}/usr/local/lib/libz.so.1.2.11 . + $sudo ln -sf libz.so.1.2.11 libz.so.1 + $sudo ln -sf libz.so.1 libz.so + + + d) Build UADK and install it into user specified directory + + $cd ${UADK} + $./cleanup.sh + $./autogen.sh + $CC=aarch64-linux-gnu-gcc \ + ac_cv_func_malloc_0_nonnull=yes \ + ac_cv_func_realloc_0_nonnull=yes \ + ./configure \ + --host=i386-linux-gnu \ + --target=aarch64-linux-gnu \ + --prefix=${LIB_ROOT}/usr/local \ + --includedir=${LIB_ROOT}/usr/local/include/uadk \ + --disable-static --enable-shared + $make + $make install diff --git a/uadk/LICENSE b/uadk/LICENSE new file mode 100644 index 0000000..360db8c --- /dev/null +++ b/uadk/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + https://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. \ No newline at end of file diff --git a/uadk/Makefile.am b/uadk/Makefile.am new file mode 100644 index 0000000..66da853 --- /dev/null +++ b/uadk/Makefile.am @@ -0,0 +1,131 @@ +ACLOCAL_AMFLAGS = -I m4 -I./include +AUTOMAKE_OPTIONS = foreign subdir-objects +AM_CFLAGS=-Wall -Werror -fno-strict-aliasing -I$(top_srcdir)/include +CLEANFILES = + +if WITH_LOG_FILE +AM_CFLAGS+=-DWITH_LOG_FILE=\"$(with_log_file)\" +endif # WITH_LOG_FILE + +# libtool version is {current}:{revision}:{age} with -version-info +# libNAME.so.{x}.{y}.{z} +# But {current}:{revision}:{age} doesn't equal to {x}.{y}.{z} +# x = current - age +# y = age +# z = revision +# +# libtool version is {major}:{minor}:{revision} with -version-number +# libNAME.so.{x}.{y}.{z} +# x = major +# y = minor +# z = revision +MAJOR = 2 +MINOR = 3 +REVISION = 38 +UADK_VERSION = -version-number ${MAJOR}:${MINOR}:${REVISION} + +DAY = 11 +MONTH = Jun +YEAR = 2022 +AM_CFLAGS+= -DUADK_VERSION_NUMBER="\"UADK version: ${MAJOR}.${MINOR}.${REVISION}\"" +AM_CFLAGS+= -DUADK_RELEASED_TIME="\"Released ${MONTH} ${DAY}, ${YEAR}\"" + +pkginclude_HEADERS = include/wd.h include/wd_cipher.h include/wd_aead.h \ + include/wd_comp.h include/wd_dh.h include/wd_digest.h \ + include/wd_rsa.h include/uacce.h include/wd_alg_common.h \ + include/wd_common.h include/wd_ecc.h include/wd_sched.h + +nobase_pkginclude_HEADERS = v1/wd.h v1/wd_cipher.h v1/wd_aead.h v1/uacce.h v1/wd_dh.h \ + v1/wd_digest.h v1/wd_rsa.h v1/wd_bmm.h + +lib_LTLIBRARIES=libwd.la libwd_comp.la libwd_crypto.la libhisi_zip.la \ + libhisi_hpre.la libhisi_sec.la + +libwd_la_SOURCES=wd.c wd_mempool.c wd.h \ + v1/wd.c v1/wd.h v1/wd_adapter.c v1/wd_adapter.h \ + v1/wd_rng.c v1/wd_rng.h \ + v1/wd_rsa.c v1/wd_rsa.h \ + v1/wd_aead.c v1/wd_aead.h \ + v1/wd_dh.c v1/wd_dh.h \ + v1/wd_comp.c v1/wd_comp.h \ + v1/wd_cipher.c v1/wd_cipher.h \ + v1/wd_digest.c v1/wd_digest.h \ + v1/wd_util.c v1/wd_util.h \ + v1/wd_bmm.c v1/wd_bmm.h \ + v1/wd_ecc.c v1/wd_ecc.h \ + v1/wd_sgl.c v1/wd_sgl.h \ + v1/drv/dummy_drv.c v1/drv/dummy_drv.h \ + v1/drv/hisi_qm_udrv.c v1/drv/hisi_qm_udrv.h \ + v1/drv/hisi_zip_udrv.c v1/drv/hisi_zip_udrv.h \ + v1/drv/hisi_hpre_udrv.c v1/drv/hisi_hpre_udrv.h \ + v1/drv/hisi_sec_udrv.c v1/drv/hisi_sec_udrv.h \ + v1/drv/hisi_rng_udrv.c v1/drv/hisi_rng_udrv.h + +libwd_comp_la_SOURCES=wd_comp.c wd_comp.h wd_comp_drv.h wd_util.c wd_util.h \ + wd_sched.c wd_sched.h + +libhisi_zip_la_SOURCES=drv/hisi_comp.c hisi_comp.h drv/hisi_qm_udrv.c \ + hisi_qm_udrv.h wd_comp_drv.h + +libwd_crypto_la_SOURCES=wd_cipher.c wd_cipher.h wd_cipher_drv.h \ + wd_aead.c wd_aead.h wd_aead_drv.h \ + wd_rsa.c wd_rsa.h wd_rsa_drv.h \ + wd_dh.c wd_dh.h wd_dh_drv.h \ + wd_ecc.c wd_ecc.h wd_ecc_drv.h \ + wd_digest.c wd_digest.h wd_digest_drv.h \ + wd_util.c wd_util.h \ + wd_sched.c wd_sched.h + +libhisi_sec_la_SOURCES=drv/hisi_sec.c drv/hisi_qm_udrv.c \ + hisi_qm_udrv.h wd_cipher_drv.h wd_aead_drv.h + +libhisi_hpre_la_SOURCES=drv/hisi_hpre.c drv/hisi_qm_udrv.c \ + hisi_qm_udrv.h wd_hpre_drv.h +if WD_STATIC_DRV +AM_CFLAGS += -DWD_STATIC_DRV +AM_CFLAGS += -DWD_NO_LOG + +libwd_la_LIBADD = $(libwd_la_OBJECTS) -lnuma + +libwd_comp_la_LIBADD = $(libwd_la_OBJECTS) -ldl +libwd_comp_la_DEPENDENCIES = libwd.la + +libhisi_zip_la_LIBADD = -ldl + +libwd_crypto_la_LIBADD = $(libwd_la_OBJECTS) -ldl -lnuma +libwd_crypto_la_DEPENDENCIES = libwd.la + +libhisi_sec_la_LIBADD = $(libwd_la_OBJECTS) $(libwd_crypto_la_OBJECTS) +libhisi_sec_la_DEPENDENCIES = libwd.la libwd_crypto.la + +libhisi_hpre_la_LIBADD = $(libwd_la_OBJECTS) $(libwd_crypto_la_OBJECTS) +libhisi_hpre_la_DEPENDENCIES = libwd.la libwd_crypto.la +else +libwd_la_LDFLAGS=$(UADK_VERSION) +libwd_la_LIBADD= -lnuma + +libwd_comp_la_LIBADD= -lwd -ldl +libwd_comp_la_LDFLAGS=$(UADK_VERSION) +libwd_comp_la_DEPENDENCIES= libwd.la + +libhisi_zip_la_LIBADD= -ldl +libhisi_zip_la_LDFLAGS=$(UADK_VERSION) + +libwd_crypto_la_LIBADD= -lwd -ldl -lnuma +libwd_crypto_la_LDFLAGS=$(UADK_VERSION) +libwd_crypto_la_DEPENDENCIES= libwd.la + +libhisi_sec_la_LIBADD= -lwd -lwd_crypto +libhisi_sec_la_LDFLAGS=$(UADK_VERSION) +libhisi_sec_la_DEPENDENCIES= libwd.la libwd_crypto.la + +libhisi_hpre_la_LIBADD= -lwd -lwd_crypto +libhisi_hpre_la_LDFLAGS=$(UADK_VERSION) +libhisi_hpre_la_DEPENDENCIES= libwd.la libwd_crypto.la +endif # WD_STATIC_DRV + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = lib/libwd_crypto.pc lib/libwd_comp.pc lib/libwd.pc +CLEANFILES += $(pkgconfig_DATA) + +SUBDIRS=. test v1/test uadk_tool sample diff --git a/uadk/NEWS b/uadk/NEWS new file mode 100644 index 0000000..b1b7161 --- /dev/null +++ b/uadk/NEWS @@ -0,0 +1 @@ +init diff --git a/uadk/README b/uadk/README new file mode 100644 index 0000000..511bbd2 --- /dev/null +++ b/uadk/README @@ -0,0 +1,40 @@ +User Space Accelerator Development Kit +====================================== + +UADK is a framework for user application to access hardware accelerator in a +unified, secure, and efficient way. UADK is comprised of UACCE, libwd and many +other algorithm libraries for different applications. + +UADK contains the following elements: + +wd.c + UADK fundamental library which wraps the basic operations to the UACCE + device. libwd is this library. + +wd_[alg].c + UADK algorithm libraries. libwd_comp is for compression/decompression, + libwd_crypto is for all encryption/decryption and hash algorithm. + +wd_utils.[ch] + Some utility functions used by UADK and its drivers. + +drv/* + Hardware drivers. It helps to fulfill the semantic of algorithm + libraries for particular hardware. + +test/* + Test applications to use UADK. + +include/* + Head files for user APP and hardware drivers. + +docs/* + Documentations. + +====================================== + +The information of deploying UADK is in INSTALL file. + +The design document is in docs/wd_design.md file. + +The rules of library version are in docs/maintenance.md file. diff --git a/uadk/autogen.sh b/uadk/autogen.sh new file mode 100644 index 0000000..58deaf4 --- /dev/null +++ b/uadk/autogen.sh @@ -0,0 +1,3 @@ +#!/bin/sh -x + +autoreconf -i -f -v diff --git a/uadk/cleanup.sh b/uadk/cleanup.sh new file mode 100644 index 0000000..60adc98 --- /dev/null +++ b/uadk/cleanup.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +if [ -r Makefile ]; then + make distclean +fi + +FILES="aclocal.m4 autom4te.cache compile config.guess config.h.in config.log \ + config.status config.sub configure cscope.out depcomp install-sh \ + libsrc/Makefile libsrc/Makefile.in libtool ltmain.sh Makefile \ + ar-lib m4 Makefile.in missing src/Makefile src/Makefile.in \ + test/Makefile test/Makefile.in test/hisi_hpre_test/Makefile.in \ + test/hisi_hpre_test/Makefile test/hisi_sec_test/Makefile \ + test/hisi_sec_test/Makefile.in test/hisi_zip_test/Makefile \ + test/hisi_zip_test/Makefile.in uadk_tool/Makefile \ + uadk_tool/Makefile.in \ + v1/Makefile.in v1/Makefile.in v1/test/Makefile v1/test/Makefile.in \ + v1/test/test_mm/Makefile v1/test/test_mm/Makefile.in \ + v1/test/bmm_test/Makefile v1/test/bmm_test/Makefile.in" + +rm -vRf $FILES *~ diff --git a/uadk/conf.sh b/uadk/conf.sh new file mode 100644 index 0000000..59af821 --- /dev/null +++ b/uadk/conf.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +# Configure UADK to generate Makefile + +# Build UADK into static library +COMPILE_TYPE="--disable-static --enable-shared" + +# These two parameters could be in arbitary sequence +if [[ $1 && $1 = "--static" ]] || [[ $2 && $2 = "--static" ]]; then + echo "Configure to static compile!" + COMPILE_TYPE="--enable-static --disable-shared --with-static_drv" +fi + + +ac_cv_func_malloc_0_nonnull=yes ac_cv_func_realloc_0_nonnull=yes ./configure \ + --enable-perf=yes \ + --host aarch64-linux-gnu \ + --target aarch64-linux-gnu \ + --includedir=/usr/local/include/uadk \ + $COMPILE_TYPE diff --git a/uadk/configure.ac b/uadk/configure.ac new file mode 100644 index 0000000..6991fe4 --- /dev/null +++ b/uadk/configure.ac @@ -0,0 +1,113 @@ +AC_PREREQ([2.69]) +AC_INIT([uadk], [2.3.38], [liguozhu@hisilicon.com]) +AC_CONFIG_SRCDIR([wd.c]) +AM_INIT_AUTOMAKE([1.10 no-define]) + +AC_CONFIG_MACRO_DIR([m4]) +AC_CONFIG_HEADERS([config.h]) + +# Checks for programs. +AC_PROG_AWK +AC_PROG_CC +AC_PROG_CPP +AC_PROG_INSTALL +AC_PROG_LN_S +AC_PROG_MAKE_SET + +AM_PROG_AR +AC_PROG_LIBTOOL +AM_PROG_LIBTOOL +LT_INIT +AM_PROG_CC_C_O + +AC_ARG_ENABLE([debug-log], + AS_HELP_STRING([--enable-debug-log], [enable debug logging globally]), + [ AS_IF([test "x$enable_debug_log" = "xyes"], + AC_DEFINE(DEBUG_LOG, 1, [Enable debug log]) + debug_log=true, + debug_log=false) + ], + [debug_log=false] +) + +AC_ARG_ENABLE([perf], + AS_HELP_STRING([--disble-perf], [enable measuring performance]), + [ AS_IF([test "x$enable_perf" = "xyes"], + AC_DEFINE(HAVE_PERF, 1, [Support for measuring performance]) + perf=true + ], + [perf=false]) + [perf=false] +) + +AC_CHECK_LIB(z, zlibVersion, + [ AC_DEFINE(HAVE_ZLIB, 1, [Have zlib]) + have_zlib=true ], + [ have_zlib=false ]) +AM_CONDITIONAL([HAVE_ZLIB], [test "x$have_zlib" = "xtrue"]) + +PKG_CHECK_MODULES(libcrypto, libcrypto < 3.0 libcrypto >= 1.1, + [ AC_DEFINE(HAVE_CRYPTO, 1, [Have crypto]) + have_crypto=true ], + [ have_crypto=false ]) +AM_CONDITIONAL([HAVE_CRYPTO], [test "x$have_crypto" = "xtrue"]) + +AC_ARG_WITH(log_file, + AS_HELP_STRING([--with-log_file], [File to write log]), + WITH_LOG_FILE=$withvar, WITH_LOG_FILE=) +AC_SUBST(with_log_file) +AM_CONDITIONAL([WITH_LOG_FILE], [test -n "$with_log_file"]) + +AC_ARG_WITH(static_drv, + AS_HELP_STRING([--with-static_drv], [Built as static library]), + WD_STATIC_DRV=$withvar, WD_STATIC_DRV=) +AC_SUBST(with_static_drv) +AM_CONDITIONAL([WD_STATIC_DRV], [test -n "$with_static_drv"]) + +AC_ARG_WITH(openssl_dir, + AS_HELP_STRING([--with-openssl_dir], [Path to OpenSSL source code])) +AC_SUBST(with_openssl_dir) + +AM_CONDITIONAL([WITH_OPENSSL_DIR], [test -n "$with_openssl_dir"]) + +AC_ARG_WITH(zlib_fse_dir, + AS_HELP_STRING([--with-zlib_fse_dir], [Path to Zlib FSE library])) +AC_SUBST(with_zlib_fse_dir) +AM_CONDITIONAL([WITH_ZLIB_FSE_DIR], [test -n "$with_zlib_fse_dir"]) + +# Checks for header files. +AC_CHECK_HEADERS([fcntl.h limits.h stddef.h stdint.h stdlib.h string.h sys/ioctl.h sys/time.h unistd.h]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_CHECK_HEADER_STDBOOL +AC_C_INLINE +AC_TYPE_OFF_T +AC_TYPE_SIZE_T +AC_TYPE_UINT16_T +AC_TYPE_UINT32_T +AC_TYPE_UINT64_T +AC_TYPE_UINT8_T + +# Checks for library functions. +AC_FUNC_MALLOC +AC_FUNC_MMAP +AC_CHECK_FUNCS([gettimeofday memmove memset munmap strstr strtoul strtoull]) + +AC_CONFIG_FILES([Makefile + lib/libwd_crypto.pc lib/libwd_comp.pc lib/libwd.pc + test/Makefile + test/hisi_hpre_test/Makefile + test/hisi_sec_test/Makefile + test/hisi_zip_test/Makefile + uadk_tool/Makefile + sample/Makefile + v1/test/Makefile + v1/test/bmm_test/Makefile + v1/test/test_mm/Makefile + v1/test/hisi_hpre_test/Makefile + v1/test/hisi_trng_test/Makefile + v1/test/hisi_sec_test/Makefile + v1/test/hisi_sec_test_sgl/Makefile + v1/test/hisi_zip_test/Makefile + v1/test/hisi_zip_test_sgl/Makefile]) +AC_OUTPUT diff --git a/uadk/docs/maintenance.md b/uadk/docs/maintenance.md new file mode 100644 index 0000000..b0fda82 --- /dev/null +++ b/uadk/docs/maintenance.md @@ -0,0 +1,130 @@ + +# Contributor's Guide + +## Getting Started + +Make sure you have registered in the mailing list "linux-accelerators@lists.ozlabs.org". + +Clone UADK from [Github](https://github.com/Linaro/uadk). + +## Lincense + +libwd is adopting Apache License 2.0. + +## Coding Style + +### Include statement ording + +All header files that are included by a source file must use the following, +grouped ordering. This is to improve readability (by making it easier to +quickly read through the list of headers) and maintainability. + +**System** includes: Head files from the standard *C* library, such as + *stddef.h* and *string.h*. + +**Library** includes: Head files under the *include/* directory within + UADK. + +**Internal** includes: Head files relating to an internal component within + UADK. + +Within each group, **\#include** statements must be in alphabetical order, +taking both the file and directory names into account. + +Groups must be separated by a single blank line for clarity. + +### Avoid anonymous typedefs of structs/enums in headers + +``` + typedef struct { + int arg1; + int arg2; + } my_struct_t; +``` +is better written as: +``` + struct { + int arg1; + int arg2; + }; +``` + +This allows function declarations in other header files that depend on the +struct/enum to forward declare the struct/enum instead of including the entire +header: + +``` + #include + void my_func(my_struct_t *arg); +``` +instead of: +``` + struct my_struct; + void my_func(struct my_struct *arg); +``` + +## Making Changes + +Keep the commits on topic. +Please test your changes. + +## Submitting Changes + +Ensure that each commit in the series has at least one **Signed-off-by:** line, +using your real name and email address. The names in the **Signed-off-by:** +and **Author:** lines must match. If anyone else contributes to the commit, +they must also add their own **Signed-off-by:** line. + +Submit your changes for review at the mailing list +"linux-accelerators@lists.ozlabs.org" targeting the **master** branch. + +Or submit your changes for review in [Github](https://github.com/Linaro/uadk). + +When the changes are accepted, the maintainers will integrate them. + +## Library Versions + +UADK could be built in dynamic library that is only linked for execution. +Because of this, multiple different UADK dynamic libraries could coexist in +system if the library versions are different. And application could link +any library with specified library version. + +The library version likes libNAME.so.{x}.{y}.{z} + +``` +{x} stand for primary version, should change when APIs are changed which + making things incompatible. +{y} stand for sub version, accumulated for three monthes. +{z} stand for mirror version, accumulated for each work week. +``` + + +## Working Branch + +### Kernel Branch + +Clone kernel from [Github](https://github.com/Linaro/uadk). + + Current working branch: uacce-devel + + This branch is based on current mainline kernel Linux X.X-rcX. Patches which + are under reviewed in community will be added into this branch. + + Release branch: uacce-devel-X.X + + Current working branch will be changed to Release branch once the mainline + kernel which current working branch is based on is released. + +### UADK Branch + + Current working branch: master + + tags like wd-X.X will be added to match with kernel release branch + uacce-devel-X.X. However, UADK should be alway compatible with + former kernel versions. + +## Main maintainers + +Haojian Zhuang +Zhou Wang +Longfang Liu diff --git a/uadk/docs/perf.rst b/uadk/docs/perf.rst new file mode 100644 index 0000000..78c6f7a --- /dev/null +++ b/uadk/docs/perf.rst @@ -0,0 +1,123 @@ + +App: test_bind_api +The test app generate pseudo-random number for test so no input file required. +Output will be double checked with inflate, which is ignored if "-o perf" + +para: +-o perf: ignore output check, for better performance + non-sva mode simulate memcpy output buffer +-c: number of caches to run together, for batch processing. + + +1. sva mode +sudo rmmod hisi_zip; sudo rmmod hisi_qm; sudo rmmod uacce; +sudo insmod uacce.ko; sudo insmod hisi_qm.ko; sudo insmod hisi_zip.ko; + +Conslusion: +a. Add memset (hack in the code) to trigger page fault early in cpu instead of in the smmu + Can improve performance a lot + + //no memset + $ sudo ./test/test_bind_api -b 8192 -s 81920000 -o perf -c 50 + Compress bz=8192, speed=1942.876 MB/s + + //add memset + $ sudo ./test/test_bind_api -b 8192 -s 81920000 -o perf -c 50 + Compress bz=8192, speed=7002.958 MB/s + +b. multi-package -c can improve performance a lot, best performance for 60 packages. +Hardware can ensure sequence output for multi package in single queue + +$ sudo ./test_bind_api -b 8192 -s 81920000 -o perf +Compress bz=8192, speed=556.533 MB/s +$ sudo ./test_bind_api -b 8192 -s 81920000 -o perf -c 10 +Compress bz=8192, speed=1381.276 MB/s +$ sudo ./test_bind_api -b 8192 -s 81920000 -o perf -c 20 +Compress bz=8192, speed=3134.403 MB/s +$ sudo ./test_bind_api -b 8192 -s 81920000 -o perf -c 30 +Compress bz=8192, speed=4316.537 MB/s +$ sudo ./test_bind_api -b 8192 -s 81920000 -o perf -c 40 +Compress bz=8192, speed=5617.674 MB/s +$ sudo ./test_bind_api -b 8192 -s 81920000 -o perf -c 50 +Compress bz=8192, speed=6715.231 MB/s +$ sudo ./test_bind_api -b 8192 -s 81920000 -o perf -c 60 +Compress bz=8192, speed=7245.201 MB/s +$ sudo ./test_bind_api -b 8192 -s 81920000 -o perf -c 70 +Compress bz=8192, speed=7271.500 MB/s + +c. -q, multi-queue has no impact to performance +$ sudo ./test_bind_api -b 8192 -s 81920000 -o perf -c 10 -q 10 +Compress bz=8192, speed=1413.388 MB/s +$ sudo ./test_bind_api -b 8192 -s 81920000 -o perf -c 20 -q 10 +Compress bz=8192, speed=3054.980 MB/s +$ sudo ./test_bind_api -b 8192 -s 81920000 -o perf -c 30 -q 10 +Compress bz=8192, speed=4405.628 MB/s +$ sudo ./test_bind_api -b 8192 -s 81920000 -o perf -c 40 -q 10 +Compress bz=8192, speed=5611.219 MB/s +$ sudo ./test_bind_api -b 8192 -s 81920000 -o perf -c 50 -q 10 +Compress bz=8192, speed=6560.715 MB/s +$ sudo ./test_bind_api -b 8192 -s 81920000 -o perf -c 60 -q 10 +Compress bz=8192, speed=6812.435 MB/s +$ sudo ./test_bind_api -b 8192 -s 81920000 -o perf -c 70 -q 10 +Compress bz=8192, speed=6774.040 MB/s + + +2. nosva: +sudo rmmod hisi_zip; sudo rmmod hisi_qm; sudo rmmod uacce; +sudo insmod uacce.ko uacce_nosva=1; sudo insmod hisi_qm.ko; sudo insmod hisi_zip.ko; +sudo ./test_bind_api -b 8192 -s 81920000 -o perf +Compress bz=8192, speed=2203.808 MB/s + +Conclusion: +a, Already add memcpy when -o perf to simulate real case +If no memcpy, speed = 5G/s +b, memset, -c, -q has no impact to performance + +$ sudo ./test_bind_api -b 8192 -s 81920000 -o perf +Compress bz=8192, speed=2294.555 MB/s +$ sudo ./test_bind_api -b 8192 -s 81920000 -o perf -c 10 +Compress bz=8192, speed=2274.646 MB/s +$ sudo ./test_bind_api -b 8192 -s 81920000 -o perf -c 10 -q 10 +Compress bz=8192, speed=2253.909 MB/s +$ sudo ./test_bind_api -b 8192 -s 81920000 -o perf -c 20 +Compress bz=8192, speed=2252.999 MB/s +$ sudo ./test_bind_api -b 8192 -s 81920000 -o perf -c 20 -q 10 +Compress bz=8192, speed=2244.004 MB/s + +3. test.sh + +#!/bin/bash + +block=8192 +size=81920000 + +for i in {1..10} +do + let "size*=$i" + echo $i $size + sudo ./test_bind_api -b $block -s $size -o perf -c 50 +done + +Conslusion: +a. only support 5w packages at most, since no enough memory for malloc +b. sva mode: +When pacakge larger than 4w, performance downgrade from 6G to 300M since page fault happen +The reason may caused by migration, known issue + +log: +./test.sh +1 81920000 +Compress bz=8192, speed=7033.219 MB/s +2 163840000 +Compress bz=8192, speed=6593.940 MB/s +3 491520000 +Compress bz=8192, speed=6595.981 MB/s +4 1966080000 +Compress bz=8192, speed=324.536 MB/s +5 9830400000 +Compress bz=8192, speed=532.281 MB/s +6 58982400000 +7 412876800000 +8 3303014400000 +9 29727129600000 +10 297271296000000 diff --git a/uadk/docs/sched_diagram.png b/uadk/docs/sched_diagram.png new file mode 100644 index 0000000..e69de29 diff --git a/uadk/docs/wd_comp_async2.png b/uadk/docs/wd_comp_async2.png new file mode 100644 index 0000000000000000000000000000000000000000..fa2a45d14c4089c7d69feec498ae197efc615a75 GIT binary patch literal 14788 zcmd_Rc{tSX`!_tKMG7^d>`@IR5@PHUsccz8mdaMP5MvucQOdqEmdd_Ic4H9Pcawca z_I+eu$9TQf<(v@at7B_C_J-@5 zNyYhRY&?ryZ#a%9Un_E-j92;?&nCNT{;}%ZfL|%c8-{yir%sVHLx*?A&dIi$`oXxV z7A{7O)!lbwu3V?v+AY;>j!6oOEfK>W(p}j>ISXM6-PEzjtrj#UE$gE?kc>4{Wgh$$ zAU8?|fk?8$fMoP=5(uQNjvNAcDXR$n&2IzbjSqx^kG?4Ihw1;*QV(UCfSN%G2rKQ` z!JF-!711<4++h8%Py1CG8&V(6|K`sjNloNgrOFDW)w+(5u=$uS2Bl3d79k@I-zX8z zJeMk}E|GhKBpYXd3f47~w8!D@g^WY+%8BeWzcbTr`i-IwwbH$)>}y9gfxgveKIw3b zlHqJ#PLQoBs?)`4?JmS+r!QV#2@fB5mln(<%-R0_L`;;{yiJjl z^IJU!LiaOeH}&t@C&ljQzA(;04RzW*TYj3hsEm#gK+Ht>Yow|kO)bb&i@TifVu>{L zwhny1D|yhUNqzNzgt`s7!*z`&1ya~l^IyL(X)&!aPvyO zgt@5*Va);td1|PbW0(J|TXrs0)lD}$xv*u9FVwpL8;ZxK;s(2x8<*A4A2kGc$eYM7 ztgpLHcl>b54Z*_vu`>-B5-X2a#xCX0>tRdO&@1wn9*ozW$2$45h$dg|o4TXD=-;ZZ z4%=16>cx-?Wfk_Vdh`)J^df8%oe^1VwsW3>X?nUVimI+~cfz}$<;H}t#IlW$X|+^w z7sc$-A>;fXt}8nX)74L~3GJH#yH8&Wr$sycWZsptQn(yrgF`U(#1Orlm!O+x`yx#fPi);WP-Im#*D_macEfgeiKRl{ zS-HhI3b_^$rz^F>INe6rBgbrs>iW+oxbR4e@q`kxjErWrtP<&!nfsVt#<9AV>77ug z%4q0%`B{S5>Qw@lx_S&2f1|5=`_Wrm)YGt|NvZc*7X6pM%RTM9Y)knqBvN3LQQls` z^)(72`H;8db;mkt$m7Fw3+Hr$EwH&0%iTP8!H$7UCY zd^fM{1bD8z;6SN;{Us&kWu+z!&!Z{9e%LFnJ8@1j?Pa$@LsE>Jmlp$`?aJY!vY3RF zAQ1aKmvB+c88Sv{NG3I5$`V@LcZW?j+rCGt3QBzFW6=m$B0D)w_NWC~hEXBh)Ek{& zb{#XqEXM0CjFXk~eA|k$4bRr=P3jPqeYVIj$G-R>gM5_-!@x*e>UWoQRdk~#SdR6gl|5p z=DCp;DBXpfn4vhOxb7}qv|HOaorh0(&DXUvRXF6k{5_!qFJS1VIy8V-n8=^s8NdJg z=KHpiC%ni|9%*UeqMA*o(rH$`?x?v&VTZ4T@k~8cN)ohfj%oTXon}{M{Q{9cTCiDn z4PH5?Ih8*;M9htw5Dp3dx?^v#Z0Dl+zC)jkY>X`RCEWJ=}V4pyX2Th%y)}7BGU!w^?!>LI7)U@yIzt0v6it? z#;)55B~cCiFO$CYp8}weH&?*%){%20{r(&!4(lO$#5zAr=wOIM{2V7!$mvv5olAT! z17i0ZPOy5Je<+fHqn_)(ISBt1*u|(I&c$0tA=RXx7^)s~lf86!5_0bZ5n#9Xmw}(oi+SC($Z4807!v zO=z1rvU7M4hiYy<#M414PBnA1ng?FZ$~@J*b{O*f7GDFOj^R5qv+5Nj352oz{bCbs z?{FWzHBuh}xy}DcG*70Ws6h6A=1~Q+GUDb81ua)ko{9fbTNzJkpp#>PI1NO3`(q^f zF&~92+l|cgwr>8+Vrl8=Gt<*5&iHVyd%j)K4@n@@RP9ZApCb>mpGy9ol9?G=sH&o( zqN>VHv6#)(=+RXwO#+eOj_SRlm}f9jlPX|8+jC!AJ8ku%fC_=~FodSq)HqwH*~6DE z@B3LnOVkxu06l^l62C6P=Uih>Yn~91FRQB?a|QOCn+F1^mgmpYY%;Et_0cy|)6|T9 zB^frTbO`eJJlNkg&)`XQwg4@Up1BRFmc7JD$eY(-?{%>EDa`jCv@=3R=5-m*hUUK> z$rVUajJZs>N3@e5fxLMK9(mB>;rPzT%zUt9CEk-V$ZZgW*kLyCidrtP&6*(2;j1n~ zm0h>4phX`)!h$zKz$~ovGA*;i5DDT8gjJSw!sf~&8;{x1p*QS)rq}M9UV|OW3p6kI z*}JM|aMX03NCNpx-8>ogBxG4kiQ3pnyv@d=Yp=k9JBdJO@VS&+-^smZZ@1r|Dv&5hwah?-Ik z8`1{cN0CF2>igoK`lGGNds9`DsU)@+8hJ1ea||lIPBN$o!-VFGMhYzY3y@p(S`mCE ze$d%waupKqSv+!0mw-bjE5()DPPCl4qQP&48?cL&4Dvt9;*z78t#>-|c+Z`Zz+^uVj}6^&!}$_BMqpN!FL{C4_Vr*+Oi(W^1${p;Jj>XZRhDtRJJ}3RY7DUip&b zP=OVm__LO!v1+zAFUA0mG8n3Ge@A&Z2` zCnHk>tisA!x4p4sq~GEahYpO7Fz@}Dn=Ovq9C-fqq`vFM*yhTNPX4noG#4)eoTO&I zWDaeeEHLZNinc6C1xB9h%V*$yTx}AE93Les1gF-1o8@XPK3vznR}k+qLbf$dc11Hw zbodQ>lz`cI31P_JZTpFxUH)46A^4kcq}_Dal+Tr{NjwI_hcCS`%n;mshKIa5;JkF- zm#6I6j`cwovkd5dcN&+Y+MDai4P_A$r|7nLVMX&d1?Em8jOIJg!A>K05JsmPGUx>m zD#jbHSW*ySC5PDd`xEe#FDm}|YZR;D#T0Q(BcV%jWQW5+qg$A0q%=oC(}bvhRM zO=p?$@$#9yh)`2xOts%>!N{(z^ek`E@r<2NQn+w&70o31Scb2p#x>;q4OmZ!cD~uC z)vi=bRyUvi#A;-NbpLb%VOot~`E1k3>4xt8^r-OB267Zz@bE#oUy_Q3yK~)Z&Y(xf zOc2zL3bdNvo;F&Hb^5$%6ReHMex{p-bNYss;#|DzM@Z&o%7Q(0v1XK&e-jKxygi8Ks)$5 zEpcK~Rgmi_+>}Q&)@uv-Ol9i*bpGu%M+((%Y5IP>$(MpoZ{a9eKYu(o_*mkuY&0~X z0~*2jod>O}D}Ixup>ey=)Js@oXJ>63w)~-(uk_xz)nG4M(qzV7Ei^`jM+ok2p1kvD zr9aSDq(9YJ1;&CWimOV1zQU=hR3LJ;Q9Ip=XcpHHZ)c>3UzbZ-M7d$#zR7c0%U_vT zx@c@bh^WX8k68^?-$J8aDO@-l((GdvEN}BUQTo{OZf6M6yEr_p@|-8 zf1&hWGRHz6UQ-){%ji00IXU@>&$_N(65AN$)sncll*lL>U6(F9(Ll~zcArI_#U>{< zV2;ALFBzVgGT=CHHfIT#(9yUC3d$E%wHKl8_(q!sLSS5@~7MWSs581^h|&|j!JfMbIpM3!ZBfD&Z~@W+dsqgoKl-QbqXzGL>+A|uTLB`a$>%2Sf{_c*-a(B zE@_O2TnAxpu2o`pdo)-nj1%9RM4-BQckC@Jc6~1fFRtO;cp8H*DFmI_T~3x@vg^9f zQ@;MVfndUb7I4;gcn~;22Drg~wIi=)y3u8Cb+)>-j zktaGR)tV^al-1BePQ)9dkrPg&aAHe&Y`juv$$6wg#pc$sy8HNW^(-4SuQ=AApJJsO zx}L>w9d@?uw!ZwrPkQt<=f_C27D6e8=yrH?oyfwI-s<{^wncdjAFsb%raw)=jOj^{ zrM#~hM^FvE>((Byqu_3fuZ-*d-hE3wf+6Vb@57-57oee`$xVOq*rpaqWM8utO^j^| zd^}-b5P?VjcugnVSS}II8XBY{6zaDAmBnymeC-sdgxv3O7hf1#%k#z2>j1q~gf&vE zO-#a$u40eokEh0O9WIlh?Cj5PryJ1ay&E^(+Cr`}l|A8)FO6wWo|>VJ$-m%xRwXky z=u>I>#lqskrwyQYJEv)^F`usHBl{Czb{<9ftkF3nXr$%#Q zC#Xha{Df*SvKk@$GSABUwsxVSf)ch!+0oa<=Ofn#0?FE!Z8prb&`x%{#2wugDG7;) zow#%F&+&cRrmCe9TW$lX8#PAhD)EIQlu*8vrON3XvU9@NU7Mh zpuO06zROF~N2mtYHG zN(LGsV)pX`y(`jpdz)HsjHi&N%Gr8&TdC}>@$TqviHWQ3T9L%j3`s1I>qoJ|Orxp> z0_0uhPRBG^)qj`>lsYL`i~JquMj6KV5*6 zj8$;Go}3d}_*qOBLM**mSrjc2A!ACZQF`Jn>ZOfA*v(~o#`X093ZL<-jOhjW$C@jj zh1a}6y?lIk)>*^_JVn#2Bcx$rb}Gsf%gxaBPnmubcjd81be4f$wosIu!y6z1Q4wxx5 zoFtL_?*2Agl*fG}(tqt!Rys>P98R@Y)VX>NMVVz4Z;VIB7@0g{5qK8DjO;}1R#eDu zFm1bD=M`a{TsysFtVbR%3NkYLPZRZDA|t|?Zf-9=nn$sY!Ic7Hpbl==+sVjw^d3Wt zgqn33=x|EsLc|!C99!UV}@4S{;<`^IZDRD-YvP@t_oxf=l@UV2P;r_&i7g$!Tc~ zph%NqE@AhH`_Fc`W67=GjtRfXcXHgw42@Rr*M2oVG-woo8hQm)i~uEPx4s)1RQ4Sm zDprcuo)1;XyrYfm6%zsOW%!Z&*e1H#Lp#sdH<(&z^n=L9bw>#!R`}%ZVQj>>@AFOb z_wfv48G3pjZ9Pg#N*KTtM7 zSSDzuHYY!+Dv9NT&geA8Wn+;s^rYpDGi{`~ z!=S|8TA6_{g!DE?zO)(Om=Gy-)~N_|&fI=rr+eUp4!z{H?n9W}EzG^UcjdjQ7nLs$ zTFYd;l`tB58C0=F>0(k13hF%7WJMO&^&jE-uEhqG9w!-YkPS{>Je1!B5?5_+f77Ln zYELTho^;J@5T_IqZAtMA4Ia}c`H&6vo2zpocGGH(7QldJpr_TbLXYX3GtNtWNgHrR z2|gAAddb!}*UePJBmQEm5zv5I#L?cXLtU@58pE({76&(qAlV22`uURCR~6?&=Zn~q zqgGXqFwap=?uo(@!T@JzxC==H8IB3s-kqc^HtYFSdGsY$Z`$Vc z8I3S0!`&}9jg5_UkOnbj>tk?Q0d9#M@N`-Rg>BA5M`>E15d_LuhvB!Co=4+eblkBq z-&yI_Ke~55E2V^Tvw|=MN8pI)UNYycWqdL{HWmZ= zxbo0c>S%?-UnEz_F6cxHS%1tk4~07DRHU||HC!{iEcY#Tjt@jrb8H$mvk*7!!gNvL zJO!}X7$@Qd@4dz36BlxJj}Fq0uTQ6E%lgvWjra;48Js@zV&PJ4^>q@EIvm&L2N!eF z(xyW-^{j13@rTy-B`HrPbGf2={zmk1Q}=ij>!d84FgxE*dNM0iFg@!atUVbo=(pU8 z+udMUYU6*c)}Wdsek2H-0Qu~0d7)RP9@+`)4h%U(r|-gRGg_CPT`oMSksXgRXbigw ze3->$!QJr8(nM>xmjHn8PZ~+Bctwh1w&qL!)A%Kp8N;syBR4d>dd)A#ANH{E02iz* zuhfcyzeod@QIZ8>&kw}87xou#R0+zozx}Cmh(4r(NN_gm0e8l-WGZP7r!ecbtbTK< zMOU}H(CIJ$P?rTB$~)ceG_jwA(!xB9t;cl;WT z2>wTZ{L_|xQbpu^{^Ap?9dLzXn8tV!p(pGvsx&cYF#_>Y%ex*n-~bufQpy95f9X9G zpxzAcsV0nY94=o8GZP>bMmY! zT{)+Z;(I*(%bj;W5)U$k_d;n?AT%PRd2RP5Wy#_1cFE?(rCUntNgTqwu4a;+LQ2ZY zH9}<%5rcM}NeZ^z%nthr20V76#51oF7@hWkcd_dCom;^acp4elZ;7Ll9NEhvBxDo= zq}O$i3|96UC=NMOWUMJ_nPl#8{COOgzl~pn9ist?A)eoefF^8Py07dXz<;*GhcgEG zGK-Y}kjSJpc3g1S)7AT0ZL^W$lKsL~W)(u4)GK^!y z9C{5G9ImUOafxT^<2&x_z=Mu>7SJx!9yvH>@Su2HSR*KZi$5pq=>t^wyFU)ae#ksj1vq*p-DJoKbk-}#lM!&B5JY7Qj0sdg_ zI_~iR&A!cw2o+{4)7YJ@HH7;3I#U&+K6NyzVoT>WQ?9E%@8pp$A$T!U96bzn%;|M1 zQr~cOS7$bWf2?T4kB=(5Wco7rkG^=qcbl@;qz8@!0$N#35$EIW?~u{TRZ*!35R63K zwRqPK&OFzw3I$te8U6;e22GTeU2H{Z{t^7m(SM?k6|bewzWal9L2sKMD&<)8->?;v zY9mm4focGw9)UhEpuQOxlH_KAA>->Tq@yjV)@K03@tL#?6x${zaP@+g!LkiuCS~>E z`N7^axkWlKZXnppBkj9L1G9ruH3qv^@LTnQQM% zf=$xX)6r{8>z3C{&C2(-1d)Q{bW7S35?*Ogh6FX3W7&d&1D6q`YDOMa;Z%xry5;dJG94W7 z<27&}!^6T_V#T%qz-#>slxlYqMe~(7=zafQSm?Yq@8ffPY87C#uN=ou z@BP=>vqfNX5bCW~GSX)1^CQtd{|2Dstbk?Pe1`!Sko>>&N*KS3f=> z&Y0e6c{W*a;Ii@LLi$UGC=t7oQR##0KDndL-F2DI>=Q?tOYm$dQKRfs9 zHbg<-Bqxrfuxea=a%$i8C84aamz9t+)oDgt2X1Uix^)G17T_;EpPvlo!|f*9egxiT zw(kBG=$M>UC~7%S6ct6UHQAkwuX;_PfK>ap+(VGjXlRC3UQ$`vc4D|*(3p;8@mQ?{ z(R%fA;J+2{I22%|_#6PyarS*rTNVL$t)ii^I-A!TrOx&*p-zpHfqWT zt2zaYH_UrJ%DfxBm=9(ltH7tVp{ig=Wd>^YJ)y&T`%)3)$Cn1PtrS^BVubC|^00xBRqm!CD)qj5HkS1(?? zCUwyk2_smr>WmljD59jWVgoK8(1Eqa(_amVs|hL-K@ z=UP4Mnlmj&E+&Bxe=nR{x4=A-OFrV-d1r)|)q^%yq%G;4%z5;hUS1^_tyqoL1&%+u z@VE6@t5622PPicUt#f?FD7)`kHXOSE=2DElF_#dm7?jNHGRqy1Wgfsnsf9`L2_mmWDE-!{@~BY>ty9CMLE_(R!Cf zfVsz@=zFriuhgw*Xr259VV6jlK-so53*x!FG2MF3bLT*FHx{aCc~|L`jf*+k?e}L- zg+S#auP1_2+4HBne0jNiQb#N%Kq)P)#^7tTr^%yzD52zIY`nn>NTiDi{n91^O+`mZ#PL@!r2#M?u_!F z_pP`8o~eTX2hh-HJ4UwqlV$gO{~9_r9-x|-^%|Z8SK{^txD8F^;_W>})}H`)IMtCj z?nH{W1K<$=P4o)Pdl$zVjUH{U|5QZ3JMbNk`e0Zz4+UzA(sgG>-=u)~)Zby~%?%he z=+3~&d*yKj$1%1Q0E)Hj zKIy@@xe-~uCK>)GCc8gwA|JiB1171?Q;FeVVE2vos&<_j>tCMRB+*ggG5+g;gn$i!hF7e}rx2Ego2f zyVrk1xF03E_P5smpK?$9ORjmMJO4lK#;Q2EeO{pa!?(m@v-V>eEIz+7oAu2Js?@-f z`M{q$__dx(c)MsJIeynmsNw26ZkxWGZt5I~ns zRdbL%As3W!pQ?f50{|u0mei3WbY7?@Z&UeKR(u0(fxZe^96s7Lk2Us`cu zy!s9Z0(bSbi;SD;O{9pScO4s;PTu=leXvlw%)uJ;(UzuE-` z_ea>+e-3ty=@m^q$EkW*g9rJ^zf2()FDLua51x(_h5|s%=BsC*cEI@39l3fbK)1e$_PUfZV{JVPo--|vk za*Q+RK3kA)Mb0y&Uv>|W419n3Uk{^T|8?EIe_S|u<}VfhM?@b$P^(<{bnCAZW_4#f zcky3(1AP9!tgGI0aXI?Sf2sICB6<;lHQ`VD@@Hd+n;wTLK=nH!%FlG~S%O|{Ce>j` z;}lHpA64ihx15(J@9XO7YHEh}^?x?hdX|72JuW$G9m{$l{m+&0piG`p0`-Z2fIu$m zZbL4Y99o3t4Nv-gfqJ&59IsP~qlF@XqnXzFF@Y?cHGja>8E$;0rf{7;t>@>)2a=I* zz97MsmFs(jWbGv7Tah2{3RI~O3Tx^nz#pGTIYA5e)dyevH~cjUJabUwvZl*;d&>c4t3 z9|&->ooPqmxD1^vnrv8_>aEvh@Rkn&P-Xc?UH4eUmk(s80~~=Gn!P3Eo&oDKdy@QG zbI4<%`##X)=6NtOs7eW!1aAEn;|KKp&ok0gi<>jqpnf#~aj!+XQ(1+5WzihT;X}eC zwokQ_ry{TRX1+B}WEOJ*Y$g$j@M->#U$m+k4?pJpwYBb9cx>?u)tAMM z^t30hH}T!qsWiW*{qP**_2q;oc@LH%c=XB~fJ4s1lt*n`CaHl#^uySd?>-xl;yChR zS$X*l;3yu~rmR32j8d;m?pkXyzZ}D*PFL~Gun?E*)b)~xi$Nk>gpVSgwIE0W4wm-) z`{%uHZ>y+nKgUa1{^LqAwI(k-H7~#`Kc1V;2c*@qy1X3`U z%`&}W6S#%>G!+-7gatPF)g4oCEm5U*&9~FLQa#oBHPVzqwZ#j?bES);tc$0e6P{sJ z6ohW0OXUe4zr4oPwBWzj0+ySl#aL*=N)Um-)<=k6bh#mdl?(6l*NYI+=}TirqlQ&BgsleJbA`^C%nel8B(4 z1?@+~(&03NMak=X*Wvt4KtlT@7XW?rF`1-wz(A)UOJlAtMa*tGduBzgyBL|Y*j7-o zSSpMyjgE4Sj7`(*n$Di{v>_!IFOMsEQ4}j=v{L_MrR4gI68ZtM_)cc2W(qwMCD(chaX0mtZE3O8=!g-gna0Cl=0`XFa0>THwPmAwbBQds;cwnW zGw~N=JNDs9*5bHonrhf?1IZUaY-uvV`73f!aAnaYPHRnK#ek4L07?A_t_A%jbCT=qe+hQ?+Uh-QZ2vbb43 zq-{-+TeY9Cv)}BWZ&sQdab2?5$%!KyC%cXh&)2|jYa$f}gM~k@udYRUk9f~yGoy?m z%LK)Pw8HKnH580D=FMi5a_%)X^ffJ}iKt6d~kABz9BaO{h$Uvub*cH0Tx}gh$BtySq?;A7ocl5xp z_s90h4d%be4V{48aEU6w&DjoXQkI|QPdG+eeaVHOP^=Yr=6|xyZXE@Z- zQ5eej7kS~Mv%eyF1Nmy#)b1fkzna~jxtp_s&wiY+b93U6TFC+=7Xd&LPpjv-F|EUp zB`)z?#wwxkQYbO&{8lvSM7gI#wjDu`Fg!{|nZ-+%E4EN^X#O(I85jp}vY@+${~@V9|oF8OP_Fb7N5aUb85yY`9(&w1FQI&gfdIU|<09ol3+Oty?h zGCWp&2z5EpF#C38*Z;@c+Ua++XkN!~Ms|u_lT%S%FRB!BLPmJ#j#$tfq$Ju|#3-5L z5Rc%AK8}!`P^h`vd1RHDzRHxZxxDol+3WtNKMDpyWO#E8+*C)&R@WO(dfqrLgSgZ> zAbH35kzu9lZN-42M4PYiz6Tks&SS?9#Y(k3<|W1O`sN-LGw|>h6I_b<;K|ou(0-hq zVpYV(Lv$gW;eRW}eoA}K)kE;%fPvQkE4#mF5So<|pfI&8ZZ2^`3>%p(`j%(E+y_6+ zp;0}nm4gq2j(!$)D}DsdU_bL7h*dj%AjQWC5(6H@E+i`KcsMj9Bt&#=z_w+vcp}!h zU4{m0C@)YK`^M}X#fuYcFnbG&G}qTsr9 z9bPF-CDv7r+}c>0h#q3xKNQlJY@HD($)tWCAD=zc3hcetYRacD2wKkKF}rV0v4gf{ z31BGpQyoTNG8f&Un%%{tUoPq#J&e`V7Xw3MfMvKYn2x7{7%!GSvRs(4>Wd>#KK7-+5^ zfqG2=tqQO<1`|r!V3?Bl$a}sUiOD!n??H`4!TSJUW=}cq39y@~J^n8Z3JO}3t1XLQ zlBo@5xLOuGc_oB$!<9zv(%FTtRN*FhGq&uoW1csDDZ4$biP;Qy+Xx4QS6Rxo?reQG z0Atl3xz_;*V3!&X9XZhx66-{FRok$@Sgs5~OK0PP2P%Nc^aHobq%N_wfjpquH9V#0 zYR{9PK(fsF((JDtvhUCSNNe>)v7YEV2Jw-vL&bx>8njrpVM-!%{J~HmU=l%xg&_dq zHniIt8I67OWyp&gq;cVlBYZAp{NC6_1ax2Y_G05=4(Lr0ILC>kAykE3EUT#<9$7yP z=53mwt^}CN;_T)>XZEUz9FSZQKWpf~NO>O@(f$HjQ}|+5YO2=f$29<<;DA>G0+1eZ zMg6TPfNC@{wey`;rWq`YegK+BFE~B9RfF;o{gM}{OH3HXwLSc$i#zoj80>OpUqkGp znDv@rJo?-efQ3x8XTTN;onjj!0MK3NDa-j&6lT};M{u(6k=eNIQP{ZX9^aa~Y@w>5 z;clwL#%S}4*prFzq-HmieC;~&b!~hPx zul3pQUf1p)yT9wVf9*e9FvI)2=RD6j_j&I7K9Q=*as;?kxM*l-1W)84>S$;;9Dv{V zv2OxDi?~0TqoFaGJb^sc^funj!h7*l?y5H^yr20FeH>7{*E5RfDLAs zhhW3txWphBeID$8@Ub%s_z@8|V-L-uU*_?h?d3#EOUFBr@EDP80b&rpPAmi>3w$1l zon9mh1~U$y#Xv#_wHQGOAnO2Gu+-Xz1b833N`eu@;5I1_vFy^zNr1now_^hHFBOl- zL;4H_i9vT*wvV);VB^0pF@x-PP`URP+%a2VJ#eaCzI;$ zn|X%T!LCR&O@)xgh!CFIwMRdM%xMe%4xvjCSr6yT!oQWx<9&)?d&AOMJ!dW?_xo#3 zDv;hol7^bw1p*(Wa!%UaC!?Hw8U4?^Z03nxDoU?w^X~gR1lj86gz3M3$$9;r;Blc# zOx6Ov9zj6=V+B^_!$+r;#V;FEW{fhjaRuZaUFyF;DN;_| z8orFxx|d6O{_SA|?2dCyyiT%WctZ0GuRu_yW0+7>As2^5Y1P{ys!tz6r2{m1>VEJc z{i||3(0xDXz`D!6uHN@6Pq&APX$P_<_P+m}#%Ngx_wMr~{uiluCc9P)25+TC^@MN& zA7FYEb;c|@>^%Dvj1qYW8Y5WtUcK*KNhQ{A#dAv8nYz(c{eb-V3d{x?iIQTyef%lt z`RsM5xMHsRP5;Ae-Pew~%}@eU8!w@Taz_&5%0_Z5twzqNOuSiouCQ1;P3g>)+AD&U z7(%Fb1GnKkj*e$#*SE2yUL5idYGTjy?zm+QG3RGpaAQF;flync{I?& zE0i<E(SW_`rYPdOH&uPp*31=_GyvA~Auv1ayyhSpHrKc_0uMktZr`?mnUHk!2zV zzF}szyZx=+>8iqa60V~S7d6hHu@Y@Els|{!{z15m7MqSLDS4dCY72D|`<&>ThX#D< ziqf5Yks4`q*G7nndUC-fgb8euc7%U*d_vKfU>M2QIhFa^?Oe)6wehtswSe&70%Xmh z3l_CapW}*I3ssJzn)Ug}Fg>b=ZBJe&Ke5cSJwiBGy*3Lb3I0<7b;y}lxD1Ke(VkhS z;faWmV3y2o2adz@#gJFl)QQhn!KmUMYv?DF^5@b=W`n&Ms-I^bsfjS#CaEF1?mTW? z?=tt8t)Qfmkof$pR3^6VZDRKKa~jSJVx`tosv}2=!RI5+b3PAv&10FVhg$w*SNhAD z=x71XN4r7pi$#+iDfIOK7nl7m63$o>j)BaSY`e|-Bn*_m-aD>%zuYODiL?9}Euy`8 z&SCAsT<*lbvw}g1&H)NW!FzJyr+ZkmP2Q(+9D1<$T8nM5tVmLJ@Zul@_Zg{*fp(9f zwcq&_Z_)h6_8loh&857aOu0VW&34B;agY>J7sBme;f9F$z!|VkH0!9OV0p`Up)ZYW zrmw9XTEz-0%Kb>HeOnd@)6pHoS>9cA(QavBg{kPbu)fqIDL}6wKH;`Ff9;P{=cQ5e z4_Z7NMr6ysv+o2Yu%tUkuWWIrqzNcoh|K*n6r`L@@RKR(*@V}EQ373py z8~J`cRAEmEADK_$cgWdWop+#eqIIhK?37}n>4{ZiQiO4Yx4y+@c5K(yBN=5ywR`3$ zr0guVAKRlk9nJ_w_LLVnpYdK`G=7rGja{-G=ug{rsPUugJj!+03a0y9#ic>OwLg8w z&_Y|uN~lj3h8u!4+5tK^Tk}lH~LO9uUMkl%!JYE##p{$3a1ZhKlkcoFNyDH(9TQ+tXM+2 zebfs__`78+m7sE_h?(+vXr5Df|HTDz#AEBT&({0G+jJ7etGy%zV;Z%NM*ccYZNhb+ zvu>%)@wf3bq8%pOy5$J3*7K~zfN7Uy<(Kex-Amok3~g<}w@zEJhap|XfgQ1+a{W>RERSX)}|e63dW(hm%M3s1|?Fzk}wKt(NfMo5-2 zJg4PL96{vrJj{ixtb9sL=FquXiso@#XleF6-U>KBS=_3$8c4C|jcfKnu36^H2Wq~fS)sZuJ$LZNSv6X5CcL4I)bPB%MM2OeW|jxpDI2* zo;E?&4rhvL)Hvt`B!M}!iz)BhydbB%@H^RA{34}Rq+K#1d2NWdve4jB^!-~)K;zGs zViHho*xtpDTv=J63%VHFAVtubk%Qdaq7o=^?zRTU^Ow?>=vNajoY3(xg5Tj`-KIhC ztPf>Ozt>$2Nqd*LND8 zcI@HX&K>HNmQR|k32DXNVH_?uJsNR7JF?A(Q(o%wiI;@r#Bs3X%k>^I4ubR2UsTof6Hx!7XsiH3F#kpTFxQ1bGgfB;DFtRV4nhttmsf8Wq z8YYW$%7EbOtE<&EW9Ca;kqd$6yIuTOUlf;3Vjd-itJB@z+}*!8!h2Yu&nEwSF;e>_-rSc1^ah z&kR(6kWL~~+|P6OYc&ZmF_oa*(Y)W@=9S-%?@x0i?iSMCyLV6A?*uYAdNU|%bD=e; z8%@M|EGrj+o_^n!*x0z<)hcriVICTd&HZX?vM3@EJ3z%~gcCJ1@^X8+Y#F8U^y#W! zgFZZ-HyUo`78MOF0Xo(BPwu%gN4{-i3G~YXX*^+yqP+%mg-b1-7w5GW%S!pH5J{ z$M)3sxkkxsW~ofUw4bad+7$gIJoMA}TSY8<$~F@T?|phf!Q-#h_TikMrQ&ubux05h ziJQ}N}BXDwhS4fp2CGXDU`*jH^f_2T(@FZ!`*(VXXWB%ksBufEzZr-(zNG z=Hb~ZDr@N&Q-7;KHm3({V|NMPqj$hU6Mzo3E!G0)fkv|$!UL8PMTJfewCg>|myNBXvqrx>J6`4yP3d($(4R*iaxOV|$Ou5U zQH?`-b|7$?02`^KaH2%{vVb~{G~$7$gHPu4PO)|g)exkk`pGTRE&4HACqeekNH3W} zTp>TEK{{%sT5sH8M`8hQ2Y>V>CYnM_k+d?S#_+@w3KM@2UCEhjIBy8HAPJ5KSbKmX z0XQCfL`iVuAe`3Viw@P^I1kQvBvqDozKsf#AtMN9!jbm5g01rp=l#_wnvHqc!Q~1U zP(1)2%B=$Y{Ja6{!&$DY{lHq;1ls$7w)Y}uF6Cig|3;4>q%%J~%f^;iiS+}gr>AQa zDAfbgn{W0bAt8y)sH7RNs5{GspMK?)>GI#2_Rd|cuozfwN>MhvqNLzCGqG;DI8^)| zNl6TX+C}w^f8s@)!cqz2r0n<&XStxr@fiDHU<(q^is`BdKl_?=y&$E((fR>fHyb{Q zACx8PwuX-zY^?0*c@lF+;0T{hyiWZQ8Gw=V0ABh8-vqLLtQGG3EDdZfactkDTJ<}> z zswoS8zhnelt@$M7`g8c}#OS`$p%;^Fd706(xdCqS3Za9q%6(dNS!${M=o@b(@eHun z+egk-Z@%YsL;qZc5!o7QCXV>Fpc_D}P%+Z%_Ku#gRB-=;>nGky3hI?_IRdm)Q{f*; zPYyFKcft{8p0ZJFX-C}Y z{IWm$^45WiCpeEfE-!fk@yTvSpUVWo8=L)wQBQP_2S$9*?m8NuA8<&AIFU3PQD@6S z%V}aIhldN=PN9W+TIW-33oSA?+PjF=4ww(sm&e-PV8{5tP|Bl!9gY)fOuy#yFY*A! zRZ8q4!0E0|(G}x|pwodh7+abVgje{i*SN_8ofNY(5x<0j+I^cFI1(3A7EjYq#4+3F zX}uQF-srMDAGC_%XhdCqe4q20_hDsVxM59hetRAA4V@6u#hfWvR|kRMLBy14goZ*u z;$JLpVBssPG+<2a1DZiZD>s&nQJ_H`d_%hk*S{s1*&WpG%AUl*_6sipQr}Oi^un$f z=DtLIGNk%&OW7>&;)lhs>U16v&4uFVmu0;ILto!dMHq_sgH?j8Y4a^aRG+!`^JzCX z1*r8-n}#_GI$oDL1bu{(p?pn7BcVUF0{r3Sy2W2w!E&>V(9JT#`i@e68uzGECBr7~ z3SiyU9oc-VJGi<$@2*9(p^ZOT-nrV5v>zT za72`4RvF@a6BfVyvK2cVCh^h(1nR$&VRCy|fy#;$Vaw`_V=t-dG=J%-lj1tS;EO%V~b07kVH&9;=Cq3lXY_E(7s8=#s`} z0$pDanuF?WEf${~*UE{kd;I$tHH-nn5}h-t5YL-xGKOYMcKT?4BTadFB%b4&k6)OBa(sC;FUT{Ec^T3QY+d_gMRh(rDtE-Q7dp3Nv+AK;wQK^Q( z)q_HD@QxN@eR^%Ra?cBazchQfKPQRUO)vMyExG_y1@65+s)F_6*iC!7ltAgi;YML@>5Dw1gDx@CcEPQ~2>mj1_9`>+w4`t6lm&!V0;CSMBQ;aB zO++39;tT6RDweY_1g!?&t08RnWL2;_8ftc|52O? zA#dC_$1nWMFVBAnN6S~+O-e<=hm=C;DynT^6_!JhaENo@w4#*I4DnBidkBgiE}fgN zhIhfU{?86AyyNKiW=I+fQ#XY7>Ew_YAUw=_VW4rvdJ6!;T4N5$VQBh{9ejWoKPtf$VDpN-%U_k}MLri22AG8yf?y z|8$uNPYVNUkD9p4QWu{^&%Tq7t9SNBeCHj>xWbAFMvfX)P-II7_u>z>RI2OfK7gCS zll|Ayt-FL*3U$hiotlqRHUx<-)9?jJ_#SowjzoFeH5llfDFQ(4t)pCm{+eDpGkkRq zZW4J)AB(LCRLc$)T1?!v2l8KgOL$QnAtYyjmTzo1=JzjZ~P0C3gr?(R(& zQOiD}gJ(E=aa*+FzPiH@?`%~<&w+`G%^ErHSXPc{J#U)|I_4-x43sP^-zP-K2bPY%&-EwkMNhxz4g zw$!_l(S5)|nHV3hgVUe!%qctto`HHi5Slx|F5`Pf3L5&rru>eM?DjE9hg6uf6_WN^ z)(0O=f;<5r5E$KzIWaLYs_PJ|_5?V#wcQYPM)*kx)E?}`+e zJEBg<`5n1|Qo8TTt%QgZbUSOo{NDSf_$>s~LN=$#O@Wubt$~;OW|UhIbEK?;Ap)=B zAI^y<*_WrH1hSnEW8&qm7U0wzK8UtpV4er5=n;@E%vGu#X7#Q_(qv9gd5D8*X}d94 zM(l~&lStM5K=x@^uiBeDqh5gW|$MlONJz$byW|nF{|0Uf;dB4niNt}zg)cn8K{cAGm zqo@wZdmsEvEols^)Z_oI{My7O>U*>SFnHwQ;Zdp~WHcnuzm}fkaThKVSOzCb2Ed4_ z%1T!^w`zY-`+eWhk?t^ha~$FXFbgXyRy89xx8q7*LRwo8Un~wFu;GAN=t1|)ug({) zS(unMOoG;4V_lkS!{9jbkf`kT5G*_}jFyk&cXSm;$5MLm89C15E+!^$>5Js#ZZhk zFdui3Gl3ml0F{uKSpm_yM2!wI0D|-ZIt+y3aTm=nB-DwVI8+hNCx@c74(K^UG2KZw z_-iEokG#yEc>j-4`PU*%PX+VaqAA^Fdazp}YbA0}x{=h!y%!24pqIE!-UM!070&n% zRwo#+SAQC#!2G{a^*KX>nrwumw@OF^H`h?#Is*a)9I^2A~@ zNzrnhCT_H!&@fxWerJM59E8*9+g9IN!Oomyp5wQ!%6n`0;@}VIab1g--ky0`Esw$DdMy)5DD-S7rni63 z^6>9$^C%J&AJV_YUs>(Y@zX>$xE@f1~*<@kLG+T++XtmckekoF$=%^L(ibr$hzC%=Pqu(9gn9Z>? zS$c8ZF89S=z4gpvrdDj_=d1uL^x~HlT1P}Z zt#k1WJLZ>_u6G1q-;n@zA&mYH3BsxArpnOkO)*s&d53B~*1!`pdWTatX z7Hai-m~R!lZf_22E3J)>s?s~-B9~k7#Du1oY$Q>src_#J$%-mGK7u0az4!)hu;E?2 z+{e2xa|{v)`lNzN&X+!kEMe0z|Y>mYDEN<<64glMxQ;Jh6R zsY(tG$58J2y*-NMA#Z}Lb?<{@uW5w_twv6?CiKvGGTSgICEoee@O|+F!$^qy15++! zoUh6VEx5r_Y8JO-7L(qn$p(`EGD$W`^yIT%^O`tbUx(7}vA7~a@wp$OxC30*q$Lg*jw(~VBCuwH3yY9v_b>1!7& ziE$0CEGQUq#4Q0=<-aVrs{=^{Uw zvt4Fo=7EYeI4nxuQUGMkIfXSHP>0C}t#SW4`y)axxqyKCLO*+AJj6)a4~*WcmqQl$ zlfbNX{vj}PX-R#UO)Uw09OVhYAwy6VbRB8id&M*{I~ZlwU-+Spxez9v)BuWGIVb;adukMCt?^g4LDphj9Ewm=k58~(A6!Zq+XJ4X zP4H^G%R%0?$Jzj4_egBp?`s#pU|(w~gtX7WHVclwxGAX^Ts`R?|4ms=o4;jniKBzY zZVp^QPi3sUOwX(JAGJEq#}R9nVLDvo>lTca?m;audodT>@jaf2fcc&98*$h9J59VD zV2rwKz>`5r?N+AUn$S+)@&vkm+kcEvuVQP1M*AVrA=<%kg{bU3WGidsvl|)P>5{@X ze_s>P)&wtAczB1Gkr*f^Cx5H zkA4Dj`Sg2&K0ILHUP2r3qe9U_)8Aa;_#ZB@bl53e1+V*&`#pIl_C_Q;6d)f{y}xP0 zfB&+|e+uybdI!dX|8ZR;rCaD;t_0)%`xTsjxyKWAjdiT$B>MVDavivFg!V*68B!`` G3i~%0_1JU( literal 0 HcmV?d00001 diff --git a/uadk/docs/wd_design.md b/uadk/docs/wd_design.md new file mode 100644 index 0000000..ba5a5b9 --- /dev/null +++ b/uadk/docs/wd_design.md @@ -0,0 +1,675 @@ + +# UADK Architecture Design + + +| Version | Author | Changes | +| --- | :---- | :---- | +| 0.91 | Haojian Zhuang |1) Remove the content of 3rd party memory | +| | Zhou Wang | allocation. | +| | |2) Remove "ss_va" and "ss_dma" from struct wd_chan.| +| | |3) Change to user app polling async interface. | +| | |4) Add examples. | +| 0.92 | |1) Reorganize the document. | +| | |2) Remove some structures that are unused in apps. | +| 0.93 | |1) Avoid to discuss whether IOMMU disabled in NOSVA | +| | | scenario since it's not important. | +| | |2) Remove multiple queue since it's transparent to | +| | | user application. | +| 0.94 | |1) Split UADK into UACCE, libwd, algorithm | +| | | libraries and libaffinity. Change doc according | +| | | to this notion. | +| | |2) Illustrate how to select hardware accelerator. | +| | |3) Illustrate how libaffinity working. | +| 0.95 | |1) Remove libaffinity extension for unclear logic. | +| | |2) Add API to identify NOSVA in libwd. | +| 0.96 | |1) Fix on asynchronous operation. | +| 0.97 | |1) Fix the missing hook of async poll. | +| | |2) Illustrate more on binding driver. | +| 0.98 | |1) Do not expose context to user application. Use | +| | | handler instead. | +| | |2) Illustrate each parameter or field in table. | +| | |3) Adjust the layout. | +| 0.99 | |1) Fix the parameters in wd_alg_compress() and | +| | | wd_alg_decompress(). | +| 0.100 | |1) Remove wd_get_domain_affinity() for no benefit. | +| | |2) Remove dev_list from struct wd_alg_comp_ctx | +| | | since only one device is meaningful. | +| | |3) Rename context to session. Rename channel to | +| | | context. | +| | |4) Remove tag_id for not used. | +| | |5) Fix in struct wd_comp_arg. | +| | |6) Add compression interface for stream mode. | +| | |7) Simplify the parameters in wd_drv_unmap_qfr(). | +| | |8) Append a new image for asynchronous mode. | +| 0.101 | |1) Make libwd used by application directly. | +| | | Application could either use algorithm library | +| | | or libwd. | +| | |2) Change affinity to accel. | +| | |3) Adjust the layout. | +| | |4) Drop the concept of session. | +| 0.102 | |1) Make libwd used by vendor driver only. | +| | |2) Add session back for algorithm libraries. | +| 0.103 | |1) Remove the device list in compression algorithm | +| | | library since it's just an interim state. | +| | |2) Fix typo error. | +| | |3) Add context as parameter of wd_is_nosva(). | +| | |4) Adjust the layout. | +| 0.104 | |1) Merge libaccel into libwd. | +| 0.105 | |1) Add parameter in callback for async mode. | +| | |2) Fix minor issues. | +| 0.106 | |1) Update *struct wd_comp_arg*. | +| | |2) Update wd_alg_comp_alloc_sess(). | +| | |3) Update *struct wd_alg_comp*. | +| | |4) Update *struct wd_comp_sess*. | +| | |5) Update *struct wd_ctx*. | +| 0.107 | |1) Remove patchset information. | +| | |2) Fix typo error. | +| | |3) Mention libwd and algorithm libraries are built | +| | | as different libraries. | +| 0.108 | |1) Add more descriptions. | +| 0.109 | |1) Hide *struct wd_ctx*. Only expose context | +| | | handle to user space Apps. | +| | |2) Update on mask and session. | +| 0.110 | |1) Remove fini() callback in *struct wd_alg_comp*. | +| 0.111 | |1) Change the meaning of *arg->src_len*. | +| 1.0 | |1) Update with the latest interface. | +| 1.1 | |1) Rename *wd_drv_mmap_qfr()/wd_drv_unmap_qfr()* | +| | | to *wd_mmap_qfr()/wd_unmap_qfr()*. | +| 1.2 | |1) Rename *wd_mmap_qfr()/wd_unmap_qfr()* to | +| | | *wd_ctx_mmap_qfr()/wd_ctx_unmap_qfr()*. | +| 1.3 | |1) Add environment variable. | +| | |2) Change *user* layer to *sched* layer since | +| | | sample_sched is moved from user space into UADK | +| | | framework. | + + +## Terminology + +| Term | Illustration | +| :-- | :-- | +| SVA | Shared Virtual Addressing | +| NUMA | Non Uniform Memory Access | +| Context | A dual directional hardware communication resource between | +| | CPU and hardware accelerator. | +| IOMMU | Input Output Memory Management Unit | + + +## Overview + +UADK is a framework for user application to access hardware accelerator +in a unified, secure, and efficient way. UADK is comprised of UACCE, +libwd and many other algorithm libraries for different applications. + +![overview](./wd_overview.png) + +Libwd provides a wrapper of basic UACCE user space interfaces, they are a set +of helper functions. + +Algorithm libraries offer a set of APIs to users, who could use this set of +APIs to do specific task without accessing low level implementations. Algorithm +libraries also offer a register interface to let hardware vendors to register +their own user space driver, which could use above helper functions to do UACCE +related work. + +So two mechanisms are provided to user application. User application could +either access libwd or algorithm libraries. And all of these are compiled as +libraries. User application could pick up appropriate libraries to link. + +This document focuses on the design of libwd and algorithm libraries. + + +## Based Technology + +UADK relies on SVA (Shared Virtual Address) that needs to be supported +by IOMMU. + +In UADK framework, virtual address could be used by vendor driver and +application directly. And it's actually the same virtual address, memory copy +could be avoided between vendor driver and application with SVA. + + +### UACCE user space API + +As the kernel driver of UADK, UACCE offers a set of APIs between kernel +and user space. UACCE is introduced in "uacce.rst" and "sysfs-driver-uacce" +in kernel documents. + +Hardware accelerator registers in UACCE as a char dev. At the same time, +hardware information of accelerators are also exported in sysfs node. For +example, the file path of char dev is */dev/[Accel]* and hardware information +are in */sys/class/uacce/[Accel]/*. The same name is shared in both devfs and +sysfs. The *Accel* is comprised of name, dash and id. + +After opening this char device once, vendor driver will get a context to access +the resource of this accelerator device. Vendor driver can configure above +context by ioctl of this opened fd, and mmap hardware resource, like MMIO or +context to user space. + + +## Libwd Helper Functions + +Hardware accelerator communicates with CPU by MMIO and contexts. Libwd helper +functions provide the interface that vendor driver could access memory from +UADK. And libwd is only accessed by vendor driver. + + +### Context + +Context is a dual directional hardware communication resource between hardware +accelerator and CPU. When a vendor driver wants to access resources of an +accelerator, a context is the requisite resource. + +UACCE creates a char dev for each registered hardware device. Once the char dev +is opened by UADK, a handle of context is created. Vendor driver or +application could refer to the context by the handle. + +``` +typedef unsigned long long int handle_t; +``` + +Libwd defines APIs to allocate contexts. + +***handle_t \*wd_request_ctx(struct uacce_dev \*dev);*** + +| Layer | Parameter | Direction | Comments | +| :-- | :-- | :-- | :-- | +| libwd | *dev* | IN | A device in sysfs. All attrs information in sysfs | +| | | | are recorded in this *struct uacce_dev*. | + +Return the context handle if it succeeds. Return 0 if it fails. + +***void wd_release_ctx(handle_t h_ctx);*** + +| Layer | Parameter | Direction | Comments | +| :-- | :-- | :-- | :-- | +| libwd | *h_ctx* | IN | The handle indicates the working context. | + + +### mmap + +With a context, resources on hardware accelerator could be shared to CPU. +When vendor driver or application wants to access the resource, it needs to map +the context. + +Libwd provides API to create the mapping between virtual address and physical +address. The mapping could cover three different types. They are MMIO (device +MMIO region), DUS (device user share region) and SS (static share memory +region). + +*wd_ctx_mmap_qfr()* and *wd_ctx_unmap_qfr()* are a pair of APIs to create and +destroy the mapping. + +***void *wd_ctx_mmap_qfr(handle_t h_ctx, enum uacce_qfrt qfrt);*** + +| Layer | Parameter | Direction | Comments | +| :-- | :-- | :-- | :-- | +| libwd | *h_ctx* | IN | The handle indicate the working context. | +| | *qfrt* | IN | Indicate the queue file region type. It could be | +| | | | MMIO (device MMIO region), DUS (device user share | +| | | | region) or SS (static share memory region for | +| | | | user). | + +Return virtual address if it succeeds. Return NULL if it fails. + +*wd_ctx_mmap_qfr()* maps qfile region to user space. + +***void wd_ctx_unmap_qfr(handle_t h_ctx, enum uacce_qfrt qfrt);*** + +| Layer | Parameter | Direction | Comments | +| :-- | :-- | :-- | :-- | +| libwd | *h_ctx* | IN | The handle indicate the working context. | +| | *qfrt* | IN | Indicate the queue file region type. | + +*wd_ctx_unmap_qfr()* unmaps qfile region from user space. + +qfrt means queue file region type. The details could be found in UACCE kernel +driver. + + +## Algorithm Libraries + +Libwd is a fundamental layer what user relies on to access hardware. UADK also +provides algorithm interfaces that user could get out of the hardware details, +such as contexts. With the algorithm interface, the user application could be +executed on multiple vendor's hardware. + + +### Compression Algorithm + +In compression algorithm, the contexts won't be accessed by user any more. +Instead, user only need to focus on compressing and decompressing. + +In libwd, everything is based on context resource. In compression algorithm, +everything is based on session. Session is a superset of context, since vendor +driver may apply multiple contexts for performance. With compression algorithm +layer, user doesn't care how the multiple contexts are used. + + +#### Session in Compression Algorithm + +The session in compression algorithm records working algorithm, accelerator, +working mode, working context, and so on. It helps to gather more information +and encapsulates them together. Application only needs to record the handle of +session. + +Whatever user wants to compress or decompress, a session is always necessary. +Each session could only support either compression or decompression. And there +are also some configurations of the compression/decompression. They are defined +in the *struct wd_comp_sess_setup*. + +``` +struct wd_comp_sess_setup { + enum wd_comp_alg_type alg_type; // zlib or gzip + enum wd_comp_level comp_lv; // compression level + enum wd_comp_winsz_type win_sz; // compression window size + enum wd_comp_op_type op_type; // compress or decompress + enum wd_ctx_mode mode; // synchronous or asynchronous +}; +``` + +With *struct wd_comp_sess_setup*, a session could be created. The details of +the session is encapsuled. Only a handle is exported to user. + +***handle_t wd_comp_alloc_sess(struct wd_comp_sess_setup \*setup)*** + +| Layer | Parameter | Direction | Comments | +| :-- | :-- | :-- | :-- | +| compress | *setup* | IN | The structure describes the configurations of | +| algorithm | | | compression or decompression. | + +If a session is created successfully, a non-zero handle value is returned. +If fails to create a session, just return 0. + + +***void wd_comp_free_sess(handle_t h_sess)*** + +| Layer | Parameter | Direction | Comments | +| :-- | :-- | :-- | :-- | +| compress | *h_sess* | IN | A 64-bit handle value indicates working | +| algorithm | | | session. | + +With the handle, a related session could be destroyed. + + +#### Compression & Decompression + +Compression & decompression always submit data buffer to hardware accelerator +and collect the output. These buffer information could be encapsulated into a +structure, *struct wd_comp_req*. + +``` + typedef void *wd_alg_comp_cb_t(void *cb_param); + struct wd_comp_req { + void *src; + __u32 src_len; + void *dst; + __u32 dst_len; + wd_alg_comp_cb_t *cb; + void *cb_param; + __u8 op_type; + __u32 last; + __u32 status; + }; +``` + +| Field | Direction | Comments | +| :-- | :-- | :-- | +| *src* | IN | Input the virtual address of source buffer that is | +| | | prepared by user application. | +| *src_len* | IN & | Input the length of source buffer. | +| | OUT | When the operation is done, *src_len* is updated. | +| | | It could indicate the length consumed by hardware. | +| *dst* | IN | Input the virtual address of destination buffer that | +| | | is prepared by user application. | +| *dst_len* | IN & | Input the length of destination buffer. | +| | OUT | When the operation is done, *dst_len* is updated. | +| | | It indicates the real length of output data. | +| *cb* | IN | Indicate the user application callback that is used | +| | | in asynchronous mode. | +| *cb_param* | IN | Indicate the parameter that is used by callback in | +| | | asynchronous mode. | +| *op_type* | IN | Indicate compression or decompression. | +| *last* | IN | Indicate whether it's the last data frame. | +| *status* | OUT | Indicate the result. 0 means successful, and others | +| | | are error code. | + +When an application gets a session, it could request hardware accelerator to +work in synchronous mode or asynchronous mode. *cb* is the callback function +of user application that is only used in asynchronous mode. *cb_param* is the +parameter of the asynchronous callback function. + +Since synchronous or asynchronous mode is specified in *struct wd_comp_req*, +the compression or decompression could be treated that user submits requests to +a session. + +There're two kinds of compression interface. One is block mode that the data +in the request is not related to the previous or later data. And the other is +stream mode that the data in the request is related to the data in the previous +or later request. If user wants to compress/decompress large data buffer, it's +suggested to use stream mode. + + +***int wd_do_comp_sync(handle_t h_sess, struct wd_comp_req \*req)*** + +| Layer | Parameter | Direction | Comments | +| :-- | :-- | :-- | :-- | +| compress | *h_sess* | IN | Indicate the session. User application doesn't | +| algorithm | | | know the details in context. | +| | *req* | IN & | Indicate the source and destination buffer. | +| | | OUT | | + +*wd_do_comp_sync()* sends a synchronous compression/decompression request for +block mode. + +Return 0 if it succeeds. Return negative value if it fails. Parameter *req* +contains the buffer information. + + +***int wd_do_comp_strm(handle_t h_sess, struct wd_comp_req \*req)*** + +| Layer | Parameter | Direction | Comments | +| :-- | :-- | :-- | :-- | +| compress | *h_sess* | IN | Indicate the session. User application doesn't | +| algorithm | | | know the details in context. | +| | *req* | IN & | Indicate the source and destination buffer. | +| | | OUT | | + +Return 0 if it succeeds. Return negative value if it fails. Parameter *req* +contains the buffer information. + +*wd_do_comp_strm()* sends a synchronous compression/decompression request for +stream mode. *wd_do_comp_strm()* just likes *wd_do_comp_sync()*, user only +sends one request that the data buffer should be processed at one time. + + +***int wd_do_comp_sync2(handle_t h_sess, struct wd_comp_req \*req)*** + +| Layer | Parameter | Direction | Comments | +| :-- | :-- | :-- | :-- | +| compress | *h_sess* | IN | Indicate the session. User application doesn't | +| algorithm | | | know the details in context. | +| | *req* | IN & | Indicate the source and destination buffer. | +| | | OUT | | + +Return 0 if it succeeds. Return negative value if it fails. Parameter *req* +contains the buffer information. + +*wd_do_comp_sync2()* sends a synchronous compression/decompression request for +stream mode. *wd_do_comp_sync2()* is the superset of *wd_do_comp_strm()*. If +the data buffer of one request is too large to hardware accelerator, it could +split it into several requests until all data handled by hardware. + + + +#### Asynchronous Mode + +In synchronous mode, user application is blocked until the submitted request +is finished by hardware accelerator. Then a new request could be submitted. +In hardware accelerator, multiple requests are always processed in a stream +line. If a process needs to submit multiple requests to hardware, it can't +get good performance in synchronous mode. Since the stream line isn't fully +used. In this case, asynchronous mode could help user application to gain +better performance. + +In asynchronous mode, user application gets return immediately while a request +is submitted. + +***int wd_do_comp_async(handle_t h_sess, struct wd_comp_req \*req)*** + +| Layer | Parameter | Direction | Comments | +| :-- | :-- | :-- | :-- | +| compress | *h_sess* | IN | Indicate the session. User application doesn't | +| algorithm | | | know the details in context. | +| | *req* | IN & | Indicate the source and destination buffer. | +| | | OUT | | + +Return 0 if it succeeds. Return negative value if it fails. Parameter *req* +contains the buffer information. + +When hardware accelerator finishes the request, the callback that +is provided by user will be invoked. Because the compression library isn't +driven by interrupt, a polling function is necessary to check result. + +***int wd_comp_poll(__u32 expt, __u32 \*count)*** + +| Layer | Parameter | Direction | Comments | +| :-- | :-- | :-- | :-- | +| compress | *expt* | IN | Indicate the expected receiving requests from | +| algorithm | | | hardware accelerator. | +| | *count* | OUT | Indicate the real receiving requests from | +| | | | hardware accelerator. | + +Return 0 if all expected requests are received. Return error number if fails. + +Usually *wd_comp_poll()* could be invoked in a user defined polling thread. + + +#### Bind Accelerator and Driver + +Compression algorithm library requires each vendor driver providing an +instance, *struct wd_comp_driver*. This instance represents a vendor driver. +Compression algorithm library binds an vendor driver by the instance. + +``` + struct wd_comp_driver { + const char *drv_name; + const char *algo_name; + __u32 drv_ctx_size; + int (*init)(struct wd_ctx_config_internal *config, void *priv); + void (*exit)(void *priv); + int (*comp_send)(handle_t ctx, struct wd_comp_msg *msg); + int (*comp_recv)(handle_t ctx, struct wd_comp_msg *msg); + }; +``` + +| Field | Comments | +| :-- | :-- | +| *drv_name* | Driver name that is matched with device name. | +| *alg_name* | Algorithm name | +| *init* | Hook to do hardware initialization that implemented in vendor | +| | driver. | +| *exit* | Hook to finish all hardware operation that implemented in | +| | vendor driver. | + + +A matched vendor driver is bound to compression algorithm library in a global +instance, *struct wd_comp_setting*. The binding process is finished by +macro *WD_COMP_SET_DRIVER()*. + + +*struct wd_comp_setting* binds context resources, user scheduler and vendor +driver together. At first, user application needs to allocate contexts and to +create scheduler instance. Then use *wd_comp_init()* to initialize vendor +device. + +***int wd_comp_init(struct wd_ctx_config \*config, struct wd_sched \*sched)*** + +| Layer | Parameter | Direction | Comments | +| :-- | :-- | :-- | :-- | +| compress | *config* | IN | Indicate a context set. | +| algorithm | *sched* | IN | Indicate a user scheduler that is used to | +| | | | arrange context resource to a session. | + +Return 0 if it succeeds. And return error number if it fails. + +In *wd_comp_init()*, context resources, user scheduler and vendor driver are +initialized. + + +***void wd_comp_uninit(void)*** + +In *wd_comp_uninit()*, all configurations on resources are cleared. + + + +### Scheduler + +When algorithm layer is used, context resource is not exposed to user any more. +So user could define a scheduler that allocate context resources, arrange +proper resources to sessions and free context resources. + +For user convenient, a sample scheduler is provided in UADK for reference. + +***struct wd_sched \*sample_sched_alloc(__u8 sched_type, __u8 type_num, +__u8 numa_num, user_poll_func func)*** + +| Layer | Parameter | Direction | Comments | +| :-- | :-- | :-- | :-- | +| sched | *sched_type* | Input | The scheduler policy type that is supported | +| | | | in current scheduler. | +| | *type_num* | Input | The service type number of user's service | +| | | | that is defined by user. | +| | *numa_num* | Input | The NUMA number is used by user. | +| | *func* | Input | User provided polling function to poll events | +| | | | on contexts. | + +Return a scheduler instance if it succeeds. And return NULL if it fails. + + +***void sample_sched_release(struct wd_sched \*sched)*** + +| Layer | Parameter | Direction | Comments | +| :-- | :-- | :-- | :-- | +| sched | *sched* | Input | The user defined scheduler. | + +*sample_sched_release()* is used to release a scheduler instance. + + +***int sample_sched_fill_data(const struct wd_sched \*sched, int numa_id, +__u8 mode, __u8 type, __u32 begin, __u32 end)*** + +| Layer | Parameter | Direction | Comments | +| :-- | :-- | :-- | :-- | +| sched | *sched* | Input | The user defined scheduler | +| | *numa_id* | Input | The ID of NUMA node | +| | *mode* | Input | Specify operation mode. | +| | | | 0 -- sync mode, 1 -- async mode. | +| | *type* | Input | Service type that is defined by user. | +| | *begin* | Input | The index of first context in the region. | +| | *end* | Input | The index of last context in the region. | + +After context resources allocated by *wd_request_ctx()*, user could specify +which context resources are working in the specified mode or type by +*sample_sched_fill_data()*. + + +### Environment Variable + +According to above document, user need to care NUMA node and context number +to make use of UADK. The configuration process is a little boring. The idea +of Environment Variable is to make those parameters configured in user's +environment variable. It could help user to configure those parameters. + + +***wd_comp_env_init(void)*** + +Create a registered table for algorithm that could parse different environment +variables. With those parameters from user environment variables, allocate +related hardware resources. + + +***wd_comp_env_uninit(void)*** + +Free allocated hardware resources. + + +***wd_comp_ctx_num_init(__u32 node, __u32 type, __u32 num, __u8 mode)*** + +| Layer | Parameter | Direction | Comments | +| :-- | :-- | :-- | :-- | +| compress | *node* | Input | The ID of NUMA node. | +| algorithm | *type* | Input | Service type that is defined by user. | +| | *num* | Input | Context number. | +| | *mode* | Input | Specify operation mode. | +| | | | 0 -- sync mode, 1 -- async mode. | + +Specify the parameters and create a pseudo environment variable. By this +pseduo environment table, allocate related hardware resource. + + +***wd_comp_ctx_num_uninit(void)*** + +Free allocated hardware resources like ***wd_comp_env_uninit()***. + + +***wd_comp_get_env_param(__u32 node, __u32 type, __u32 mode, + __u32 \*num, __u8 \*is_enable)*** + +| Layer | Parameter | Direction | Comments | +| :-- | :-- | :-- | :-- | +| compress | *node* | Input | The ID of NUMA node. | +| algorithm | *type* | Input | Service type that is defined by user. | +| | *mode* | Input | Specify operation mode. | +| | | | 0 -- sync mode, 1 -- async mode. | +| | *num* | Output | Context number. | +| | *is_enable* | Output | Indicate whether asynchronous polling | +| | | | mode is enabled or not. | + +Query context number that is defined in environment variable by specified +NUMA node, type and operation mode. At the same time, asynchronous polling +mode is queried. + + + +## Vendor Driver + +A vendor driver is the counterpart of a hardware accelerator. Without the +vendor driver, the accelerator can't work. *Context* could store the +information from the both accelerator and vendor driver. + +If an accelerator is a bit special and not be generalized, application could +access the vendor driver directly. The interface to application is defined +by vendor driver itself. + +Before accessing hardware accelerator, vendor driver needs to allocate +*context* first. In the *struct wd_ctx*, the node path of accelerator is also +recorded. If there're multiple accelerators share a same vendor driver, vendor +driver should decide to choose which accelerator by itself. + +Application may want to track *context*. It's not good to share *context* to +application directly. It's better to transfer *context* to handle for security. + + + +## Example + +### Example in user application + +Here's an example of compression in user application. User application just +needs a few APIs to complete synchronous compression. + +![comp_sync](./wd_comp_sync.png) + +Synchoronous operation means polling hardware accelerator status of each +operation. It costs too much CPU resources on polling and causes performance +down. User application could divide the job into multiple parts. Then it +could make use of asynchronous mechanism to save time on polling. + +![comp_async2](./wd_comp_async2.png) + +There's also a limitation on asynchronous operation in SVA scenario. Let's +assume there're two output frames generated by accelerator, A frame and B +frame. If the output is in fixed-length, then we can calculate the address of +A and B frame in the output buffer of application. If the length of hardware +accelerator output isn't fixed, we have to setup the temperary buffer to store +A and B frame. Then a memory copy operation is required between temperary +buffer and application buffer. So we use compression as a demo to explain +asynchronous operation. It doesn't mean that we recommend to use asynchronous +compression. + + +### Vendor Driver Exposed to User Application + +Here's an example of implementing vendor driver that is exposed to application +direcly. + +When user application needs to access hardware accelerator, it calls the +interface in vendor driver. The interface is defined by vendor driver. Then +vendor driver requests a context by *wd_request_ctx()*. + +With the context, vendor driver could access hardware accelerator by libwd, +such as MMIO, memory mapping, and so on. And application has to use the +interface that is defined by vendor driver. + +When application doesn't want to access hardware accelerator, vendor driver +could invokes *wd_release_ctx()* to release the hardware. diff --git a/uadk/docs/wd_environment_variable b/uadk/docs/wd_environment_variable new file mode 100644 index 0000000..8ac2da7 --- /dev/null +++ b/uadk/docs/wd_environment_variable @@ -0,0 +1,59 @@ +Define WD related environment variables +======================================= + +-v0.1 2021.3.29 Sherlock Init +-v0.2 2021.4. 1 Barry, Sherlock Remove driver, sched, async polling env + +Currently WD lib offers init related APIs to init accelerator resources in +one process. User should call libwd and libwd_comp/libwd_crypto APIs to do +this. WD lib could help to do this by parsing a set of WD configurations +set by user. This document defines this set of WD environment variables to +offer process level WD configures. + +1. WD environment variables define +================================== + +WD__ASYNC_POLL_EN +---------------------- + + Define if enble polling threads in WD. WD__ASYNC_POLL_EN=1 means enable + polling threads in WD, otherwise caller should poll finished request by + WD APIs. + +WD_COMP_CTX_NUM +----------------- + + Define the algorithm ctx number. For example: + WD_COMP_CTX_NUM=sync-comp:10@0,async-decomp:20@1 means 10 sync ctxs are used + for compression in node0, and 20 async ctxs are used for decompression in + node1. + + currently, we only have: + :@ + +WD__CTX_NUM +----------------- + + Define the algorithm ctx number. For example: + WD__CTX_NUM=sync:10@0,async:20@1 means 10 sync ctxs are used + in node0, and 20 async ctxs are used in node1. + +alg above could be CIPHER, AEAD, DIGEST, DH, RSA, ECC. + +WD__ASYNC_POLL_NUM +----------------------- + + Define the async polling thread numbers in NUMA node. For example: + WD__ASYNC_POLL_NUM=2@0,4@2 means to configure 2 async polling threads in + node0, and 4 polling threads in node2. + +WD__EPOLL_EN + Define if wd_do__sync enable wd_ctx_wait in WD. WD__EPOLL_EN=1 + means enable wd_ctx_wait in WD, driver will wait to receive the package until + hardware is done with package, otherwise driver will try to receive the package + directly after the package is sent. + +2. User model +============= + + (to do: ...) diff --git a/uadk/docs/wd_overview.png b/uadk/docs/wd_overview.png new file mode 100644 index 0000000000000000000000000000000000000000..05c35b82df92601e3c81e9613ec654bb51ef1d0c GIT binary patch literal 14618 zcmeHu2T+vTvhDy96+}q_5+n*ZAWF_E2uKtpCq*(0IcFp@o1_Rx7^39hkTaqnNrDVH z=QQLnWO)CeXK&9vb?&|I)v0>#);pF}Q;sWjukNq=Tip|?tSC)LKt%uofe2+~Bvn8l zOlJ@X!x#?}_+};P0S*WxFe5AZ=!L8PdJ=vTSxfl^vUh21Xr@U@l z%~y`_Zei|TiBuH+Zs1Lpv_`EFyOKSQv} zG=UF#uGALv`P?wT=!8A)Kw4QIx9F8e=Wke~ge1P2H*_GuRv&QI4#gj(y^NNmN~GiHq|5mX&vEiS+B zeQ+E3Vn~J0gY7eR#F$*b;k0 zq4fv%#!d>HKCLbmBrF|L8@#Tsg-?lfoo^F(nBjYvllVCNxt1Be9A9jos zr<4%g?M%t*BoZr)P1cJRMcuwQ;@6zAM=ix2);{D59#mnZ#opXZMaSlRpyd}3&h;rr1I?A|s|r>GODJ~0$^<-+IdBV`uOrd{~{ z#EL(45n9l!37r2+=+ECg>;8y4397w1F2hX7Z_T9pFqFr}o9lIIYgodq6g5yhMyy2x_vF{0#B7#treq+K ze^3AaO?7z1^{CM&*F_!omY<(wyi?#X=m-0cENH*7FMD*r#3yW z%(xy*xJ=MZ&@L)|z|gk3smxKBlarH|XJKV!B?MD*lxO7GDANZ?ymH%aq397p7R2eh zx1XDF4K!YyZSF31QF9wM_u|(q={S$Yd)j^J10_2jt}EXBe@w zv!~0aV;#putoVL&Qv*r(2{^B5UYwtqzfw%(TaWZPWu)QZ;n`dM;ZIayGu3U0<>tMg zZ%}SAkXKOf{roGfU@XxxBViw#zK&0?A&KEsgBLS1^O~etz~yQ)nw8ec^&-NK%hUG; zHYRH6#606Qu+whwTEwgmP*d!%k|P1n_e-4xBnO(ZZm#=W}Sd?JjEq%@I88nQqzdCNSjK|crN(aOg z(2}|wN2TjJ6WFcd1!(pNK~J^Wc;Rhl2Vd70N{y@wVoPmd=}3DL+|ki-H-FhcXi*6Z z)c^7XweF0yJk@vsf8BbBpnssDYZtiwN@%)=@`|=q-#zWJkdmqMPP@7FOvq^|*?OHF$gr5|}(b$^ab2-Jm^AMAs2uzuzlS+^#6)23|* zcCa=NB$&!qHf$v5^Fn^cC^&NwPmnkX@yJVA3&wyyQ;y-A8dP6X@I$OVF_qtV9P*4I zaYKSlS;;DtBYdXkiX@-r+flqblFYx*zM}d4w=Gjl2I_mVkO1QJx4%M;&g`?-hYvBL z31c()9^?HjcL@dCedIp<;M;~Hr$T)vAcv`Bg(wDdzd5$5@7B4zgpogUZaDGd7dL-~ z3PU+v^J_jV^d(Ji`=8>~&sR{cMSM7Yi5H3#TeYcv;tKR=cj@?o{Yj< zPxPC>X`OaZ%lprqQ15=OnHV)hj+D7q8P188fc$FOto@V-Ut!JB+?)L2Q;tIa#=7rC zx4zcImLNRfTo=-)do4~~g==dBmJkEM2%2*{XTWRWKqA#gWOZumJQ1*Hd{k>X9KQ=* z!0;NGJK&wlw8o%*(bOT7a-XE}#P(RRqP=_E>s{@VCS&Hq%k)Z|P~lSIkRcLnmkA{k z4jaP@*TAzC>=^Dw@ifYVo_3M3i%OWU+*+5`k+b*{@7Z zd=`rNl;S1oK~f_q8kZP4SOU{NeDyRK5;Q? z%y7Ui_7J%2es-ksM9nAf?2@HHQ(V#fIs?)D(*!x_b`O^^nRR^vxSHEz+|X$;uQ~*< zbno*_7WjhV-~~^<8Beu*Y9vpUXM~zcLw!VY|7giX@ukAXy@XsS5_KM$f2s-d+G05A zLd2Tps5X>;W!FlfG^~auemXhdAotkNTB|o5nKUi*SL5dw=d7%;XYo*f(bz$$3pNJq zcAez$x>2*>h)olhjR{${ChkSOztc)gIBxr*@bGupL5vm?4KHWg?Qp9Z-oYkhq_*7X zbC|20vlgFqrS(oviczc0VZr{#;Rbx>e9>icw0&$?#U@lcyi4)%-v`@pQhvL{0YDco zxY<$~T?tS2Rn?6hzeVzuyfQ7N7PsWB6P;@3>|rTp-_%e#Ygojo)NHIBiR>;sYyuzx z_hk1E`%VvqBKODp*(dE?A7AgtbUHUO3_2Rh;#8)n#yw)Cg9Q0rYZ`iqx_>7z&8^4b0d;O8w#ZbI2l;1pPFu-bIt>|4YA>3#%S$3w zgf&!I___^}mOT*Txq}$k@eNM}U22WpowfS-n>xI^<}!T-s@4>|x4RbYq)#`#uGE%l zSuAcOD!--`j3K-z2O*n*L=?=@X_K8+?@= zCj+XD#nnyV!A)ya#usx%Ko#V8zb|F`q^+$O`$$EYH6Wqm z!Yi`e@^yXx%6N4BZUFCN%ksJte1j;+wmikgSV|k`;BHqG+MZqbf)lG5alOr$_mX)} ztFkUJ`OCn&Dbd&K%I2*7F-P8l%ZJwAz}20D#js)#tHTZC*^+m)y?UEmQK6H+T>F#K}OM!f_HdZ+&`3Tu)>>l0T$G7DahlYcdY6< zD-)zu(1qASzyVJZ#?qSImrSqg3&U&xK`cA8>KFi?#~ots?iB zcS2%UoN>lJ3)tlx1OV%(a(EY~q?pqZ^|WZWx~UiJybR*F>*Lxjq{+>nztT{e(hegV zD7MGZkVAueu-;9A4%GYD(s7&7i=C44Sa-+r`Q11jMVlSjIF=NH*=S|Ql@qI0)S9Z- zaD+#RKSqA{t{4n|#`7BYu79z%4`)WYgvS(HMkxW#-`r_a0YY^J-j}} zv$r?QOAMs;3zC`!RM4?n@J@gP!CiEqeOw1qmdnsq(hKKPtM4c%Sw1B@xTt>#;jM|? zX%y@z+=1h^IsyL-#??i8nj{g;&z~Ix+zj6+u8KslT*ED0LN-5@N zF22?C$Ns@H6Uqmh(^4L66trS zb(5c*-z>e<`!992|NiFR+W7BT!qv_uf82|s9v>mPYTMH}x(i#M{u`MZ4>hgeSaFyw zkHW}f8Kon1?c15f51X#9MJfsae6i7X=1VZGdybZxQj~tzOLz;BE&(Yno3^cbf###< zRXZIV7kk;_BQwJdULM8z_0QzwuHP2;Y>C9_%cs0oG5pg`uXf|oc`EDb%KI%3!x_&` zKJ<778OQV6&=%+2ktsI$G;D~=i5=!os)jN8WfU@yrk1a6(|E>Loc;Iz>j#h<2e30h z8SCD{GKK2Zi*&0^duW$3N{7v&6b0w#d2$RS?4r`cl(n>0tl>&xM@+?OthtKCK|w*z z>!VSNw(T|>|CYYW@y&whPJRK`Ux;(GhCwy&*~GMo0|2v0b5m)fbx{TW=%r1#0!B%{=j$ zo?h~V;fk*~E(3jH1c*s~RD~4Gm)^$mM^Z)Z+E`^V6BfgNXN|!~PMaAPu_70$~dyr+#ik@>GR- z`5ImKscKX(CcWaQN`DD|HbkOXitiP`0cjypd=CxN=&xf-0LQ;;;VK!ea0_62(mK&y ze`wxqdxAmC3M@oL`*We0AL>RA8OaHDltInt^8`tw&(r_ZwTx`!dr06L5mJyHAR_+I z7Vr)!Y_j8jhpFg9k^((OkxwM**6*8{ec=@;8eDcs`Ni(%T5Eq>`1G~q)_-7MgNHxa zSJyB0mG<}StD95ZVsTty1NJ&Rs(UM z^3Wi>K!eg_{f6^e_FB49sT*P>_@aH%>us`|kjJ@SftXX)kFUcQYet(sLl$KQS{8av zgDX}m_mC_~gYZGAkwKX`te%(9B2$3adAVRAmA`nS_Sa~Z7x#3nS-cNs_L9jtcpVND zCJ(8Q6X9nlb4$bP;8$FbSySM7`HPGNZjkh&?Nd3?qXRT^o=xvgxtA&V+kKlsc|Ds2 z*M5)GLf}?X{}1mt_~8eZuQP@ z>w^mCNAK1S2~)}ma=ma@t5B&rmx(z?-Qo8M{-eLWzb9-`-b3Hpgo^765?0WL4DiD8 z^lw*3ZYi*z))}OO%ll4ieW}oY({m(`wk+}06CsXG>$4xc8iJKA zeH*1G?XvO6epDLX-abaAO`!|0#7Y5!W)SK7cHj|RH5F-jA z6N9>-v(3)6;wjVXT(1+Ydte<9ct7b$ipiO;*@d+w>#8?}9PJVi;HA%iDf?Z-z$gWoaxsgnM*$0xQgv|7c`p*mXfkKM7>w9&e7==*@=rA zDWB7dEQ<9!x6jubnX3k#w#+hDts)8Afda<4;uu`?N}UM*?eJ6m2OK>G3(>=mw3AC!!!7F0EyWR{mF zi}VRC9L(x*{SHNWdW0GZmjYF80rUAAVnw|w3!0$u%Dvkm2DAUg#%Wju6!4$aV~Fas3o$772Ds_g z6BnJvfYpAnG4+4YV|o5e-lbO}$!QzOJvPCE90#1q!v#IY7ug0(K+=AZ+94)p^AaTv zFKO9rsnuslq=YN~0__*IR7D9uT*&16l2Q1(5laz9-bK4t_?8*R@3;2+D`OZM0vJU` ze+SFw{affz0X*|XR{Xv`DX$1R?EJTvFMJG2Z#v;2mW7mQ{uM%QXPSY+gr&DvM%ol^ zfYlAyWQ54k&gM@_C}FpBS4@<;nk~I$l>=M0^)ggMrDNRPxZRR%%E&KOrs?&Oenk^4 zFOdols3ke$aL;N!%WS|r73?Xnt8@t&GCx41E)lbc(&vU@+OF)*eJ`D;tgdMPwLWuJ zPGGhnE1`OJ)6-Pme-Hn+X8zSikoZL&o|g7%s7S9{x>c3VYwtM(vVMMclB~)C2MQ38fr&~D&N&7CP%n2DCAWn*L0s{0R}#u@UA0-^g@7(nC(?S;e(VjM`i2e5`yNJ9xr- z1(G4^3Umg?eR1Qown7K(zu)^9L1gn6a6a)x4U*%yg4K zkb)b%28u>58{_75y^TPP$rS?8s(0t59H?*NvKz@Ehk4`8md_@k%a6L>9w8j=F#Qtz+RQ&0h$uhD*euBO(4{DAF6G7mA4 zZz>Lcp2|B?q$k|{lnPD(24R~b2Me9G_1#xKb~j!L-_2v2Yl~*gPO>McPPZH?s)$?m zJ^zSS1_f0RIrZls8PXi=>}%hh&CJZE_rHHRzgj(JbS&dv2V4A}B#3}8K0+6wuxCH} zVI>Q@EULr+*P@|7$Dv*@E%F4YLS=)lf%)QVYJ^-!J3BgvXoQ+MC|d*YNygO?()v$) z^nK2pD#NdYZ#@H%MjY)fIj}urtW#k>n)bgQ28B+*($J+THqa9&p~=sJnIb&}Si9LW zzHPThd@8B#j~~+dU-5znsTYT3&;==i4&lu@M4lQ4tJF&TQ`e7W54?^YTOVElXh*+q zT1$nDfV$T^z8r< zfKw9Q(zb%~@bQg4PZF?W@afiFn;L(R;bVk6^&I^K%zEv*nwuTLf5YUW=9a(Z7K1P-oza|OT&$s1f!=AA{yI?Ad6Vc$0@7Ze@If+s!@o#se82?xtLfr#-b|*J7~2gD+%FUa{=PgtRFFMT( ztnH4mZ%7Vrg5YOs-{*DcxEbd4INJr?2qLIwp*9A(T zV`b(K4Vy!ZJ7f2Ox^Y!iRY}QC6E0nu(_n#?!=&5N56>Fsb@vuBjSzz>0D=9ma4P^* z&?wdiYNyVeOg%AiaR@>z-FaE)b;$Fy$#Up^5{y;X*Uac>XTj05CU(PfCXfQhML~Q) zw^i}O17pA-y8{OX1~Q~0oy7*Bfw%5L$r_SY3*ufe!$Glrp1dqj5SPd?67K*oToeNHc8I*g3NeQ%i?c)Wcg!4wGoHe=Ft9%rS4>%7cWSA4bNgk zY2>WaxUQfoF>0c|SILz@SsPgnyBjE~?Yj2Yf3JN92x^JBn_- z6BR4R^{@X^qmty|l&h7MKT+Z);T?Xdzz?bPZ0!HqmtN$5T`jbZt++ zpw7ejlN_t%mO=Ph0b-<23t;XjBN|J+0CEn=pB~$ybMMjnXlJ<>3|x(;JK@y)eQgvC zTY(5g;cy~$4vuX34>wa+il(bgu>qH~hL&IK$X=u7Tg%HYDv1R8LbOk~VvR8M9(xq4 zQ!d9>gubDOjf)%ezcQktrlyusZ97t8++CFd6*1pV1GD$j0aX#i?pK=BM4N^YSZPgWu)4FDiXh+YgKyxV56s^wgqBdGY(0*6zF#m>eY4)eQ z(veyvZJn`p#zNI%@s1iNI8|Yx;I?6z=AE~fz;<`Q5W;6QEHQ9e(#e@GeqPxCL^HtD zj?YgvulG7?Y>k(`3ArLs(K0wV=)BTrJXQheX66IyFIOr!8fZ?vg$ihUnn4Nnxz`Pa zomOLNx%ZouMtb0Y?}0fvSu|o|Vt^iuBw>zU$3#=LlR+ZO6bm{7VOZe_L+#Pj$m{&! zbmT}yi`61ig>#xym=O26OR~r00~)Y;$WI^*tJEBgkxv$K+Fu<&4i(cqFp_a{Di;;A z9v8^_gu-E#K;%xt(2Do9f|eUlMo>NsdUgRMCPj_s?xQB5x-tqM0VwEKT#HMFjFtiE z5WY*ALJ{<7#O;++y&;94n6S?|=-|FDrnEHKf?EFZx-V1qy4WE-L?wABA4YL$TVlIN zG_uqjG!R`z77OV9c#BwB^Ju9$>a~x%pXdds_E=@GQp5v)-LN+054{4OKYb&S4?-pG zEwV0Ww)?2?$2q=|*Wys7}pKU}2h;kJi zJTE%1v+`P0zz}3QxUhT9MgG%Feq*fs`A3P_TCJ!-o8)Cz;GL>fIeFA{jQwovg2(yb zwq;VygUJ?xx0i88YMUG>4S|5yqX1L+oYIEHfDvN-e9e}#Xt=nm!CLpyBYawX37PL$hmsZQBiN#Q1BX5)e?3*kJGH_oRM$79$@M zdu^Fz_2De^h~(%I6X*swEIB|gQ}|NJ63{@`zk=g)s+*9`<(jFs7V?KK6_jUGg=CCgXYAgCm{5fvDLGMeU&PyBOAF^qF!sK0n|Thu*f2thph$v!KbP8_E340p5sfYz(tw)Tx!AHe9Yp*#Ia+9uY4 zv~K&EdkIjoDk>JaINhyNv54m}e>+CD7d@nm548IG-T~VA+H&iFMn|CQZ;rRj_)7qO zgt=*wT@YpMu5I1cm#YyRctBfW&K2P20-uS;YwHsdsLso}dn*Ra+4D7u7nQO@0X6R< zhkBf`Y0zAZ8Lg3{^xzc#EH^)&5np;#74g~oF5}k zLtofG!SQ|}ieBgG_SVj`)hiaF}^b z7m~yW;0Lx^zI!3w-Qv*^%r7^huwZTGSRe^qv!Phbj(q0|U)wA5zO4460E|$KmVfl! z$x8;)-^LJ}4!xWl=nP>?t+Oz_iYF~W;KY*%mo zsg<^hkFxJr-p9r|FZaHhZ;J-Pd;%Y2w0a4KO!}zM!yKpkHlNR|m)<$4cC$fPqpA7{ z^h%7z4V~q*y=8O|Ge?*-hur9l1tZ5QZS3sqjExukuZx)>3$#iXfzHs3YNz$l{VayKYYJ} zOY8a)@Yl*ocjRcfWo}8aPGv;5^<>?LyrtP|NmR+AOGyq%;OOi(^cV|j&Eys`zwww@ zq2GB-_o9Y5Ald1*xp+~toS-hy=cPfPa;R=(#uG=k--DQ4k48j zCUl4xpjX(6?j1gbuI(c)6KjB7y68*jd+iTU=s8BW1-eW)QRr0xZyX+;hg&m%Qxf(s^zJ>Gb1af)Klpz!|`~jn6Q_VWet=1{{OV22S zywF!)gY=vR)KJ^yL;98%EpNZ4o%BxTtKkS`iKb5nE-Wmd=pQ))crjqgsas+7;o-&# zr?|FfPDlj8@XTa6n55*NvWcBbHgQYh_XFCGe0qiTezTLaw&475>R_=aWeP~C(eIK< z;g;}ff;X3jtZgMzUS1Bw1t3XHbO=>|QXH?}n4lQMt>K76>xZP1vqCjnv6@;{=``l- zHh^}cv$KZwQnIq`I}4rFrLe!ygaOj-$HxE+)~k2l2k3C{HA)pdJxF9EHGf22UOn5k zszarw680kihC;w#KBklRGx6N7bM^om-8e=TXG3D!0{dUM@2^U&H+v&SvJ?`T@StX5h&J_0k%;Fs_zzlmSQBjE9JnNzoi|g^8LjA2_~|8tu%Air5NCYCfxJrFlQ!9V#do|8sTcq%Pp8N0NmBAv=3_ho0W~6a7La zV{^Lu6c=WpT#HKc!N7!x*ef!_dQblXGD$1BGO`TeJ)nob#bBdZO2RGNOb(N2lamp@ z4MS59v8*qDJ9SH$U`_CkT5Fod_x<0BR;Wp4sP8{(Upww27D(jb*Vh1q( zd4%2~Fm{Z_x)sI@-k +#include "drv/wd_comp_drv.h" +#include "hisi_qm_udrv.h" +#include "wd.h" + +#define ZLIB 0 +#define GZIP 1 + +#define DEFLATE 0 +#define INFLATE 1 + +#define ZLIB_HEADER "\x78\x9c" +#define ZLIB_HEADER_SZ 2 + +/* + * We use a extra field for gzip block length. So the fourth byte is \x04. + * This is necessary because our software don't know the size of block when + * using an hardware decompressor (It is known by hardware). This help our + * decompressor to work and helpfully, compatible with gzip. + */ +#define GZIP_HEADER "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03" +#define GZIP_HEADER_SZ 10 + +#define GZIP_HEADER_EX "\x1f\x8b\x08\x04\x00\x00\x00\x00\x00\x03" +#define GZIP_EXTRA_SZ 10 +#define GZIP_TAIL_SZ 8 + +#define ZSTD_MAX_SIZE (1 << 17) + +#define swab32(x) \ + ((((x) & 0x000000ff) << 24) | \ + (((x) & 0x0000ff00) << 8) | \ + (((x) & 0x00ff0000) >> 8) | \ + (((x) & 0xff000000) >> 24)) + +#define STREAM_FLUSH_SHIFT 25 +#define STREAM_POS_SHIFT 2 +#define STREAM_MODE_SHIFT 1 +#define LITLEN_OVERFLOW_CNT_SHIFT 24 +#define BUF_TYPE_SHIFT 8 +#define WINDOW_SIZE_SHIFT 12 + +#define LITLEN_OVERFLOW_POS_MASK 0xffffff + +#define HZ_DECOMP_NO_SPACE 0x01 +#define HZ_NEGACOMPRESS 0x0d +#define HZ_CRC_ERR 0x10 +#define HZ_DECOMP_END 0x13 + +#define HZ_CTX_ST_MASK 0x000f +#define HZ_LSTBLK_MASK 0x0100 +#define HZ_STATUS_MASK 0xff +#define HZ_REQ_TYPE_MASK 0xff +#define HZ_SGL_OFFSET_MASK 0xffffff +#define HZ_STREAM_POS_MASK 0x08000000 +#define HZ_BUF_TYPE_MASK 0xf00 +#define HZ_HADDR_SHIFT 32 +#define HZ_SQE_TYPE_V1 0x0 +#define HZ_SQE_TYPE_V3 0x30000000 + +#define lower_32_bits(addr) ((__u32)((uintptr_t)(addr))) +#define upper_32_bits(addr) ((__u32)((uintptr_t)(addr) >> HZ_HADDR_SHIFT)) + +#define HZ_MAX_SIZE (8 * 1024 * 1024) + +#define RSV_OFFSET 64 +#define CTX_DW1_OFFSET 4 +#define CTX_DW2_OFFSET 8 +#define CTX_REPCODE1_OFFSET 12 +#define CTX_REPCODE2_OFFSET 24 +#define CTX_HW_REPCODE_OFFSET 784 +#define OVERFLOW_DATA_SIZE 2 +#define ZSTD_FREQ_DATA_SIZE 784 +#define ZSTD_LIT_RESV_SIZE 16 +#define REPCODE_SIZE 12 + +#define BUF_TYPE 2 + +enum alg_type { + HW_DEFLATE = 0x1, + HW_ZLIB, + HW_GZIP, + HW_LZ77_ZSTD_PRICE = 0x42, + HW_LZ77_ZSTD, +}; + +enum hw_state { + HZ_STATELESS, + HZ_STATEFUL, +}; + +enum hw_flush { + HZ_SYNC_FLUSH, + HZ_FINISH, +}; + +enum hw_stream_status { + HZ_STREAM_OLD, + HZ_STREAM_NEW, +}; + +enum lz77_compress_status { + UNCOMP_BLK, + RLE_BLK, + COMP_BLK, +}; + +struct hisi_zip_sqe { + __u32 consumed; + __u32 produced; + __u32 comp_data_length; + /* + * status: 0~7 bits + * rsvd: 8~31 bits + */ + __u32 dw3; + __u32 input_data_length; + __u32 dw5; + __u32 dw6; + /* + * in_sge_data_offset: 0~23 bits + * rsvd: 24 bit + * flush_type: 25 bit + * stream_mode: 26 bit + * steam_new_flag: 27 bit + * sqe_type: 28~31 bits + */ + __u32 dw7; + /* + * out_sge_data_offset: 0~23 bits + * rsvd: 24~31 bits + */ + __u32 dw8; + /* + * request_type: 0~7 bits + * buffer_type: 8~11 bits + * window_size: 12~15 bits + * rsvd: 16~31 bits + */ + __u32 dw9; + __u32 dw10; + __u32 dw11; + __u32 dw12; + /* tag: in sqe type 0 */ + __u32 dw13; + __u32 dest_avail_out; + __u32 ctx_dw0; + __u32 dw16; + __u32 dw17; + __u32 source_addr_l; + __u32 source_addr_h; + __u32 dest_addr_l; + __u32 dest_addr_h; + __u32 stream_ctx_addr_l; + __u32 stream_ctx_addr_h; + __u32 literals_addr_l; + __u32 literals_addr_h; + /* tag: in sqe type 3 */ + __u32 dw26; + __u32 dw27; + __u32 ctx_dw1; + __u32 ctx_dw2; + __u32 isize; + /* + * checksum: in alg gzip + * linlength_overflow_pos: 0~23 bits in alg lz77_zstd + * linlength_overflow_cnt: 24~31 bits in alg lz77_zstd + */ + __u32 dw31; +}; + +struct hisi_zip_sqe_ops { + const char *alg_name; + int (*fill_buf[BUF_TYPE])(handle_t h_qp, struct hisi_zip_sqe *sqe, + struct wd_comp_msg *msg); + void (*fill_sqe_type)(struct hisi_zip_sqe *sqe); + void (*fill_alg)(struct hisi_zip_sqe *sqe); + void (*fill_tag)(struct hisi_zip_sqe *sqe, __u32 tag); + int (*fill_comp_level)(struct hisi_zip_sqe *sqe, enum wd_comp_level comp_lv); + void (*get_data_size)(struct hisi_zip_sqe *sqe, enum wd_comp_op_type op_type, + struct wd_comp_msg *recv_msg); + int (*get_tag)(struct hisi_zip_sqe *sqe); +}; + +struct hisi_zip_ctx { + struct wd_ctx_config_internal config; +}; + +static void dump_zip_msg(struct wd_comp_msg *msg) +{ + WD_ERR("dump zip message after a task error occurs.\n"); + WD_ERR("avali_out:%u in_cons:%u produced:%u data_fmt:%d.\n", + msg->avail_out, msg->in_cons, msg->produced, msg->data_fmt); +} + +static int buf_size_check_deflate(__u32 *in_size, __u32 *out_size) +{ + if (unlikely(*in_size > HZ_MAX_SIZE)) { + WD_ERR("invalid: in_len(%u) is out of range!\n", *in_size); + return -WD_EINVAL; + } + + if (unlikely(*out_size > HZ_MAX_SIZE)) { + WD_ERR("warning: avail_out(%u) is out of range, will set 8MB size max!\n", + *out_size); + *out_size = HZ_MAX_SIZE; + } + + return 0; +} + +static void fill_buf_size_deflate(struct hisi_zip_sqe *sqe, __u32 in_size, + __u32 out_size) +{ + sqe->input_data_length = in_size; + sqe->dest_avail_out = out_size; +} + +static void fill_buf_addr_deflate(struct hisi_zip_sqe *sqe, void *src, + void *dst, void *ctx_buf) +{ + sqe->source_addr_l = lower_32_bits(src); + sqe->source_addr_h = upper_32_bits(src); + sqe->dest_addr_l = lower_32_bits(dst); + sqe->dest_addr_h = upper_32_bits(dst); + sqe->stream_ctx_addr_l = lower_32_bits(ctx_buf); + sqe->stream_ctx_addr_h = upper_32_bits(ctx_buf); +} + +static int fill_buf_deflate_generic(struct hisi_zip_sqe *sqe, + struct wd_comp_msg *msg, + const char *head, int head_size) +{ + __u32 in_size = msg->req.src_len; + __u32 out_size = msg->avail_out; + void *src = msg->req.src; + void *dst = msg->req.dst; + void *ctx_buf = NULL; + int ret; + + if (msg->stream_pos == WD_COMP_STREAM_NEW && head != NULL) { + if (msg->req.op_type == WD_DIR_COMPRESS) { + memcpy(dst, head, head_size); + dst += head_size; + out_size -= head_size; + } else { + src += head_size; + in_size -= head_size; + } + } + + ret = buf_size_check_deflate(&in_size, &out_size); + if (unlikely(ret)) + return ret; + + fill_buf_size_deflate(sqe, in_size, out_size); + + if (msg->ctx_buf) + ctx_buf = msg->ctx_buf + RSV_OFFSET; + + fill_buf_addr_deflate(sqe, src, dst, ctx_buf); + + return 0; +} + +static int fill_buf_deflate(handle_t h_qp, struct hisi_zip_sqe *sqe, + struct wd_comp_msg *msg) +{ + return fill_buf_deflate_generic(sqe, msg, NULL, 0); +} + +static int fill_buf_zlib(handle_t h_qp, struct hisi_zip_sqe *sqe, + struct wd_comp_msg *msg) +{ + return fill_buf_deflate_generic(sqe, msg, ZLIB_HEADER, ZLIB_HEADER_SZ); +} + +static int fill_buf_gzip(handle_t h_qp, struct hisi_zip_sqe *sqe, + struct wd_comp_msg *msg) +{ + return fill_buf_deflate_generic(sqe, msg, GZIP_HEADER, GZIP_HEADER_SZ); +} + +static void fill_buf_type_sgl(struct hisi_zip_sqe *sqe) +{ + __u32 val; + + val = sqe->dw9 & HZ_BUF_TYPE_MASK; + val |= 1 << BUF_TYPE_SHIFT; + sqe->dw9 = val; +} + +static int fill_buf_addr_deflate_sgl(handle_t h_qp, struct hisi_zip_sqe *sqe, + struct wd_comp_msg *msg) +{ + struct wd_comp_req *req = &msg->req; + void *hw_sgl_in, *hw_sgl_out; + handle_t h_sgl_pool; + + h_sgl_pool = hisi_qm_get_sglpool(h_qp); + if (unlikely(!h_sgl_pool)) { + WD_ERR("failed to get sglpool!\n"); + return -WD_EINVAL; + } + + hw_sgl_in = hisi_qm_get_hw_sgl(h_sgl_pool, req->list_src); + if (unlikely(!hw_sgl_in)) { + WD_ERR("failed to get hw sgl in!\n"); + return -WD_ENOMEM; + } + + hw_sgl_out = hisi_qm_get_hw_sgl(h_sgl_pool, req->list_dst); + if (unlikely(!hw_sgl_out)) { + WD_ERR("failed to get hw sgl out!\n"); + hisi_qm_put_hw_sgl(h_sgl_pool, hw_sgl_in); + return -WD_ENOMEM; + } + + fill_buf_addr_deflate(sqe, hw_sgl_in, hw_sgl_out, NULL); + + return 0; +} + +static void fill_buf_sgl_skip(struct hisi_zip_sqe *sqe, __u32 src_skip, + __u32 dst_skip) +{ + __u32 val; + + val = sqe->dw7 & ~HZ_SGL_OFFSET_MASK; + val |= src_skip; + sqe->dw7 = val; + + val = sqe->dw8 & ~HZ_SGL_OFFSET_MASK; + val |= dst_skip; + sqe->dw8 = val; +} + +static int fill_buf_deflate_slg_generic(handle_t h_qp, struct hisi_zip_sqe *sqe, + struct wd_comp_msg *msg, const char *head, + int head_size) +{ + struct wd_comp_req *req = &msg->req; + __u32 out_size = msg->avail_out; + __u32 in_size = req->src_len; + __u32 src_skip = 0; + __u32 dst_skip = 0; + int ret; + + fill_buf_type_sgl(sqe); + + ret = fill_buf_addr_deflate_sgl(h_qp, sqe, msg); + if (unlikely(ret)) + return ret; + + if (head != NULL && msg->req.op_type == WD_DIR_COMPRESS) { + memcpy(req->list_dst->data, head, head_size); + dst_skip = head_size; + out_size -= head_size; + } else if (head != NULL && msg->req.op_type == WD_DIR_DECOMPRESS) { + src_skip = head_size; + in_size -= head_size; + } + + fill_buf_sgl_skip(sqe, src_skip, dst_skip); + + fill_buf_size_deflate(sqe, in_size, out_size); + + return 0; +} + +static int fill_buf_deflate_sgl(handle_t h_qp, struct hisi_zip_sqe *sqe, + struct wd_comp_msg *msg) +{ + return fill_buf_deflate_slg_generic(h_qp, sqe, msg, NULL, 0); +} + +static int fill_buf_zlib_sgl(handle_t h_qp, struct hisi_zip_sqe *sqe, + struct wd_comp_msg *msg) +{ + return fill_buf_deflate_slg_generic(h_qp, sqe, msg, ZLIB_HEADER, ZLIB_HEADER_SZ); +} + +static int fill_buf_gzip_sgl(handle_t h_qp, struct hisi_zip_sqe *sqe, + struct wd_comp_msg *msg) +{ + return fill_buf_deflate_slg_generic(h_qp, sqe, msg, GZIP_HEADER, GZIP_HEADER_SZ); +} + +static void fill_buf_size_lz77_zstd(struct hisi_zip_sqe *sqe, __u32 in_size, + __u32 lits_size, __u32 seqs_size) +{ + sqe->input_data_length = in_size; + + /* fill the literals output size */ + sqe->dw13 = lits_size; + + /* fill the sequences output size */ + sqe->dest_avail_out = seqs_size; +} + +static void fill_buf_addr_lz77_zstd(struct hisi_zip_sqe *sqe, + void *src, void *lits_start, + void *seqs_start, void *ctx_buf) +{ + sqe->source_addr_l = lower_32_bits(src); + sqe->source_addr_h = upper_32_bits(src); + sqe->dest_addr_l = lower_32_bits(seqs_start); + sqe->dest_addr_h = upper_32_bits(seqs_start); + sqe->literals_addr_l = lower_32_bits(lits_start); + sqe->literals_addr_h = upper_32_bits(lits_start); + sqe->stream_ctx_addr_l = lower_32_bits(ctx_buf); + sqe->stream_ctx_addr_h = upper_32_bits(ctx_buf); +} + +static int fill_buf_lz77_zstd(handle_t h_qp, struct hisi_zip_sqe *sqe, + struct wd_comp_msg *msg) +{ + struct wd_comp_req *req = &msg->req; + struct wd_lz77_zstd_data *data = req->priv; + __u32 in_size = msg->req.src_len; + __u32 lit_size = in_size + ZSTD_LIT_RESV_SIZE; + __u32 out_size = msg->avail_out; + void *ctx_buf = NULL; + + if (unlikely(!data)) { + WD_ERR("invalid: wd_lz77_zstd_data address is NULL!\n"); + return -WD_EINVAL; + } + + if (unlikely(in_size > ZSTD_MAX_SIZE)) { + WD_ERR("invalid: in_len(%u) of lz77_zstd is out of range!\n", + in_size); + return -WD_EINVAL; + } + + if (unlikely(out_size > HZ_MAX_SIZE)) { + WD_ERR("warning: avail_out(%u) is out of range , will set 8MB size max!\n", + out_size); + out_size = HZ_MAX_SIZE; + } + + /* + * For lz77_zstd, the hardware need 784 Bytes buffer to output + * the frequency information about input data. + */ + if (unlikely(out_size < ZSTD_FREQ_DATA_SIZE + lit_size)) { + WD_ERR("invalid: sequences output size(%u) is not enough!\n", + ZSTD_FREQ_DATA_SIZE + in_size); + return -WD_EINVAL; + } + + if (msg->ctx_buf) { + ctx_buf = msg->ctx_buf + RSV_OFFSET; + if (data->blk_type != COMP_BLK) + memcpy(ctx_buf + CTX_HW_REPCODE_OFFSET, + msg->ctx_buf + CTX_REPCODE2_OFFSET, REPCODE_SIZE); + } + + fill_buf_size_lz77_zstd(sqe, in_size, lit_size, out_size - lit_size); + + fill_buf_addr_lz77_zstd(sqe, req->src, req->dst, + req->dst + lit_size, ctx_buf); + + data->literals_start = req->dst; + data->sequences_start = req->dst + lit_size; + + return 0; +} + +static struct wd_datalist *get_seq_start_list(struct wd_comp_req *req) +{ + struct wd_datalist *cur = req->list_dst; + __u32 lits_size = 0; + + while (cur) { + lits_size += cur->len; + cur = cur->next; + if (lits_size >= req->src_len + ZSTD_LIT_RESV_SIZE) + break; + } + + return cur; +} + +static int fill_buf_lz77_zstd_sgl(handle_t h_qp, struct hisi_zip_sqe *sqe, + struct wd_comp_msg *msg) +{ + void *hw_sgl_in, *hw_sgl_out_lit, *hw_sgl_out_seq; + struct wd_comp_req *req = &msg->req; + struct wd_lz77_zstd_data *data = req->priv; + __u32 in_size = msg->req.src_len; + __u32 out_size = msg->avail_out; + struct wd_datalist *seq_start; + handle_t h_sgl_pool; + __u32 lits_size; + int ret; + + if (unlikely(in_size > ZSTD_MAX_SIZE)) { + WD_ERR("invalid: in_len(%u) of lz77_zstd is out of range!\n", + in_size); + return -WD_EINVAL; + } + + if (unlikely(!data)) { + WD_ERR("invalid: wd_lz77_zstd_data address is NULL!\n"); + return -WD_EINVAL; + } + + fill_buf_type_sgl(sqe); + + seq_start = get_seq_start_list(req); + + data->literals_start = req->list_dst; + data->sequences_start = seq_start; + + lits_size = hisi_qm_get_list_size(req->list_dst, seq_start); + + fill_buf_size_lz77_zstd(sqe, in_size, lits_size, out_size - lits_size); + + h_sgl_pool = hisi_qm_get_sglpool(h_qp); + if (unlikely(!h_sgl_pool)) { + WD_ERR("failed to get sglpool!\n"); + return -WD_EINVAL; + } + + hw_sgl_in = hisi_qm_get_hw_sgl(h_sgl_pool, req->list_src); + if (unlikely(!hw_sgl_in)) { + WD_ERR("failed to get hw sgl in!\n"); + return -WD_ENOMEM; + } + + hw_sgl_out_lit = hisi_qm_get_hw_sgl(h_sgl_pool, req->list_dst); + if (unlikely(!hw_sgl_out_lit)) { + WD_ERR("failed to get hw sgl out for literals!\n"); + ret = -WD_ENOMEM; + goto err_free_sgl_in; + } + + hw_sgl_out_seq = hisi_qm_get_hw_sgl(h_sgl_pool, seq_start); + if (unlikely(!hw_sgl_out_seq)) { + WD_ERR("failed to get hw sgl out for sequences!\n"); + ret = -WD_ENOMEM; + goto err_free_sgl_out_lit; + } + + fill_buf_addr_lz77_zstd(sqe, hw_sgl_in, hw_sgl_out_lit, + hw_sgl_out_seq, NULL); + + return 0; + +err_free_sgl_out_lit: + hisi_qm_put_hw_sgl(h_sgl_pool, hw_sgl_out_lit); +err_free_sgl_in: + hisi_qm_put_hw_sgl(h_sgl_pool, hw_sgl_in); + return ret; +} + +static void fill_sqe_type_v1(struct hisi_zip_sqe *sqe) +{ + __u32 val; + val = sqe->dw7 & ~HZ_SQE_TYPE_V1; + val |= HZ_SQE_TYPE_V1; + sqe->dw7 = val; +} + +static void fill_sqe_type_v3(struct hisi_zip_sqe *sqe) +{ + __u32 val; + val = sqe->dw7 & ~HZ_SQE_TYPE_V3; + val |= HZ_SQE_TYPE_V3; + sqe->dw7 = val; +} + +static void fill_alg_deflate(struct hisi_zip_sqe *sqe) +{ + __u32 val; + val = sqe->dw9 & ~HZ_REQ_TYPE_MASK; + val |= HW_DEFLATE; + sqe->dw9 = val; +} + +static void fill_alg_zlib(struct hisi_zip_sqe *sqe) +{ + __u32 val; + val = sqe->dw9 & ~HZ_REQ_TYPE_MASK; + val |= HW_ZLIB; + sqe->dw9 = val; +} + +static void fill_alg_gzip(struct hisi_zip_sqe *sqe) +{ + __u32 val; + val = sqe->dw9 & ~HZ_REQ_TYPE_MASK; + val |= HW_GZIP; + sqe->dw9 = val; +} + +static void fill_alg_lz77_zstd(struct hisi_zip_sqe *sqe) +{ + __u32 val; + + val = sqe->dw9 & ~HZ_REQ_TYPE_MASK; + val |= HW_LZ77_ZSTD; + sqe->dw9 = val; +} + +static void fill_tag_v1(struct hisi_zip_sqe *sqe, __u32 tag) +{ + sqe->dw13 = tag; +} + +static void fill_tag_v3(struct hisi_zip_sqe *sqe, __u32 tag) +{ + sqe->dw26 = tag; +} + +static int fill_comp_level_deflate(struct hisi_zip_sqe *sqe, enum wd_comp_level comp_lv) +{ + return 0; +} + +static int fill_comp_level_lz77_zstd(struct hisi_zip_sqe *sqe, enum wd_comp_level comp_lv) +{ + __u32 val; + + switch (comp_lv) { + case WD_COMP_L8: + break; + case WD_COMP_L9: + val = sqe->dw9 & ~HZ_REQ_TYPE_MASK; + val |= HW_LZ77_ZSTD_PRICE; + sqe->dw9 = val; + break; + default: + WD_ERR("invalid: comp_lv(%d) is unsupport!\n", comp_lv); + return -WD_EINVAL; + } + + return 0; +} + +static void get_data_size_deflate(struct hisi_zip_sqe *sqe, enum wd_comp_op_type op_type, + struct wd_comp_msg *recv_msg) +{ + recv_msg->in_cons = sqe->consumed; + recv_msg->produced = sqe->produced; +} + +static void get_data_size_zlib(struct hisi_zip_sqe *sqe, enum wd_comp_op_type op_type, + struct wd_comp_msg *recv_msg) +{ + __u32 stream_pos = sqe->dw7 & HZ_STREAM_POS_MASK; + + recv_msg->in_cons = sqe->consumed; + recv_msg->produced = sqe->produced; + + if (stream_pos) { + if (op_type == WD_DIR_COMPRESS) + recv_msg->produced += ZLIB_HEADER_SZ; + else + recv_msg->in_cons += ZLIB_HEADER_SZ; + } +} + +static void get_data_size_gzip(struct hisi_zip_sqe *sqe, enum wd_comp_op_type op_type, + struct wd_comp_msg *recv_msg) +{ + __u32 stream_pos = sqe->dw7 & HZ_STREAM_POS_MASK; + + recv_msg->in_cons = sqe->consumed; + recv_msg->produced = sqe->produced; + + if (stream_pos) { + if (op_type == WD_DIR_COMPRESS) + recv_msg->produced += GZIP_HEADER_SZ; + else + recv_msg->in_cons += GZIP_HEADER_SZ; + } +} + +static void get_data_size_lz77_zstd(struct hisi_zip_sqe *sqe, enum wd_comp_op_type op_type, + struct wd_comp_msg *recv_msg) +{ + struct wd_lz77_zstd_data *data = recv_msg->req.priv; + void *ctx_buf = recv_msg->ctx_buf; + + if (unlikely(!data)) + return; + + data->lit_num = sqe->comp_data_length; + data->seq_num = sqe->produced; + data->lit_length_overflow_cnt = sqe->dw31 >> LITLEN_OVERFLOW_CNT_SHIFT; + data->lit_length_overflow_pos = sqe->dw31 & LITLEN_OVERFLOW_POS_MASK; + data->freq = data->sequences_start + data->seq_num + OVERFLOW_DATA_SIZE; + + if (ctx_buf) { + memcpy(ctx_buf + CTX_REPCODE2_OFFSET, + ctx_buf + CTX_REPCODE1_OFFSET, REPCODE_SIZE); + memcpy(ctx_buf + CTX_REPCODE1_OFFSET, + ctx_buf + RSV_OFFSET + CTX_HW_REPCODE_OFFSET, REPCODE_SIZE); + } +} + +static int get_tag_v1(struct hisi_zip_sqe *sqe) +{ + return sqe->dw13; +} + +static int get_tag_v3(struct hisi_zip_sqe *sqe) +{ + return sqe->dw26; +} + +struct hisi_zip_sqe_ops ops[] = { { + .alg_name = "deflate", + .fill_buf[WD_FLAT_BUF] = fill_buf_deflate, + .fill_buf[WD_SGL_BUF] = fill_buf_deflate_sgl, + .fill_sqe_type = fill_sqe_type_v3, + .fill_alg = fill_alg_deflate, + .fill_tag = fill_tag_v3, + .fill_comp_level = fill_comp_level_deflate, + .get_data_size = get_data_size_deflate, + .get_tag = get_tag_v3, + }, { + .alg_name = "zlib", + .fill_buf[WD_FLAT_BUF] = fill_buf_zlib, + .fill_buf[WD_SGL_BUF] = fill_buf_zlib_sgl, + .fill_alg = fill_alg_zlib, + .fill_comp_level = fill_comp_level_deflate, + .get_data_size = get_data_size_zlib, + }, { + .alg_name = "gzip", + .fill_buf[WD_FLAT_BUF] = fill_buf_gzip, + .fill_buf[WD_SGL_BUF] = fill_buf_gzip_sgl, + .fill_alg = fill_alg_gzip, + .fill_comp_level = fill_comp_level_deflate, + .get_data_size = get_data_size_gzip, + }, { + .alg_name = "lz77_zstd", + .fill_buf[WD_FLAT_BUF] = fill_buf_lz77_zstd, + .fill_buf[WD_SGL_BUF] = fill_buf_lz77_zstd_sgl, + .fill_sqe_type = fill_sqe_type_v3, + .fill_alg = fill_alg_lz77_zstd, + .fill_tag = fill_tag_v3, + .fill_comp_level = fill_comp_level_lz77_zstd, + .get_data_size = get_data_size_lz77_zstd, + .get_tag = get_tag_v3, + } +}; + +static void hisi_zip_sqe_ops_adapt(handle_t h_qp) +{ + struct hisi_qp *qp = (struct hisi_qp *)h_qp; + + if (qp->q_info.hw_type == HISI_QM_API_VER2_BASE) { + ops[WD_ZLIB].fill_sqe_type = fill_sqe_type_v1; + ops[WD_ZLIB].fill_tag = fill_tag_v1; + ops[WD_ZLIB].get_tag = get_tag_v1; + ops[WD_GZIP].fill_sqe_type = fill_sqe_type_v1; + ops[WD_GZIP].fill_tag = fill_tag_v1; + ops[WD_GZIP].get_tag = get_tag_v1; + } else if (qp->q_info.hw_type >= HISI_QM_API_VER3_BASE) { + ops[WD_ZLIB].fill_sqe_type = fill_sqe_type_v3; + ops[WD_ZLIB].fill_tag = fill_tag_v3; + ops[WD_ZLIB].get_tag = get_tag_v3; + ops[WD_GZIP].fill_sqe_type = fill_sqe_type_v3; + ops[WD_GZIP].fill_tag = fill_tag_v3; + ops[WD_GZIP].get_tag = get_tag_v3; + } +} + +static int hisi_zip_init(struct wd_ctx_config_internal *config, void *priv) +{ + struct hisi_zip_ctx *zip_ctx = (struct hisi_zip_ctx *)priv; + struct hisi_qm_priv qm_priv; + handle_t h_qp = 0; + handle_t h_ctx; + int i; + + if (!config->ctx_num) { + WD_ERR("invalid: zip init config ctx num is 0!\n"); + return -WD_EINVAL; + } + + memcpy(&zip_ctx->config, config, sizeof(struct wd_ctx_config_internal)); + /* allocate qp for each context */ + for (i = 0; i < config->ctx_num; i++) { + h_ctx = config->ctxs[i].ctx; + qm_priv.sqe_size = sizeof(struct hisi_zip_sqe); + qm_priv.op_type = config->ctxs[i].op_type; + qm_priv.qp_mode = config->ctxs[i].ctx_mode; + /* Setting the epoll en to 0 for ASYNC ctx */ + qm_priv.epoll_en = (qm_priv.qp_mode == CTX_MODE_SYNC) ? + config->epoll_en : 0; + qm_priv.idx = i; + h_qp = hisi_qm_alloc_qp(&qm_priv, h_ctx); + if (unlikely(!h_qp)) + goto out; + } + + hisi_zip_sqe_ops_adapt(h_qp); + + return 0; +out: + for (; i >= 0; i--) { + h_qp = (handle_t)wd_ctx_get_priv(config->ctxs[i].ctx); + hisi_qm_free_qp(h_qp); + } + return -WD_EINVAL; +} + +static void hisi_zip_exit(void *priv) +{ + struct hisi_zip_ctx *zip_ctx = (struct hisi_zip_ctx *)priv; + struct wd_ctx_config_internal *config = &zip_ctx->config; + handle_t h_qp; + int i; + + for (i = 0; i < config->ctx_num; i++) { + h_qp = (handle_t)wd_ctx_get_priv(config->ctxs[i].ctx); + hisi_qm_free_qp(h_qp); + } +} + +static int fill_zip_comp_sqe(struct hisi_qp *qp, struct wd_comp_msg *msg, + struct hisi_zip_sqe *sqe) +{ + enum hisi_hw_type hw_type = qp->q_info.hw_type; + enum wd_comp_alg_type alg_type = msg->alg_type; + __u32 win_sz = msg->win_sz; + __u8 flush_type; + __u8 stream_pos; + __u8 state; + int ret; + + if (unlikely((hw_type <= HISI_QM_API_VER2_BASE && alg_type > WD_GZIP) || + (hw_type >= HISI_QM_API_VER3_BASE && alg_type >= WD_COMP_ALG_MAX))) { + WD_ERR("invalid: algorithm type is %d!\n", alg_type); + return -WD_EINVAL; + } + + ret = ops[alg_type].fill_buf[msg->req.data_fmt]((handle_t)qp, sqe, msg); + if (unlikely(ret)) + return ret; + + ops[alg_type].fill_sqe_type(sqe); + + ops[alg_type].fill_alg(sqe); + + ops[alg_type].fill_tag(sqe, msg->tag); + + ret = ops[alg_type].fill_comp_level(sqe, msg->comp_lv); + if (unlikely(ret)) + return ret; + + state = (msg->stream_mode == WD_COMP_STATEFUL) ? HZ_STATEFUL : + HZ_STATELESS; + stream_pos = (msg->stream_pos == WD_COMP_STREAM_NEW) ? HZ_STREAM_NEW : + HZ_STREAM_OLD; + flush_type = (msg->req.last == 1) ? HZ_FINISH : HZ_SYNC_FLUSH; + sqe->dw7 |= ((stream_pos << STREAM_POS_SHIFT) | + (state << STREAM_MODE_SHIFT) | + (flush_type)) << STREAM_FLUSH_SHIFT; + sqe->dw9 |= win_sz << WINDOW_SIZE_SHIFT; + sqe->isize = msg->isize; + sqe->dw31 = msg->checksum; + + if (msg->ctx_buf) { + sqe->ctx_dw0 = *(__u32 *)msg->ctx_buf; + sqe->ctx_dw1 = *(__u32 *)(msg->ctx_buf + CTX_DW1_OFFSET); + sqe->ctx_dw2 = *(__u32 *)(msg->ctx_buf + CTX_DW2_OFFSET); + } + + return 0; +} + +static int hisi_zip_comp_send(handle_t ctx, void *comp_msg) +{ + struct hisi_qp *qp = wd_ctx_get_priv(ctx); + struct wd_comp_msg *msg = comp_msg; + handle_t h_qp = (handle_t)qp; + struct hisi_zip_sqe sqe = {0}; + __u16 count = 0; + int ret; + + hisi_set_msg_id(h_qp, &msg->tag); + ret = fill_zip_comp_sqe(qp, msg, &sqe); + if (unlikely(ret < 0)) { + WD_ERR("failed to fill zip sqe, ret = %d!\n", ret); + return ret; + } + ret = hisi_qm_send(h_qp, &sqe, 1, &count); + if (unlikely(ret < 0)) { + if (ret != -WD_EBUSY) + WD_ERR("failed to send to hardware, ret = %d!\n", ret); + + return ret; + } + + return 0; +} + +static int get_alg_type(__u32 type) +{ + int alg_type = -WD_EINVAL; + + switch (type) { + case HW_DEFLATE: + alg_type = WD_DEFLATE; + break; + case HW_ZLIB: + alg_type = WD_ZLIB; + break; + case HW_GZIP: + alg_type = WD_GZIP; + break; + case HW_LZ77_ZSTD: + case HW_LZ77_ZSTD_PRICE: + alg_type = WD_LZ77_ZSTD; + break; + default: + break; + } + + return alg_type; +} + +static void free_hw_sgl(handle_t h_qp, struct hisi_zip_sqe *sqe, + enum wd_comp_alg_type alg_type) +{ + void *hw_sgl_in, *hw_sgl_out; + handle_t h_sgl_pool; + + h_sgl_pool = hisi_qm_get_sglpool(h_qp); + if (unlikely(!h_sgl_pool)) { + WD_ERR("failed to get sglpool to free hw sgl!\n"); + return; + } + + hw_sgl_in = VA_ADDR(sqe->source_addr_h, sqe->source_addr_l); + hisi_qm_put_hw_sgl(h_sgl_pool, hw_sgl_in); + + hw_sgl_out = VA_ADDR(sqe->dest_addr_h, sqe->dest_addr_l); + hisi_qm_put_hw_sgl(h_sgl_pool, hw_sgl_out); + + if (alg_type == WD_LZ77_ZSTD) { + hw_sgl_out = VA_ADDR(sqe->literals_addr_h, + sqe->literals_addr_l); + hisi_qm_put_hw_sgl(h_sgl_pool, hw_sgl_out); + } +} + +static void get_ctx_buf(struct hisi_zip_sqe *sqe, + struct wd_comp_msg *recv_msg) +{ + recv_msg->avail_out = sqe->dest_avail_out; + if (VA_ADDR(sqe->stream_ctx_addr_h, sqe->stream_ctx_addr_l)) { + /* + * In ASYNC mode, recv_msg->ctx_buf is NULL. + * recv_msg->ctx_buf is only valid in SYNC mode. + * ctx_dwx uses 4 BYTES + */ + *(__u32 *)recv_msg->ctx_buf = sqe->ctx_dw0; + *(__u32 *)(recv_msg->ctx_buf + CTX_DW1_OFFSET) = sqe->ctx_dw1; + *(__u32 *)(recv_msg->ctx_buf + CTX_DW2_OFFSET) = sqe->ctx_dw2; + } +} + +static int parse_zip_sqe(struct hisi_qp *qp, struct hisi_zip_sqe *sqe, + struct wd_comp_msg *msg) +{ + __u32 buf_type = (sqe->dw9 & HZ_BUF_TYPE_MASK) >> BUF_TYPE_SHIFT; + __u16 ctx_st = sqe->ctx_dw0 & HZ_CTX_ST_MASK; + __u16 lstblk = sqe->dw3 & HZ_LSTBLK_MASK; + __u32 status = sqe->dw3 & HZ_STATUS_MASK; + __u32 type = sqe->dw9 & HZ_REQ_TYPE_MASK; + struct wd_comp_msg *recv_msg = msg; + bool need_debug = wd_need_debug(); + int alg_type, ret; + __u32 tag; + + alg_type = get_alg_type(type); + if (unlikely(alg_type < 0)) { + WD_ERR("invalid: hardware type is %u!\n", type); + return -WD_EINVAL; + } + + tag = ops[alg_type].get_tag(sqe); + ret = hisi_check_bd_id((handle_t)qp, recv_msg->tag, tag); + if (ret) + return ret; + + recv_msg->tag = tag; + + if (qp->q_info.qp_mode == CTX_MODE_ASYNC) { + recv_msg = wd_comp_get_msg(qp->q_info.idx, tag); + if (unlikely(!recv_msg)) { + WD_ERR("failed to get send msg! idx = %u, tag = %u!\n", + qp->q_info.idx, tag); + return -WD_EINVAL; + } + } + + recv_msg->req.status = 0; + + if (unlikely(status != 0 && status != HZ_NEGACOMPRESS && + status != HZ_CRC_ERR && status != HZ_DECOMP_END)) { + WD_ERR("bad request(ctx_st = 0x%x, status = 0x%x, algorithm type = %u)!\n", + ctx_st, status, type); + recv_msg->req.status = WD_IN_EPARA; + } + + ops[alg_type].get_data_size(sqe, qp->q_info.qc_type, recv_msg); + + get_ctx_buf(sqe, recv_msg); + + /* last block no space, need resend null size req */ + if (ctx_st == HZ_DECOMP_NO_SPACE) + recv_msg->req.status = WD_EAGAIN; + + if (need_debug) + WD_DEBUG("zip recv lst =%hu, ctx_st=0x%x, status=0x%x, alg=%u!\n", + lstblk, ctx_st, status, type); + if (lstblk && (status == HZ_DECOMP_END)) + recv_msg->req.status = WD_STREAM_END; + + recv_msg->isize = sqe->isize; + recv_msg->checksum = sqe->dw31; + recv_msg->alg_type = alg_type; + + if (buf_type == WD_SGL_BUF) + free_hw_sgl((handle_t)qp, sqe, alg_type); + + if (unlikely(recv_msg->req.status == WD_IN_EPARA)) + dump_zip_msg(recv_msg); + + return 0; +} + +static int hisi_zip_comp_recv(handle_t ctx, void *comp_msg) +{ + struct hisi_qp *qp = wd_ctx_get_priv(ctx); + struct wd_comp_msg *recv_msg = comp_msg; + handle_t h_qp = (handle_t)qp; + struct hisi_zip_sqe sqe = {0}; + __u16 count = 0; + int ret; + + ret = hisi_qm_recv(h_qp, &sqe, 1, &count); + if (unlikely(ret < 0)) + return ret; + + return parse_zip_sqe(qp, &sqe, recv_msg); +} + +struct wd_comp_driver hisi_zip = { + .drv_name = "hisi_zip", + .alg_name = "zlib\ngzip\ndeflate\nlz77_zstd", + .drv_ctx_size = sizeof(struct hisi_zip_ctx), + .init = hisi_zip_init, + .exit = hisi_zip_exit, + .comp_send = hisi_zip_comp_send, + .comp_recv = hisi_zip_comp_recv, +}; + +WD_COMP_SET_DRIVER(hisi_zip); diff --git a/uadk/drv/hisi_hpre.c b/uadk/drv/hisi_hpre.c new file mode 100644 index 0000000..552a565 --- /dev/null +++ b/uadk/drv/hisi_hpre.c @@ -0,0 +1,2438 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. */ + +#include +#include +#include +#include +#include +#include +#include +#include "hisi_qm_udrv.h" +#include "../include/drv/wd_rsa_drv.h" +#include "../include/drv/wd_dh_drv.h" +#include "../include/drv/wd_ecc_drv.h" + +#define HPRE_HW_TASK_DONE 3 +#define HPRE_HW_TASK_INIT 1 + +#define HPRE_HW_V2_ALG_TYPE 0 +#define HPRE_HW_V3_ECC_ALG_TYPE 1 + +#define HPRE_HW_SVA_ERROR (1u << 5) + +/* realize with hardware ECC multiplication, avoid conflict with wd_ecc.h */ +#define HPRE_SM2_ENC 0xE +#define HPRE_SM2_DEC 0xF + +#define SM2_SQE_NUM 2 + +#define MAX_WAIT_CNT 10000000 +#define SM2_KEY_SIZE 32 +#define SM2_PONIT_SIZE 64 +#define MAX_HASH_LENS BITS_TO_BYTES(521) +#define HW_PLAINTEXT_BYTES_MAX BITS_TO_BYTES(4096) + +#define CRT_PARAMS_SZ(key_size) ((5 * (key_size)) >> 1) +#define CRT_GEN_PARAMS_SZ(key_size) ((7 * (key_size)) >> 1) +#define GEN_PARAMS_SZ(key_size) ((key_size) << 1) +#define CRT_PARAM_SZ(key_size) ((key_size) >> 1) + +enum hpre_alg_type { + HPRE_ALG_NC_NCRT = 0x0, + HPRE_ALG_NC_CRT = 0x1, + HPRE_ALG_KG_STD = 0x2, + HPRE_ALG_KG_CRT = 0x3, + HPRE_ALG_DH_G2 = 0x4, + HPRE_ALG_DH = 0x5, + HPRE_ALG_PRIME = 0x6, + HPRE_ALG_MOD = 0x7, + HPRE_ALG_MOD_INV = 0x8, + HPRE_ALG_MUL = 0x9, + HPRE_ALG_COPRIME = 0xA, + HPRE_ALG_ECC_CURVE_TEST = 0xB, + HPRE_ALG_ECDH_PLUS = 0xC, + HPRE_ALG_ECDH_MULTIPLY = 0xD, + HPRE_ALG_ECDSA_SIGN = 0xE, + HPRE_ALG_ECDSA_VERF = 0xF, + HPRE_ALG_X_DH_MULTIPLY = 0x10, + HPRE_ALG_SM2_KEY_GEN = 0x11, + HPRE_ALG_SM2_SIGN = 0x12, + HPRE_ALG_SM2_VERF = 0x13, + HPRE_ALG_SM2_ENC = 0x14, + HPRE_ALG_SM2_DEC = 0x15 +}; + +/* put vendor hardware message as a user interface is not suitable here */ +struct hisi_hpre_sqe { + __u32 alg : 5; + + /* error type */ + __u32 etype : 11; + __u32 etype1 : 14; + __u32 done : 2; + __u32 task_len1 : 8; + __u32 task_len2 : 8; + __u32 mrttest_num : 8; + __u32 uwkey_enb : 1; + __u32 sm2_ksel : 1; + __u32 sva_bypass: 1; + __u32 sva_status: 4; + __u32 bd_rsv2 : 1; + __u32 low_key; + __u32 hi_key; + __u32 low_in; + __u32 hi_in; + __u32 low_out; + __u32 hi_out; + __u32 low_tag; + __u32 hi_tag; + __u32 sm2_mlen : 9; + __u32 rsvd1 : 7; + __u32 uwkey_sel : 4; + __u32 wrap_num : 3; + __u32 resv2 : 9; + __u32 kek_key; + __u32 rsvd3[4]; +}; + +struct hisi_hpre_ctx { + struct wd_ctx_config_internal config; +}; + +static void dump_hpre_msg(void *msg, const char *s) +{ + struct wd_rsa_msg *rsa_msg; + struct wd_ecc_msg *ecc_msg; + struct wd_dh_msg *dh_msg; + + WD_ERR("dump %s alg message after a task error occurs.\n", s); + + if (!strcmp(s, "rsa")) { + rsa_msg = (struct wd_rsa_msg *)msg; + WD_ERR("key_bytes:%u key_type:%u\n", rsa_msg->key_bytes, rsa_msg->key_type); + } else if (!strcmp(s, "ecc")) { + ecc_msg = (struct wd_ecc_msg *)msg; + WD_ERR("key_bytes:%u curve_id:%u\n", ecc_msg->key_bytes, ecc_msg->curve_id); + } else if (!strcmp(s, "dh")) { + dh_msg = (struct wd_dh_msg *)msg; + WD_ERR("gbytes:%u key_bytes:%u is_g2:%u\n", dh_msg->gbytes, + dh_msg->key_bytes, dh_msg->is_g2); + } +} + +static bool is_hpre_bin_fmt(char *dst, const char *src, __u32 dsz, __u32 bsz) +{ + const char *temp = src + dsz; + int lens = bsz - dsz; + int i = 0; + + if (!lens) + return true; + + while (i < lens) { + if (temp[i] && !src[i]) + break; + i++; + } + + if (dst == src && i != lens) + return true; + + return false; +} + +static int crypto_bin_to_hpre_bin(char *dst, const char *src, + __u32 b_size, __u32 d_size, const char *p_name) +{ + int i = d_size - 1; + int j; + + if (!dst || !src || !b_size || !d_size) { + WD_ERR("invalid: %s trans to hpre bin parameters err!\n", p_name); + return -WD_EINVAL; + } + + if (b_size < d_size) { + WD_ERR("invalid: %s trans to hpre bin data too long!\n", p_name); + return -WD_EINVAL; + } + + if (is_hpre_bin_fmt(dst, src, d_size, b_size)) + return WD_SUCCESS; + + for (j = b_size - 1; j >= 0; j--, i--) { + if (i >= 0) + dst[j] = src[i]; + else + dst[j] = 0; + } + + return WD_SUCCESS; +} + +static int hpre_bin_to_crypto_bin(char *dst, const char *src, __u32 b_size, + const char *p_name) +{ + int i, cnt; + int j = 0; + int k = 0; + + if (!dst || !src || !b_size) { + WD_ERR("invalid: %s trans to crypto bin parameters err!\n", p_name); + return 0; + } + + while (!src[j] && k < (b_size - 1)) + k = ++j; + + if (j == 0 && src == dst) + return b_size; + + for (i = 0, cnt = j; i < b_size; j++, i++) { + if (i < b_size - cnt) + dst[i] = src[j]; + else + dst[i] = 0; + } + + return b_size - k; +} + +static int fill_rsa_crt_prikey2(struct wd_rsa_prikey *prikey, + void **data) +{ + struct wd_dtb *wd_dq, *wd_dp, *wd_qinv, *wd_q, *wd_p; + int ret; + + wd_rsa_get_crt_prikey_params(prikey, &wd_dq, &wd_dp, + &wd_qinv, &wd_q, &wd_p); + ret = crypto_bin_to_hpre_bin(wd_dq->data, (const char *)wd_dq->data, + wd_dq->bsize, wd_dq->dsize, "rsa crt dq"); + if (ret) + return ret; + + ret = crypto_bin_to_hpre_bin(wd_dp->data, (const char *)wd_dp->data, + wd_dp->bsize, wd_dp->dsize, "rsa crt dp"); + if (ret) + return ret; + + ret = crypto_bin_to_hpre_bin(wd_q->data, (const char *)wd_q->data, + wd_q->bsize, wd_q->dsize, "rsa crt q"); + if (ret) + return ret; + + ret = crypto_bin_to_hpre_bin(wd_p->data, + (const char *)wd_p->data, wd_p->bsize, wd_p->dsize, "rsa crt p"); + if (ret) + return ret; + + ret = crypto_bin_to_hpre_bin(wd_qinv->data, + (const char *)wd_qinv->data, wd_qinv->bsize, + wd_qinv->dsize, "rsa crt qinv"); + if (ret) + return ret; + + *data = wd_dq->data; + + return WD_SUCCESS; +} + +static int fill_rsa_prikey1(struct wd_rsa_prikey *prikey, void **data) +{ + struct wd_dtb *wd_d, *wd_n; + int ret; + + wd_rsa_get_prikey_params(prikey, &wd_d, &wd_n); + ret = crypto_bin_to_hpre_bin(wd_d->data, (const char *)wd_d->data, + wd_d->bsize, wd_d->dsize, "rsa d"); + if (ret) + return ret; + + ret = crypto_bin_to_hpre_bin(wd_n->data, (const char *)wd_n->data, + wd_n->bsize, wd_n->dsize, "rsa n"); + if (ret) + return ret; + + *data = wd_d->data; + + return WD_SUCCESS; +} + +static int fill_rsa_pubkey(struct wd_rsa_pubkey *pubkey, void **data) +{ + struct wd_dtb *wd_e, *wd_n; + int ret; + + wd_rsa_get_pubkey_params(pubkey, &wd_e, &wd_n); + ret = crypto_bin_to_hpre_bin(wd_e->data, (const char *)wd_e->data, + wd_e->bsize, wd_e->dsize, "rsa e"); + if (ret) + return ret; + + ret = crypto_bin_to_hpre_bin(wd_n->data, (const char *)wd_n->data, + wd_n->bsize, wd_n->dsize, "rsa n"); + if (ret) + return ret; + + *data = wd_e->data; + + return WD_SUCCESS; +} + +static int fill_rsa_genkey_in(struct wd_rsa_kg_in *genkey) +{ + struct wd_dtb e, q, p; + int ret; + + wd_rsa_get_kg_in_params(genkey, &e, &q, &p); + + ret = crypto_bin_to_hpre_bin(e.data, (const char *)e.data, + e.bsize, e.dsize, "rsa kg e"); + if (ret) + return ret; + + ret = crypto_bin_to_hpre_bin(q.data, (const char *)q.data, + q.bsize, q.dsize, "rsa kg q"); + if (ret) + return ret; + + return crypto_bin_to_hpre_bin(p.data, (const char *)p.data, + p.bsize, p.dsize, "rsa kg p"); +} + +static int hpre_tri_bin_transfer(struct wd_dtb *bin0, struct wd_dtb *bin1, + struct wd_dtb *bin2) +{ + int ret; + + ret = hpre_bin_to_crypto_bin(bin0->data, (const char *)bin0->data, + bin0->bsize, "hpre"); + if (!ret) + return -WD_EINVAL; + + bin0->dsize = ret; + + if (bin1) { + ret = hpre_bin_to_crypto_bin(bin1->data, + (const char *)bin1->data, + bin1->bsize, "hpre"); + if (!ret) + return -WD_EINVAL; + + bin1->dsize = ret; + } + + if (bin2) { + ret = hpre_bin_to_crypto_bin(bin2->data, + (const char *)bin2->data, bin2->bsize, "hpre"); + if (!ret) + return -WD_EINVAL; + + bin2->dsize = ret; + } + + return WD_SUCCESS; +} + +static int rsa_out_transfer(struct wd_rsa_msg *msg, + struct hisi_hpre_sqe *hw_msg, __u8 qp_mode) +{ + struct wd_rsa_req *req = &msg->req; + struct wd_rsa_kg_out *key = req->dst; + __u16 kbytes = msg->key_bytes; + struct wd_dtb qinv, dq, dp; + struct wd_dtb d, n; + void *data; + int ret; + + if (hw_msg->alg == HPRE_ALG_KG_CRT || hw_msg->alg == HPRE_ALG_KG_STD) { + /* async */ + if (qp_mode == CTX_MODE_ASYNC) { + data = VA_ADDR(hw_msg->hi_out, hw_msg->low_out); + key = container_of(data, struct wd_rsa_kg_out, data); + } else { + key = req->dst; + } + } + + msg->result = WD_SUCCESS; + if (hw_msg->alg == HPRE_ALG_KG_CRT) { + req->dst_bytes = CRT_GEN_PARAMS_SZ(kbytes); + wd_rsa_get_kg_out_crt_params(key, &qinv, &dq, &dp); + ret = hpre_tri_bin_transfer(&qinv, &dq, &dp); + if (ret) { + WD_ERR("failed to parse rsa genkey qinv&&dq&&dp format!\n"); + return ret; + } + + wd_rsa_set_kg_out_crt_psz(key, qinv.dsize, + dq.dsize, dp.dsize); + } else if (hw_msg->alg == HPRE_ALG_KG_STD) { + req->dst_bytes = GEN_PARAMS_SZ(kbytes); + + wd_rsa_get_kg_out_params(key, &d, &n); + ret = hpre_tri_bin_transfer(&d, &n, NULL); + if (ret) { + WD_ERR("failed to parse rsa genkey1 d&&n format!\n"); + return ret; + } + + wd_rsa_set_kg_out_psz(key, d.dsize, n.dsize); + } else { + req->dst_bytes = kbytes; + } + + return WD_SUCCESS; +} + +static int rsa_prepare_key(struct wd_rsa_msg *msg, + struct hisi_hpre_sqe *hw_msg) +{ + struct wd_rsa_req *req = &msg->req; + void *data; + int ret; + + if (req->op_type == WD_RSA_SIGN) { + if (hw_msg->alg == HPRE_ALG_NC_CRT) { + ret = fill_rsa_crt_prikey2((void *)msg->key, &data); + if (ret) + return ret; + } else { + ret = fill_rsa_prikey1((void *)msg->key, &data); + if (ret) + return ret; + hw_msg->alg = HPRE_ALG_NC_NCRT; + } + } else if (req->op_type == WD_RSA_VERIFY) { + ret = fill_rsa_pubkey((void *)msg->key, &data); + if (ret) + return ret; + hw_msg->alg = HPRE_ALG_NC_NCRT; + } else if (req->op_type == WD_RSA_GENKEY) { + ret = fill_rsa_genkey_in((void *)msg->key); + if (ret) + return ret; + ret = wd_rsa_kg_in_data((void *)msg->key, (char **)&data); + if (ret < 0) { + WD_ERR("failed to get rsa gen key data!\n"); + return ret; + } + if (hw_msg->alg == HPRE_ALG_NC_CRT) + hw_msg->alg = HPRE_ALG_KG_CRT; + else + hw_msg->alg = HPRE_ALG_KG_STD; + } else { + WD_ERR("invalid: rsa operatin type %u is error!\n", req->op_type); + return -WD_EINVAL; + } + + hw_msg->low_key = LW_U32((uintptr_t)data); + hw_msg->hi_key = HI_U32((uintptr_t)data); + + return WD_SUCCESS; +} + +static int rsa_prepare_iot(struct wd_rsa_msg *msg, + struct hisi_hpre_sqe *hw_msg) +{ + struct wd_rsa_req *req = &msg->req; + struct wd_rsa_kg_out *kout = req->dst; + int ret = WD_SUCCESS; + void *out = NULL; + + if (req->op_type != WD_RSA_GENKEY) { + hw_msg->low_in = LW_U32((uintptr_t)req->src); + hw_msg->hi_in = HI_U32((uintptr_t)req->src); + out = req->dst; + } else { + hw_msg->low_in = 0; + hw_msg->hi_in = 0; + ret = wd_rsa_kg_out_data(kout, (char **)&out); + if (ret < 0) + return ret; + } + + hw_msg->low_out = LW_U32((uintptr_t)out); + hw_msg->hi_out = HI_U32((uintptr_t)out); + + return ret; +} + +static int hpre_init(struct wd_ctx_config_internal *config, void *priv, const char *alg_name) +{ + struct hisi_hpre_ctx *hpre_ctx = (struct hisi_hpre_ctx *)priv; + struct hisi_qm_priv qm_priv; + handle_t h_ctx, h_qp; + int i, j; + + if (!config->ctx_num) { + WD_ERR("invalid: hpre init config ctx num is 0!\n"); + return -WD_EINVAL; + } + + memcpy(&hpre_ctx->config, config, sizeof(*config)); + + /* allocate qp for each context */ + qm_priv.sqe_size = sizeof(struct hisi_hpre_sqe); + + /* DH/RSA: qm sqc_type = 0, ECC: qm sqc_type = 1; */ + if (!strcmp(alg_name, "ecc")) + qm_priv.op_type = HPRE_HW_V3_ECC_ALG_TYPE; + else + qm_priv.op_type = HPRE_HW_V2_ALG_TYPE; + + for (i = 0; i < config->ctx_num; i++) { + h_ctx = config->ctxs[i].ctx; + qm_priv.qp_mode = config->ctxs[i].ctx_mode; + /* Setting the epoll en to 0 for ASYNC ctx */ + qm_priv.epoll_en = (qm_priv.qp_mode == CTX_MODE_SYNC) ? + config->epoll_en : 0; + qm_priv.idx = i; + h_qp = hisi_qm_alloc_qp(&qm_priv, h_ctx); + if (!h_qp) { + WD_ERR("failed to alloc qp!\n"); + goto out; + } + } + + return 0; +out: + for (j = 0; j < i; j++) { + h_qp = (handle_t)wd_ctx_get_priv(config->ctxs[j].ctx); + hisi_qm_free_qp(h_qp); + } + + return -WD_EINVAL; +} + +static void hpre_exit(void *priv) +{ + struct hisi_hpre_ctx *hpre_ctx = (struct hisi_hpre_ctx *)priv; + struct wd_ctx_config_internal *config = &hpre_ctx->config; + handle_t h_qp; + int i; + + for (i = 0; i < config->ctx_num; i++) { + h_qp = (handle_t)wd_ctx_get_priv(config->ctxs[i].ctx); + hisi_qm_free_qp(h_qp); + } +} + +static int rsa_send(handle_t ctx, void *rsa_msg) +{ + handle_t h_qp = (handle_t)wd_ctx_get_priv(ctx); + struct wd_rsa_msg *msg = rsa_msg; + struct hisi_hpre_sqe hw_msg; + __u16 send_cnt = 0; + int ret; + + memset(&hw_msg, 0, sizeof(struct hisi_hpre_sqe)); + + if (msg->key_type == WD_RSA_PRIKEY1 || + msg->key_type == WD_RSA_PUBKEY) + hw_msg.alg = HPRE_ALG_NC_NCRT; + else if (msg->key_type == WD_RSA_PRIKEY2) + hw_msg.alg = HPRE_ALG_NC_CRT; + else + return -WD_EINVAL; + + hw_msg.task_len1 = msg->key_bytes / BYTE_BITS - 0x1; + + ret = rsa_prepare_key(msg, &hw_msg); + if (ret < 0) + return ret; + + /* prepare in/out put */ + ret = rsa_prepare_iot(msg, &hw_msg); + if (ret < 0) + return ret; + + hisi_set_msg_id(h_qp, &msg->tag); + hw_msg.done = 0x1; + hw_msg.etype = 0x0; + hw_msg.low_tag = msg->tag; + + return hisi_qm_send(h_qp, &hw_msg, 1, &send_cnt); +} + +static void hpre_result_check(struct hisi_hpre_sqe *hw_msg, + __u8 *result) +{ + *result = WD_SUCCESS; + + if (hw_msg->done != HPRE_HW_TASK_DONE || + hw_msg->etype || hw_msg->etype1) { + WD_ERR("failed to do hpre task! done=0x%x, etype=0x%x, etype1=0x%x!\n", + hw_msg->done, hw_msg->etype, hw_msg->etype1); + if (hw_msg->etype1 & HPRE_HW_SVA_ERROR) + WD_ERR("failed to SVA prefetch: status=%u!\n", + hw_msg->sva_status); + if (hw_msg->done == HPRE_HW_TASK_INIT) + *result = WD_EINVAL; + else + *result = WD_IN_EPARA; + } +} + +static int rsa_recv(handle_t ctx, void *rsa_msg) +{ + handle_t h_qp = (handle_t)wd_ctx_get_priv(ctx); + struct hisi_qp *qp = (struct hisi_qp *)h_qp; + struct hisi_hpre_sqe hw_msg = {0}; + struct wd_rsa_msg *msg = rsa_msg; + struct wd_rsa_msg *temp_msg; + __u16 recv_cnt = 0; + int ret; + + ret = hisi_qm_recv(h_qp, &hw_msg, 1, &recv_cnt); + if (ret < 0) + return ret; + + ret = hisi_check_bd_id(h_qp, msg->tag, hw_msg.low_tag); + if (ret) + return ret; + + msg->tag = LW_U16(hw_msg.low_tag); + if (qp->q_info.qp_mode == CTX_MODE_ASYNC) { + temp_msg = wd_rsa_get_msg(qp->q_info.idx, msg->tag); + if (!temp_msg) { + WD_ERR("failed to get send msg! idx = %u, tag = %u.\n", + qp->q_info.idx, msg->tag); + return -WD_EINVAL; + } + } else { + temp_msg = msg; + } + + hpre_result_check(&hw_msg, &msg->result); + if (!msg->result) { + ret = rsa_out_transfer(msg, &hw_msg, qp->q_info.qp_mode); + if (ret) { + WD_ERR("failed to transfer out rsa BD!\n"); + msg->result = WD_OUT_EPARA; + } + } + + if (unlikely(msg->result != WD_SUCCESS)) + dump_hpre_msg(temp_msg, "rsa"); + + return 0; +} + +static struct wd_rsa_driver rsa_hisi_hpre = { + .drv_name = "hisi_hpre", + .alg_name = "rsa", + .drv_ctx_size = sizeof(struct hisi_hpre_ctx), + .init = hpre_init, + .exit = hpre_exit, + .send = rsa_send, + .recv = rsa_recv, +}; + +static int fill_dh_xp_params(struct wd_dh_msg *msg, + struct hisi_hpre_sqe *hw_msg) +{ + struct wd_dh_req *req = &msg->req; + void *x, *p; + int ret; + + x = req->x_p; + p = req->x_p + msg->key_bytes; + ret = crypto_bin_to_hpre_bin(x, (const char *)x, + msg->key_bytes, req->xbytes, "dh x"); + if (ret) { + WD_ERR("failed to transfer dh x para format to hpre bin!\n"); + return ret; + } + + ret = crypto_bin_to_hpre_bin(p, (const char *)p, + msg->key_bytes, req->pbytes, "dh p"); + if (ret) { + WD_ERR("failed to transfer dh p para format to hpre bin!\n"); + return ret; + } + + hw_msg->low_key = LW_U32((uintptr_t)x); + hw_msg->hi_key = HI_U32((uintptr_t)x); + + return WD_SUCCESS; +} + +static int dh_out_transfer(struct wd_dh_msg *msg, + struct hisi_hpre_sqe *hw_msg, __u8 qp_mode) +{ + __u16 key_bytes = (hw_msg->task_len1 + 1) * BYTE_BITS; + struct wd_dh_req *req = &msg->req; + void *out; + int ret; + + /* async */ + if (qp_mode == CTX_MODE_ASYNC) + out = VA_ADDR(hw_msg->hi_out, hw_msg->low_out); + else + out = req->pri; + + ret = hpre_bin_to_crypto_bin((char *)out, + (const char *)out, key_bytes, "dh out"); + if (!ret) + return -WD_EINVAL; + + req->pri_bytes = ret; + + return WD_SUCCESS; +} + +static int dh_send(handle_t ctx, void *dh_msg) +{ + handle_t h_qp = (handle_t)wd_ctx_get_priv(ctx); + struct wd_dh_msg *msg = dh_msg; + struct wd_dh_req *req = &msg->req; + struct hisi_hpre_sqe hw_msg; + __u16 send_cnt = 0; + int ret; + + memset(&hw_msg, 0, sizeof(struct hisi_hpre_sqe)); + + if (msg->is_g2 && req->op_type != WD_DH_PHASE2) + hw_msg.alg = HPRE_ALG_DH_G2; + else + hw_msg.alg = HPRE_ALG_DH; + + hw_msg.task_len1 = msg->key_bytes / BYTE_BITS - 0x1; + + if (!(msg->is_g2 && req->op_type == WD_DH_PHASE1)) { + ret = crypto_bin_to_hpre_bin((char *)msg->g, + (const char *)msg->g, msg->key_bytes, + msg->gbytes, "dh g"); + if (ret) { + WD_ERR("failed to transfer dh g para format to hpre bin!\n"); + return ret; + } + + hw_msg.low_in = LW_U32((uintptr_t)msg->g); + hw_msg.hi_in = HI_U32((uintptr_t)msg->g); + } + + ret = fill_dh_xp_params(msg, &hw_msg); + if (ret) + return ret; + + hisi_set_msg_id(h_qp, &msg->tag); + hw_msg.low_out = LW_U32((uintptr_t)req->pri); + hw_msg.hi_out = HI_U32((uintptr_t)req->pri); + hw_msg.done = 0x1; + hw_msg.etype = 0x0; + hw_msg.low_tag = msg->tag; + + return hisi_qm_send(h_qp, &hw_msg, 1, &send_cnt); +} + +static int dh_recv(handle_t ctx, void *dh_msg) +{ + handle_t h_qp = (handle_t)wd_ctx_get_priv(ctx); + struct hisi_qp *qp = (struct hisi_qp *)h_qp; + struct wd_dh_msg *msg = dh_msg; + struct hisi_hpre_sqe hw_msg = {0}; + struct wd_dh_msg *temp_msg; + __u16 recv_cnt = 0; + int ret; + + ret = hisi_qm_recv(h_qp, &hw_msg, 1, &recv_cnt); + if (ret < 0) + return ret; + + ret = hisi_check_bd_id(h_qp, msg->tag, hw_msg.low_tag); + if (ret) + return ret; + + msg->tag = LW_U16(hw_msg.low_tag); + if (qp->q_info.qp_mode == CTX_MODE_ASYNC) { + temp_msg = wd_dh_get_msg(qp->q_info.idx, msg->tag); + if (!temp_msg) { + WD_ERR("failed to get send msg! idx = %u, tag = %u.\n", + qp->q_info.idx, msg->tag); + return -WD_EINVAL; + } + } else { + temp_msg = msg; + } + + hpre_result_check(&hw_msg, &msg->result); + if (!msg->result) { + ret = dh_out_transfer(msg, &hw_msg, qp->q_info.qp_mode); + if (ret) { + WD_ERR("failed to transfer out dh BD!\n"); + msg->result = WD_OUT_EPARA; + } + } + + if (unlikely(msg->result != WD_SUCCESS)) + dump_hpre_msg(temp_msg, "dh"); + + return 0; +} + +static struct wd_dh_driver dh_hisi_hpre = { + .drv_name = "hisi_hpre", + .alg_name = "dh", + .drv_ctx_size = sizeof(struct hisi_hpre_ctx), + .init = hpre_init, + .exit = hpre_exit, + .send = dh_send, + .recv = dh_recv, +}; + +static int ecc_prepare_alg(struct wd_ecc_msg *msg, + struct hisi_hpre_sqe *hw_msg) +{ + switch (msg->req.op_type) { + case WD_SM2_SIGN: + hw_msg->alg = HPRE_ALG_SM2_SIGN; + break; + case WD_ECDSA_SIGN: + hw_msg->alg = HPRE_ALG_ECDSA_SIGN; + break; + case WD_SM2_VERIFY: + hw_msg->alg = HPRE_ALG_SM2_VERF; + break; + case WD_ECDSA_VERIFY: + hw_msg->alg = HPRE_ALG_ECDSA_VERF; + break; + case WD_SM2_ENCRYPT: + hw_msg->alg = HPRE_ALG_SM2_ENC; + break; + case WD_SM2_DECRYPT: + hw_msg->alg = HPRE_ALG_SM2_DEC; + break; + case WD_SM2_KG: + hw_msg->alg = HPRE_ALG_SM2_KEY_GEN; + break; + case WD_ECXDH_GEN_KEY: /* fall through */ + case HPRE_SM2_ENC: /* fall through */ + case HPRE_SM2_DEC: /* fall through */ + case WD_ECXDH_COMPUTE_KEY: + if (msg->curve_id == WD_X448 || msg->curve_id == WD_X25519) + hw_msg->alg = HPRE_ALG_X_DH_MULTIPLY; + else + hw_msg->alg = HPRE_ALG_ECDH_MULTIPLY; + break; + default: + return -WD_EINVAL; + } + + return 0; +} + +static int trans_cv_param_to_hpre_bin(struct wd_dtb *p, struct wd_dtb *a, + struct wd_dtb *b, struct wd_dtb *n, + struct wd_ecc_point *g) +{ + int ret; + + ret = crypto_bin_to_hpre_bin(p->data, (const char *)p->data, + p->bsize, p->dsize, "cv p"); + if (ret) + return ret; + + ret = crypto_bin_to_hpre_bin(a->data, (const char *)a->data, + a->bsize, a->dsize, "cv a"); + if (ret) + return ret; + + ret = crypto_bin_to_hpre_bin(b->data, (const char *)b->data, + b->bsize, b->dsize, "cv b"); + if (ret) + return ret; + + ret = crypto_bin_to_hpre_bin(n->data, (const char *)n->data, + n->bsize, n->dsize, "cv n"); + if (ret) + return ret; + + ret = crypto_bin_to_hpre_bin(g->x.data, (const char *)g->x.data, + g->x.bsize, g->x.dsize, "cv gx"); + if (ret) + return ret; + + return crypto_bin_to_hpre_bin(g->y.data, (const char *)g->y.data, + g->y.bsize, g->y.dsize, "cv gy"); +} + +static int trans_d_to_hpre_bin(struct wd_dtb *d) +{ + return crypto_bin_to_hpre_bin(d->data, (const char *)d->data, + d->bsize, d->dsize, "ecc d"); +} + +static bool big_than_one(const char *data, __u32 data_sz) +{ + int i; + + for (i = 0; i < data_sz - 1; i++) { + if (data[i] > 0) + return true; + } + + if (data[i] == 0 || data[i] == 1) + return false; + + return true; +} + +static bool less_than_latter(struct wd_dtb *d, struct wd_dtb *n) +{ + int ret, shift; + + if (d->dsize > n->dsize) + return false; + else if (d->dsize < n->dsize) + return true; + + shift = n->bsize - n->dsize; + ret = memcmp(d->data + shift, n->data + shift, n->dsize); + if (ret < 0) + return true; + else + return false; +} + +static int ecc_prepare_prikey(struct wd_ecc_key *key, void **data, int id) +{ + struct wd_ecc_point *g = NULL; + struct wd_dtb *p = NULL; + struct wd_dtb *a = NULL; + struct wd_dtb *b = NULL; + struct wd_dtb *n = NULL; + struct wd_dtb *d = NULL; + char bsize, dsize; + char *dat; + int ret; + + wd_ecc_get_prikey_params((void *)key, &p, &a, &b, &n, &g, &d); + + ret = trans_cv_param_to_hpre_bin(p, a, b, n, g); + if (ret) + return ret; + + ret = trans_d_to_hpre_bin(d); + if (ret) + return ret; + + /* + * This is a pretreatment of X25519/X448, as described in RFC 7748: + * For X25519, in order to decode 32 random bytes as an integer + * scaler, set the three LSB of the first byte and MSB of the last + * to zero, set the second MSB of the last byte to 1. + * For X448, set the two LSB of the first byte to 0, and MSB of the + * last byte to 1. Decode in little-endian mode. + * HPRE hardware module uses big-endian mode, so the bytes to be + * set are reversed compared to RFC 7748: + * For example, dat[0] of X25519 in RFC 7748 is reversed to dat[31] + * in HPRE specification, so does X448. + */ + dat = d->data; + bsize = d->bsize; + dsize = d->dsize; + if (id == WD_X25519) { + dat[31] &= 248; + dat[0] &= 127; + dat[0] |= 64; + } else if (id == WD_X448) { + dat[55 + bsize - dsize] &= 252; + dat[0 + bsize - dsize] |= 128; + } + + if (!big_than_one(dat, bsize)) { + WD_ERR("failed to prepare ecc prikey: d <= 1!\n"); + return -WD_EINVAL; + } + + if (id != WD_X25519 && id != WD_X448 && + !less_than_latter(d, n)) { + WD_ERR("failed to prepare ecc prikey: d >= n!\n"); + return -WD_EINVAL; + } + + *data = p->data; + + return 0; +} + +static int trans_pub_to_hpre_bin(struct wd_ecc_point *pub) +{ + struct wd_dtb *temp; + int ret; + + temp = &pub->x; + ret = crypto_bin_to_hpre_bin(temp->data, (const char *)temp->data, + temp->bsize, temp->dsize, "ecc pub x"); + if (ret) + return ret; + + temp = &pub->y; + return crypto_bin_to_hpre_bin(temp->data, (const char *)temp->data, + temp->bsize, temp->dsize, "ecc pub y"); +} + +static int ecc_prepare_pubkey(struct wd_ecc_key *key, void **data) +{ + struct wd_ecc_point *pub = NULL; + struct wd_ecc_point *g = NULL; + struct wd_dtb *p = NULL; + struct wd_dtb *a = NULL; + struct wd_dtb *b = NULL; + struct wd_dtb *n = NULL; + int ret; + + wd_ecc_get_pubkey_params((void *)key, &p, &a, &b, &n, &g, &pub); + + ret = trans_cv_param_to_hpre_bin(p, a, b, n, g); + if (ret) + return ret; + + ret = trans_pub_to_hpre_bin(pub); + if (ret) + return ret; + + *data = p->data; + + return 0; +} + +static bool is_prikey_used(__u8 op_type) +{ + return op_type == WD_ECXDH_GEN_KEY || + op_type == WD_ECXDH_COMPUTE_KEY || + op_type == WD_ECDSA_SIGN || + op_type == WD_SM2_DECRYPT || + op_type == WD_SM2_SIGN || + op_type == HPRE_SM2_ENC || + op_type == HPRE_SM2_DEC; +} + +static int ecc_prepare_key(struct wd_ecc_msg *msg, + struct hisi_hpre_sqe *hw_msg) +{ + void *data = NULL; + int ret; + + if (is_prikey_used(msg->req.op_type)) { + ret = ecc_prepare_prikey((void *)msg->key, &data, msg->curve_id); + if (ret) + return ret; + } else { + ret = ecc_prepare_pubkey((void *)msg->key, &data); + if (ret) + return ret; + } + + hw_msg->low_key = LW_U32((uintptr_t)data); + hw_msg->hi_key = HI_U32((uintptr_t)data); + + return 0; +} + +static void ecc_get_io_len(__u32 atype, __u32 hsz, size_t *ilen, + size_t *olen) +{ + if (atype == HPRE_ALG_ECDH_MULTIPLY) { + *olen = ECDH_OUT_PARAMS_SZ(hsz); + *ilen = *olen; + } else if (atype == HPRE_ALG_X_DH_MULTIPLY) { + *olen = X_DH_OUT_PARAMS_SZ(hsz); + *ilen = *olen; + } else if (atype == HPRE_ALG_ECDSA_SIGN) { + *olen = ECC_SIGN_OUT_PARAMS_SZ(hsz); + *ilen = ECC_SIGN_IN_PARAMS_SZ(hsz); + } else if (atype == HPRE_ALG_ECDSA_VERF) { + *olen = ECC_VERF_OUT_PARAMS_SZ; + *ilen = ECC_VERF_IN_PARAMS_SZ(hsz); + } else { + *olen = hsz; + *ilen = hsz; + } +} + +static bool is_all_zero(struct wd_dtb *e, struct wd_ecc_msg *msg) +{ + int i; + + for (i = 0; i < e->dsize && i < msg->key_bytes; i++) { + if (e->data[i]) + return false; + } + + return true; +} + +static void correct_random(struct wd_dtb *k) +{ + int lens = k->bsize - k->dsize; + + k->data[lens] = 0; +} + +static int ecc_prepare_sign_in(struct wd_ecc_msg *msg, + struct hisi_hpre_sqe *hw_msg, void **data) +{ + struct wd_ecc_sign_in *in = msg->req.src; + struct wd_dtb *n = NULL; + struct wd_dtb *e, *k; + int ret; + + if (!in->dgst_set) { + WD_ERR("invalid: prepare sign_in, hash not set!\n"); + return -WD_EINVAL; + } + + e = &in->dgst; + k = &in->k; + if (!in->k_set) { + if (msg->req.op_type == WD_ECDSA_SIGN) { + WD_ERR("invalid: random k not set!\n"); + return -WD_EINVAL; + } + hw_msg->sm2_ksel = 1; + } else if (is_all_zero(k, msg)) { + WD_ERR("invalid: ecc sign in k all zero!\n"); + return -WD_EINVAL; + } + + if (is_all_zero(e, msg)) { + WD_ERR("invalid: ecc sign in e all zero!\n"); + return -WD_EINVAL; + } + + ret = crypto_bin_to_hpre_bin(e->data, (const char *)e->data, + e->bsize, e->dsize, "ecc sgn e"); + if (ret) + return ret; + + ret = crypto_bin_to_hpre_bin(k->data, (const char *)k->data, + k->bsize, k->dsize, "ecc sgn k"); + if (ret) + return ret; + + wd_ecc_get_prikey_params((void *)msg->key, NULL, NULL, NULL, + &n, NULL, NULL); + if (!less_than_latter(k, n)) + correct_random(k); + + *data = e->data; + + return 0; +} + +static int ecc_prepare_verf_in(struct wd_ecc_msg *msg, + struct hisi_hpre_sqe *hw_msg, void **data) + +{ + struct wd_ecc_verf_in *vin = msg->req.src; + struct wd_dtb *e, *s, *r; + int ret; + + if (!vin->dgst_set) { + WD_ERR("invalid: prepare verf_in, hash not set!\n"); + return -WD_EINVAL; + } + + e = &vin->dgst; + s = &vin->s; + r = &vin->r; + + if (is_all_zero(e, msg)) { + WD_ERR("invalid: ecc verf in e all zero!\n"); + return -WD_EINVAL; + } + + ret = crypto_bin_to_hpre_bin(e->data, (const char *)e->data, + e->bsize, e->dsize, "ecc vrf e"); + if (ret) + return ret; + + ret = crypto_bin_to_hpre_bin(s->data, (const char *)s->data, + s->bsize, s->dsize, "ecc vrf s"); + if (ret) + return ret; + + ret = crypto_bin_to_hpre_bin(r->data, (const char *)r->data, + r->bsize, r->dsize, "ecc vrf r"); + if (ret) + return ret; + + *data = e->data; + + return 0; +} + +static int sm2_prepare_enc_in(struct wd_ecc_msg *msg, + struct hisi_hpre_sqe *hw_msg, void **data) + +{ + struct wd_sm2_enc_in *ein = msg->req.src; + struct wd_dtb *k = &ein->k; + int ret; + + if (ein->k_set) { + ret = crypto_bin_to_hpre_bin(k->data, (const char *)k->data, + k->bsize, k->dsize, "sm2 encode k"); + if (ret) + return ret; + } else { + hw_msg->sm2_ksel = 1; + } + + hw_msg->sm2_mlen = ein->plaintext.dsize - 1; + *data = k->data; + + return 0; +} + +static int sm2_prepare_dec_in(struct wd_ecc_msg *msg, + struct hisi_hpre_sqe *hw_msg, void **data) + +{ + struct wd_sm2_dec_in *din = msg->req.src; + struct wd_ecc_point *c1 = &din->c1; + int ret; + + ret = crypto_bin_to_hpre_bin(c1->x.data, (const char *)c1->x.data, + c1->x.bsize, c1->x.dsize, "sm2 decode c1 x"); + if (ret) + return ret; + + ret = crypto_bin_to_hpre_bin(c1->y.data, (const char *)c1->y.data, + c1->y.bsize, c1->y.dsize, "sm2 decode c1 y"); + if (ret) + return ret; + + hw_msg->sm2_mlen = din->c2.dsize - 1; + *data = c1->x.data; + + return 0; +} + +static int ecc_prepare_dh_gen_in(struct wd_ecc_msg *msg, + struct hisi_hpre_sqe *hw_msg, void **data) +{ + struct wd_ecc_point *in = msg->req.src; + int ret; + + ret = crypto_bin_to_hpre_bin(in->x.data, (const char *)in->x.data, + in->x.bsize, in->x.dsize, "ecdh gen x"); + if (ret) + return ret; + + ret = crypto_bin_to_hpre_bin(in->y.data, (const char *)in->y.data, + in->y.bsize, in->y.dsize, "ecdh gen y"); + if (ret) + return ret; + + *data = in->x.data; + + return 0; +} + +static int ecc_prepare_dh_compute_in(struct wd_ecc_msg *msg, + struct hisi_hpre_sqe *hw_msg, void **data) +{ + struct wd_ecc_dh_in *dh_in = msg->req.src; + struct wd_ecc_point *pbk = &dh_in->pbk; + int ret; + + ret = crypto_bin_to_hpre_bin(pbk->x.data, (const char *)pbk->x.data, + pbk->x.bsize, pbk->x.dsize, "ecdh compute x"); + if (ret) + return ret; + + ret = crypto_bin_to_hpre_bin(pbk->y.data, (const char *)pbk->y.data, + pbk->y.bsize, pbk->y.dsize, "ecdh compute y"); + if (ret) + return ret; + + *data = pbk->x.data; + + return 0; +} + +static int u_is_in_p(struct wd_ecc_msg *msg) +{ + struct wd_ecc_in *ecc_in = (struct wd_ecc_in *)msg->req.src; + struct wd_ecc_dh_in *in = &ecc_in->param.dh_in; + struct wd_ecc_point *pbk = &in->pbk; + struct wd_dtb *p = NULL; + + wd_ecc_get_prikey_params((void *)msg->key, &p, NULL, NULL, NULL, + NULL, NULL); + if (unlikely(!p)) { + WD_ERR("failed to get param p!\n"); + return -WD_EINVAL; + } + /* + * In big-endian order, when receiving u-array, implementations + * of X25519 (but not X448) should mask the most significant bit + * in the 1st byte. + * See RFC7748 for details. + */ + if (msg->curve_id == WD_X25519) + pbk->x.data[0] &= 0x7f; + if (!less_than_latter(&pbk->x, p)) { + WD_ERR("invalid: ux is out of p!\n"); + return -WD_EINVAL; + } + + if (is_all_zero(&pbk->x, msg)) { + WD_ERR("invalid: ux is zero!\n"); + return -WD_EINVAL; + } + + return 0; +} + +static int ecc_prepare_in(struct wd_ecc_msg *msg, + struct hisi_hpre_sqe *hw_msg, void **data) +{ + int ret = -WD_EINVAL; + + switch (msg->req.op_type) { + case HPRE_SM2_ENC: /* fall through */ + case HPRE_SM2_DEC: + /* driver to identify sm2 algorithm when async receive */ + hw_msg->sm2_mlen = msg->req.op_type; + hw_msg->bd_rsv2 = 1; /* fall through */ + case WD_SM2_KG: /* fall through */ + case WD_ECXDH_GEN_KEY: + ret = ecc_prepare_dh_gen_in(msg, hw_msg, data); + break; + case WD_ECXDH_COMPUTE_KEY: + ret = ecc_prepare_dh_compute_in(msg, hw_msg, data); + if (!ret && (msg->curve_id == WD_X25519 || + msg->curve_id == WD_X448)) + ret = u_is_in_p(msg); + break; + case WD_ECDSA_SIGN: /* fall through */ + case WD_SM2_SIGN: + ret = ecc_prepare_sign_in(msg, hw_msg, data); + break; + case WD_ECDSA_VERIFY: /* fall through */ + case WD_SM2_VERIFY: + ret = ecc_prepare_verf_in(msg, hw_msg, data); + break; + case WD_SM2_ENCRYPT: + ret = sm2_prepare_enc_in(msg, hw_msg, data); + break; + case WD_SM2_DECRYPT: + ret = sm2_prepare_dec_in(msg, hw_msg, data); + break; + default: + break; + } + + return ret; +} + +static int ecc_prepare_dh_out(struct wd_ecc_out *out, void **data) +{ + struct wd_ecc_point *dh_out = NULL; + + wd_ecxdh_get_out_params(out, &dh_out); + if (!dh_out) { + WD_ERR("failed to get ecxdh out param!\n"); + return -WD_EINVAL; + } + + *data = dh_out->x.data; + + return 0; +} + +static int ecc_prepare_out(struct wd_ecc_msg *msg, void **data) +{ + struct wd_ecc_out *out = (struct wd_ecc_out *)msg->req.dst; + struct wd_ecc_sign_out *sout = &out->param.sout; + struct wd_sm2_enc_out *eout = &out->param.eout; + struct wd_sm2_dec_out *dout = &out->param.dout; + struct wd_sm2_kg_out *kout = &out->param.kout; + int ret = 0; + + switch (msg->req.op_type) { + case WD_ECXDH_GEN_KEY: /* fall through */ + case HPRE_SM2_ENC: /* fall through */ + case HPRE_SM2_DEC: /* fall through */ + case WD_ECXDH_COMPUTE_KEY: + ret = ecc_prepare_dh_out(out, data); + break; + case WD_ECDSA_SIGN: + case WD_SM2_SIGN: + *data = sout->r.data; + break; + case WD_ECDSA_VERIFY: + case WD_SM2_VERIFY: + break; + case WD_SM2_ENCRYPT: + *data = eout->c1.x.data; + break; + case WD_SM2_DECRYPT: + *data = dout->plaintext.data; + break; + case WD_SM2_KG: + *data = kout->pub.x.data; + break; + default: + break; + } + + return ret; +} + +/* prepare in/out hw message */ +static int ecc_prepare_iot(struct wd_ecc_msg *msg, + struct hisi_hpre_sqe *hw_msg) +{ + void *data = NULL; + size_t i_sz = 0; + size_t o_sz = 0; + __u16 kbytes; + int ret; + + kbytes = msg->key_bytes; + ecc_get_io_len(hw_msg->alg, kbytes, &i_sz, &o_sz); + ret = ecc_prepare_in(msg, hw_msg, &data); + if (ret) { + WD_ERR("failed to prepare ecc in!\n"); + return ret; + } + hw_msg->low_in = LW_U32((uintptr_t)data); + hw_msg->hi_in = HI_U32((uintptr_t)data); + + ret = ecc_prepare_out(msg, &data); + if (ret) { + WD_ERR("failed to prepare ecc out!\n"); + return ret; + } + + if (!data) + return 0; + + hw_msg->low_out = LW_U32((uintptr_t)data); + hw_msg->hi_out = HI_U32((uintptr_t)data); + + return 0; +} + +static __u32 get_hw_keysz(__u32 ksz) +{ + __u32 size = 0; + + if (ksz <= BITS_TO_BYTES(256)) + size = BITS_TO_BYTES(256); + else if (ksz <= BITS_TO_BYTES(384)) + size = BITS_TO_BYTES(384); + else if (ksz <= BITS_TO_BYTES(576)) + size = BITS_TO_BYTES(576); + else + WD_ERR("invalid: keysize %u is error!\n", ksz); + + return size; +} + +static void init_prikey(struct wd_ecc_prikey *prikey, __u32 bsz) +{ + prikey->p.dsize = 0; + prikey->p.bsize = bsz; + prikey->p.data = prikey->data; + prikey->a.dsize = 0; + prikey->a.bsize = bsz; + prikey->a.data = prikey->p.data + bsz; + prikey->d.dsize = 0; + prikey->d.bsize = bsz; + prikey->d.data = prikey->a.data + bsz; + prikey->b.dsize = 0; + prikey->b.bsize = bsz; + prikey->b.data = prikey->d.data + bsz; + prikey->n.dsize = 0; + prikey->n.bsize = bsz; + prikey->n.data = prikey->b.data + bsz; + prikey->g.x.dsize = 0; + prikey->g.x.bsize = bsz; + prikey->g.x.data = prikey->n.data + bsz; + prikey->g.y.dsize = 0; + prikey->g.y.bsize = bsz; + prikey->g.y.data = prikey->g.x.data + bsz; +} + +static int set_param(struct wd_dtb *dst, const struct wd_dtb *src, + const char *p_name) +{ + if (unlikely(!src || !src->data)) { + WD_ERR("invalid: %s src or data NULL!\n", p_name); + return -WD_EINVAL; + } + + if (unlikely(!src->dsize || src->dsize > dst->bsize)) { + WD_ERR("invalid: %s src dsz %u, dst bsz %u is error!\n", + p_name, src->dsize, dst->bsize); + return -WD_EINVAL; + } + + dst->dsize = src->dsize; + memset(dst->data, 0, dst->bsize); + memcpy(dst->data, src->data, src->dsize); + + return 0; +} + +static int set_prikey(struct wd_ecc_prikey *prikey, + struct wd_ecc_msg *msg) +{ + struct wd_ecc_key *key = (struct wd_ecc_key *)msg->key; + struct wd_ecc_pubkey *pubkey = key->pubkey; + struct wd_sm2_enc_in *ein = msg->req.src; + int ret; + + ret = set_param(&prikey->p, &pubkey->p, "p"); + if (unlikely(ret)) + return ret; + + ret = set_param(&prikey->a, &pubkey->a, "a"); + if (unlikely(ret)) + return ret; + + ret = set_param(&prikey->d, &ein->k, "k"); + if (unlikely(ret)) + return ret; + + ret = set_param(&prikey->b, &pubkey->b, "b"); + if (unlikely(ret)) + return ret; + + ret = set_param(&prikey->n, &pubkey->n, "n"); + if (unlikely(ret)) + return ret; + + ret = set_param(&prikey->g.x, &pubkey->g.x, "gx"); + if (unlikely(ret)) + return ret; + + return set_param(&prikey->g.y, &pubkey->g.y, "gy"); +} + +static struct wd_ecc_out *create_ecdh_out(struct wd_ecc_msg *msg) +{ + __u32 hsz = get_hw_keysz(msg->key_bytes); + __u32 data_sz = ECDH_OUT_PARAMS_SZ(hsz); + __u32 len = sizeof(struct wd_ecc_out) + data_sz + + sizeof(struct wd_ecc_msg *); + struct wd_ecc_dh_out *dh_out; + struct wd_ecc_out *out; + + if (!hsz) { + WD_ERR("failed to get msg key size!\n"); + return NULL; + } + + out = malloc(len); + if (!out) { + WD_ERR("failed to alloc out memory, sz = %u!\n", len); + return NULL; + } + + out->size = data_sz; + dh_out = (void *)out; + dh_out->out.x.data = out->data; + dh_out->out.x.dsize = msg->key_bytes; + dh_out->out.x.bsize = hsz; + dh_out->out.y.data = out->data; + dh_out->out.y.dsize = msg->key_bytes; + dh_out->out.y.bsize = hsz; + out->size = data_sz; + + memcpy(out->data + data_sz, &msg, sizeof(void *)); + + return out; +} + +static int init_req(struct wd_ecc_msg *dst, struct wd_ecc_msg *src, + struct wd_ecc_key *key, __u8 req_idx) +{ + struct wd_ecc_key *ecc_key = (struct wd_ecc_key *)src->key; + struct wd_ecc_pubkey *pubkey = ecc_key->pubkey; + + memcpy(dst, src, sizeof(*dst)); + memcpy(dst + 1, src, sizeof(struct wd_ecc_msg)); + dst->key = (void *)key; + dst->req.op_type = HPRE_SM2_ENC; + + dst->req.dst = create_ecdh_out(dst); + if (unlikely(!dst->req.dst)) + return -WD_ENOMEM; + + if (!req_idx) + dst->req.src = (void *)&pubkey->g; + else + dst->req.src = (void *)&pubkey->pub; + + return 0; +} + +static struct wd_ecc_msg *create_req(struct wd_ecc_msg *src, __u8 req_idx) +{ + struct wd_ecc_prikey *prikey; + struct wd_ecc_key *ecc_key; + struct wd_ecc_msg *dst; + int ret; + + dst = malloc(sizeof(*dst) + sizeof(*src)); + if (unlikely(!dst)) { + WD_ERR("failed to alloc dst!\n"); + return NULL; + } + + ecc_key = malloc(sizeof(*ecc_key) + sizeof(*prikey)); + if (unlikely(!ecc_key)) { + WD_ERR("failed to alloc ecc_key!\n"); + goto fail_alloc_key; + } + + prikey = (struct wd_ecc_prikey *)(ecc_key + 1); + ecc_key->prikey = prikey; + prikey->data = malloc(ECC_PRIKEY_SZ(src->key_bytes)); + if (unlikely(!prikey->data)) { + WD_ERR("failed to alloc prikey data!\n"); + goto fail_alloc_key_data; + } + init_prikey(prikey, src->key_bytes); + ret = set_prikey(prikey, src); + if (unlikely(ret)) + goto fail_set_prikey; + + ret = init_req(dst, src, ecc_key, req_idx); + if (unlikely(ret)) { + WD_ERR("failed to init req, ret = %d!\n", ret); + goto fail_set_prikey; + } + + return dst; + +fail_set_prikey: + free(prikey->data); +fail_alloc_key_data: + free(ecc_key); +fail_alloc_key: + free(dst); + + return NULL; +} + +static void free_req(struct wd_ecc_msg *msg) +{ + struct wd_ecc_key *key = (void *)msg->key; + + free(key->prikey->data); + free(key); + free(msg->req.dst); + free(msg); +} + +static int split_req(struct wd_ecc_msg *src, struct wd_ecc_msg **dst) +{ + /* k * G */ + dst[0] = create_req(src, 0); + if (unlikely(!dst[0])) + return -WD_ENOMEM; + + /* k * pub */ + dst[1] = create_req(src, 1); + if (unlikely(!dst[1])) { + free_req(dst[0]); + return -WD_ENOMEM; + } + + return 0; +} + +static int ecc_fill(struct wd_ecc_msg *msg, struct hisi_hpre_sqe *hw_msg) +{ + __u32 hw_sz = get_hw_keysz(msg->key_bytes); + __u8 op_type = msg->req.op_type; + int ret; + + if (unlikely(!op_type || (op_type >= WD_EC_OP_MAX && + op_type != HPRE_SM2_ENC && op_type != HPRE_SM2_DEC))) { + WD_ERR("invalid: input op_type %u is error!\n", op_type); + return -WD_EINVAL; + } + + if (!hw_sz) { + WD_ERR("failed to get msg key size!\n"); + return -WD_EINVAL; + } + + memset(hw_msg, 0, sizeof(*hw_msg)); + + /* prepare algorithm */ + ret = ecc_prepare_alg(msg, hw_msg); + if (ret) + return ret; + + /* prepare key */ + ret = ecc_prepare_key(msg, hw_msg); + if (ret) + return ret; + + /* prepare in/out put */ + ret = ecc_prepare_iot(msg, hw_msg); + if (ret) + return ret; + + hw_msg->done = 0x1; + hw_msg->etype = 0x0; + hw_msg->low_tag = msg->tag; + hw_msg->task_len1 = hw_sz / BYTE_BITS - 0x1; + + return ret; +} + +static int ecc_general_send(handle_t ctx, struct wd_ecc_msg *msg) +{ + handle_t h_qp = (handle_t)wd_ctx_get_priv(ctx); + struct hisi_hpre_sqe hw_msg; + __u16 send_cnt = 0; + int ret; + + ret = ecc_fill(msg, &hw_msg); + if (ret) + return ret; + + return hisi_qm_send(h_qp, &hw_msg, 1, &send_cnt); +} + + +static int sm2_enc_send(handle_t ctx, struct wd_ecc_msg *msg) +{ + handle_t h_qp = (handle_t)wd_ctx_get_priv(ctx); + struct wd_sm2_enc_in *ein = msg->req.src; + struct wd_ecc_msg *msg_dst[2] = {NULL}; + struct hisi_hpre_sqe hw_msg[2] = {0}; + struct wd_hash_mt *hash = &msg->hash; + __u16 send_cnt = 0; + int ret; + + if (ein->plaintext.dsize <= HW_PLAINTEXT_BYTES_MAX && + hash->type == WD_HASH_SM3) + return ecc_general_send(ctx, msg); + + if (unlikely(!ein->k_set)) { + WD_ERR("invalid: k not set!\n"); + return -WD_EINVAL; + } + + if (unlikely(!hash->cb || hash->type >= WD_HASH_MAX)) { + WD_ERR("invalid: input hash type %u is error!\n", hash->type); + return -WD_EINVAL; + } + + /* + * split message into two inner request message + * first message used to compute k * g + * second message used to compute k * pb + */ + ret = split_req(msg, msg_dst); + if (unlikely(ret)) { + WD_ERR("failed to split req, ret = %d!\n", ret); + return ret; + } + + ret = ecc_fill(msg_dst[0], &hw_msg[0]); + if (unlikely(ret)) { + WD_ERR("failed to fill 1th sqe, ret = %d!\n", ret); + goto fail_fill_sqe; + } + + ret = ecc_fill(msg_dst[1], &hw_msg[1]); + if (unlikely(ret)) { + WD_ERR("failed to fill 2th sqe, ret = %d!\n", ret); + goto fail_fill_sqe; + } + + ret = hisi_qm_get_free_sqe_num(h_qp); + if (ret < SM2_SQE_NUM) { + ret = -WD_EBUSY; + goto fail_fill_sqe; + } + + ret = hisi_qm_send(h_qp, &hw_msg, SM2_SQE_NUM, &send_cnt); + if (unlikely(ret)) + goto fail_fill_sqe; + + return ret; + +fail_fill_sqe: + free_req(msg_dst[0]); + free_req(msg_dst[1]); + + return ret; +} + +static int sm2_dec_send(handle_t ctx, struct wd_ecc_msg *msg) +{ + struct wd_sm2_dec_in *din = (void *)msg->req.src; + struct wd_hash_mt *hash = &msg->hash; + struct wd_ecc_msg *dst; + int ret; + + /* c2 data lens <= 4096 bit */ + if (din->c2.dsize <= BITS_TO_BYTES(4096) && + hash->type == WD_HASH_SM3) + return ecc_general_send(ctx, msg); + + if (unlikely(!hash->cb || hash->type >= WD_HASH_MAX)) { + WD_ERR("invalid: input hash type %u is error!\n", hash->type); + return -WD_EINVAL; + } + + /* dst last store point "struct wd_ecc_msg *" */ + dst = malloc(sizeof(*dst) + sizeof(*msg)); + if (unlikely(!dst)) + return -WD_ENOMEM; + + /* compute d * c1 */ + memcpy(dst, msg, sizeof(*dst)); + memcpy(dst + 1, msg, sizeof(struct wd_ecc_msg)); + + dst->req.op_type = HPRE_SM2_DEC; + dst->req.src = (void *)&din->c1; + + /* dst->req.dst last store point "struct wd_ecc_msg *" */ + dst->req.dst = create_ecdh_out(dst); + if (unlikely(!dst->req.dst)) { + ret = -WD_ENOMEM; + goto free_dst; + } + + ret = ecc_general_send(ctx, dst); + if (unlikely(ret)) + goto free_req_dst; + + return ret; + +free_req_dst: + free(dst->req.dst); +free_dst: + free(dst); + return ret; +} + +static int ecc_send(handle_t ctx, void *ecc_msg) +{ + handle_t h_qp = (handle_t)wd_ctx_get_priv(ctx); + struct wd_ecc_msg *msg = ecc_msg; + + hisi_set_msg_id(h_qp, &msg->tag); + if (msg->req.op_type == WD_SM2_ENCRYPT) + return sm2_enc_send(ctx, msg); + else if (msg->req.op_type == WD_SM2_DECRYPT) + return sm2_dec_send(ctx, msg); + + return ecc_general_send(ctx, msg); +} + +static int ecdh_out_transfer(struct wd_ecc_msg *msg, struct hisi_hpre_sqe *hw_msg) +{ + struct wd_ecc_out *out = (void *)msg->req.dst; + struct wd_ecc_point *key = NULL; + struct wd_dtb *y = NULL; + int ret; + + if (msg->req.op_type == HPRE_SM2_DEC || + msg->req.op_type == HPRE_SM2_ENC) + return WD_SUCCESS; + + wd_ecxdh_get_out_params(out, &key); + + if (hw_msg->alg == HPRE_ALG_ECDH_MULTIPLY) + y = &key->y; + + ret = hpre_tri_bin_transfer(&key->x, y, NULL); + if (ret) { + WD_ERR("failed to transfer ecdh format to crypto bin!\n"); + return ret; + } + + return WD_SUCCESS; +} + +static int ecc_sign_out_transfer(struct wd_ecc_msg *msg, + struct hisi_hpre_sqe *hw_msg) +{ + struct wd_ecc_out *out = (void *)msg->req.dst; + struct wd_dtb *r = NULL; + struct wd_dtb *s = NULL; + int ret; + + wd_sm2_get_sign_out_params(out, &r, &s); + if (!r || !s) { + WD_ERR("failed to get ecc sign out param!\n"); + return -WD_EINVAL; + } + + ret = hpre_tri_bin_transfer(r, s, NULL); + if (ret) + WD_ERR("failed to tri ecc sign out r&s!\n"); + + return ret; +} + +static int ecc_verf_out_transfer(struct wd_ecc_msg *msg, + struct hisi_hpre_sqe *hw_msg) +{ + __u32 result = hw_msg->low_out; + + result >>= 1; + result &= 1; + if (!result) + msg->result = WD_VERIFY_ERR; + + return WD_SUCCESS; +} + +static int sm2_kg_out_transfer(struct wd_ecc_msg *msg, + struct hisi_hpre_sqe *hw_msg) +{ + struct wd_ecc_out *out = (void *)msg->req.dst; + struct wd_ecc_point *pbk = NULL; + struct wd_dtb *prk = NULL; + int ret; + + wd_sm2_get_kg_out_params(out, &prk, &pbk); + if (!prk || !pbk) { + WD_ERR("failed to get sm2 kg out param!\n"); + return -WD_EINVAL; + } + + ret = hpre_tri_bin_transfer(prk, &pbk->x, &pbk->y); + if (ret) + WD_ERR("failed to tri sm2 kg out param!\n"); + + return ret; +} + +static int sm2_enc_out_transfer(struct wd_ecc_msg *msg, + struct hisi_hpre_sqe *hw_msg) +{ + struct wd_ecc_out *out = (void *)msg->req.dst; + struct wd_ecc_point *c1 = NULL; + int ret; + + wd_sm2_get_enc_out_params(out, &c1, NULL, NULL); + if (!c1) { + WD_ERR("failed to get sm2 encode out param!\n"); + return -WD_EINVAL; + } + + ret = hpre_tri_bin_transfer(&c1->x, &c1->y, NULL); + if (ret) + WD_ERR("failed to tri sm2 encode out param!\n"); + + return ret; +} + +static int ecc_out_transfer(struct wd_ecc_msg *msg, + struct hisi_hpre_sqe *hw_msg, __u8 qp_mode) +{ + int ret = -WD_EINVAL; + void *va; + + /* async */ + if (qp_mode == CTX_MODE_ASYNC) { + va = VA_ADDR(hw_msg->hi_out, hw_msg->low_out); + msg->req.dst = container_of(va, struct wd_ecc_out, data); + } + + if (hw_msg->alg == HPRE_ALG_SM2_SIGN || + hw_msg->alg == HPRE_ALG_ECDSA_SIGN) + ret = ecc_sign_out_transfer(msg, hw_msg); + else if (hw_msg->alg == HPRE_ALG_SM2_VERF || + hw_msg->alg == HPRE_ALG_ECDSA_VERF) + ret = ecc_verf_out_transfer(msg, hw_msg); + else if (hw_msg->alg == HPRE_ALG_SM2_ENC) + ret = sm2_enc_out_transfer(msg, hw_msg); + else if (hw_msg->alg == HPRE_ALG_SM2_DEC) + ret = 0; + else if (hw_msg->alg == HPRE_ALG_SM2_KEY_GEN) + ret = sm2_kg_out_transfer(msg, hw_msg); + else if (hw_msg->alg == HPRE_ALG_ECDH_MULTIPLY || + hw_msg->alg == HPRE_ALG_X_DH_MULTIPLY) + ret = ecdh_out_transfer(msg, hw_msg); + else + WD_ERR("invalid: algorithm type %u is error!\n", hw_msg->alg); + + return ret; +} + + +static __u32 get_hash_bytes(__u8 type) +{ + __u32 val = 0; + + switch (type) { + case WD_HASH_SHA1: + val = BITS_TO_BYTES(160); + break; + case WD_HASH_SHA256: /* fall through */ + case WD_HASH_SM3: + val = BITS_TO_BYTES(256); + break; + case WD_HASH_MD4: /* fall through */ + case WD_HASH_MD5: + val = BITS_TO_BYTES(128); + break; + case WD_HASH_SHA224: + val = BITS_TO_BYTES(224); + break; + case WD_HASH_SHA384: + val = BITS_TO_BYTES(384); + break; + case WD_HASH_SHA512: + val = BITS_TO_BYTES(512); + break; + default: + WD_ERR("invalid: hash type %u is error!\n", type); + break; + } + + return val; +} + +static void msg_pack(char *dst, __u64 *out_len, + const void *src, __u32 src_len) +{ + if (unlikely(!src || !src_len)) + return; + + memcpy(dst + *out_len, src, src_len); + *out_len += src_len; +} + +static int sm2_kdf(struct wd_dtb *out, struct wd_ecc_point *x2y2, + __u64 mt_len, struct wd_hash_mt *hash) +{ + char p_out[MAX_HASH_LENS] = {0}; + __u32 h_bytes, x2y2_len; + char *tmp = out->data; + __u64 m_len = mt_len; + __u64 in_len, lens; + char *p_in, *t_out; + __u8 ctr[4]; + __u32 i = 1; + int ret; + + h_bytes = get_hash_bytes(hash->type); + if (unlikely(!h_bytes)) + return -WD_EINVAL; + + x2y2_len = x2y2->x.dsize + x2y2->y.dsize; + lens = x2y2_len + sizeof(ctr); + p_in = malloc(lens); + if (unlikely(!p_in)) + return -WD_ENOMEM; + + /* + * Use big-endian mode to store the value of counter i in ctr, + * i >> 8/16/24 for intercepts 8-bits whole-byte data. + */ + out->dsize = m_len; + while (1) { + in_len = 0; + ctr[3] = i & 0xFF; + ctr[2] = (i >> 8) & 0xFF; + ctr[1] = (i >> 16) & 0xFF; + ctr[0] = (i >> 24) & 0xFF; + msg_pack(p_in, &in_len, x2y2->x.data, x2y2_len); + msg_pack(p_in, &in_len, ctr, sizeof(ctr)); + + t_out = m_len >= h_bytes ? tmp : p_out; + ret = hash->cb(p_in, in_len, t_out, h_bytes, hash->usr); + if (ret) { + WD_ERR("%s failed to do hash cb, ret = %d!\n", __func__, ret); + break; + } + + if (m_len >= h_bytes) { + tmp += h_bytes; + m_len -= h_bytes; + if (!m_len) + break; + } else { + memcpy(tmp, p_out, m_len); + break; + } + + i++; + } + + free(p_in); + + return ret; +} + +static void sm2_xor(struct wd_dtb *val1, struct wd_dtb *val2) +{ + int i; + + for (i = 0; i < val1->dsize; ++i) + val1->data[i] = (char)((__u8)val1->data[i] ^ + (__u8)val2->data[i]); +} + +static int is_equal(struct wd_dtb *src, struct wd_dtb *dst) +{ + if (src->dsize == dst->dsize && + !memcmp(src->data, dst->data, src->dsize)) { + return 0; + } + + return -WD_EINVAL; +} + +static int sm2_hash(struct wd_dtb *out, struct wd_ecc_point *x2y2, + struct wd_dtb *msg, struct wd_hash_mt *hash) +{ + __u64 lens = (__u64)msg->dsize + 2 * (__u64)x2y2->x.dsize; + char hash_out[MAX_HASH_LENS] = {0}; + __u64 in_len = 0; + __u32 h_bytes; + char *p_in; + int ret; + + h_bytes = get_hash_bytes(hash->type); + if (unlikely(!h_bytes)) + return -WD_EINVAL; + + p_in = malloc(lens); + if (unlikely(!p_in)) + return -WD_ENOMEM; + + msg_pack(p_in, &in_len, x2y2->x.data, x2y2->x.dsize); + msg_pack(p_in, &in_len, msg->data, msg->dsize); + msg_pack(p_in, &in_len, x2y2->y.data, x2y2->y.dsize); + ret = hash->cb(p_in, in_len, hash_out, h_bytes, hash->usr); + if (unlikely(ret)) { + WD_ERR("%s failed to do hash cb, ret = %d!\n", __func__, ret); + goto fail; + } + + out->dsize = h_bytes; + memcpy(out->data, hash_out, out->dsize); + +fail: + free(p_in); + + return ret; +} + +static int sm2_convert_enc_out(struct wd_ecc_msg *src, + struct wd_ecc_msg *first, + struct wd_ecc_msg *second) +{ + struct wd_ecc_out *out = (void *)src->req.dst; + struct wd_ecc_in *in = (void *)src->req.src; + struct wd_sm2_enc_out *eout = &out->param.eout; + struct wd_sm2_enc_in *ein = &in->param.ein; + struct wd_hash_mt *hash = &src->hash; + struct wd_ecc_dh_out *dh_out; + __u32 ksz = src->key_bytes; + struct wd_ecc_point x2y2; + struct wd_dtb *kdf_out; + int ret; + + /* + * encode origin out data format: + * | x1y1(2*256bit) | x2y2(2*256bit) | other | + * final out data format: + * | c1(2*256bit) | c2(plaintext size) | c3(256bit) | + */ + dh_out = second->req.dst; + x2y2.x.data = (void *)dh_out->out.x.data; + x2y2.x.dsize = ksz; + x2y2.y.dsize = ksz; + x2y2.y.data = (void *)(x2y2.x.data + ksz); + + /* C1 */ + dh_out = first->req.dst; + memcpy(eout->c1.x.data, dh_out->out.x.data, ksz + ksz); + + /* C3 = hash(x2 || M || y2) */ + ret = sm2_hash(&eout->c3, &x2y2, &ein->plaintext, hash); + if (unlikely(ret)) { + WD_ERR("failed to do sm2 hash, ret = %d!\n", ret); + return ret; + } + + /* t = KDF(x2 || y2, klen) */ + kdf_out = &eout->c2; + ret = sm2_kdf(kdf_out, &x2y2, ein->plaintext.dsize, hash); + if (unlikely(ret)) { + WD_ERR("%s failed to do sm2 kdf, ret = %d!\n", __func__, ret); + return ret; + } + + /* C2 = M XOR t */ + sm2_xor(kdf_out, &ein->plaintext); + + return ret; +} + +static int sm2_convert_dec_out(struct wd_ecc_msg *src, + struct wd_ecc_msg *dst) +{ + struct wd_ecc_out *out = (void *)src->req.dst; + struct wd_sm2_dec_out *dout = &out->param.dout; + struct wd_ecc_in *in = (void *)src->req.src; + struct wd_sm2_dec_in *din = &in->param.din; + struct wd_ecc_dh_out *dh_out; + __u32 ksz = dst->key_bytes; + struct wd_ecc_point x2y2; + struct wd_dtb tmp = {0}; + char buff[64] = {0}; + int ret; + + /* + * decode origin out data format: + * | x2y2(2*256bit) | other | + * final out data format: + * | plaintext | + */ + + dh_out = dst->req.dst; + x2y2.x.data = (void *)dh_out->out.x.data; + x2y2.y.data = (void *)(x2y2.x.data + ksz); + x2y2.x.dsize = ksz; + x2y2.y.dsize = ksz; + + tmp.data = buff; + + /* t = KDF(x2 || y2, klen) */ + ret = sm2_kdf(&dout->plaintext, &x2y2, din->c2.dsize, &src->hash); + if (unlikely(ret)) { + WD_ERR("%s failed to do sm2 kdf, ret = %d!\n", __func__, ret); + return ret; + } + + /* M' = C2 XOR t */ + sm2_xor(&dout->plaintext, &din->c2); + + /* u = hash(x2 || M' || y2), save u to din->c2 */ + ret = sm2_hash(&tmp, &x2y2, &dout->plaintext, &src->hash); + if (unlikely(ret)) { + WD_ERR("failed to compute c3, ret = %d!\n", ret); + return ret; + } + + /* u == c3 */ + ret = is_equal(&tmp, &din->c3); + if (ret) + WD_ERR("failed to decode sm2, u != C3!\n"); + + return ret; +} + +static int ecc_sqe_parse(struct hisi_qp *qp, struct wd_ecc_msg *msg, + struct hisi_hpre_sqe *hw_msg) +{ + struct wd_ecc_msg *temp_msg; + int ret; + + msg->tag = LW_U16(hw_msg->low_tag); + if (qp->q_info.qp_mode == CTX_MODE_ASYNC) { + temp_msg = wd_ecc_get_msg(qp->q_info.idx, msg->tag); + if (!temp_msg) { + WD_ERR("failed to get send msg! idx = %u, tag = %u.\n", + qp->q_info.idx, msg->tag); + return -WD_EINVAL; + } + } else { + temp_msg = msg; + } + + hpre_result_check(hw_msg, &msg->result); + if (msg->result) { + ret = -msg->result; + goto dump_err_msg; + } + + ret = ecc_out_transfer(msg, hw_msg, qp->q_info.qp_mode); + if (ret) { + msg->result = WD_OUT_EPARA; + WD_ERR("failed to transfer out ecc BD, ret = %d!\n", ret); + goto dump_err_msg; + } + + return ret; + +dump_err_msg: + dump_hpre_msg(temp_msg, "ecc"); + + return ret; +} + +static int parse_second_sqe(handle_t h_qp, + struct wd_ecc_msg *msg, + struct wd_ecc_msg **second) +{ + struct hisi_hpre_sqe hw_msg; + struct wd_ecc_msg *dst; + __u16 recv_cnt = 0; + int cnt = 0; + void *data; + __u32 hsz; + int ret; + + while (1) { + ret = hisi_qm_recv(h_qp, &hw_msg, 1, &recv_cnt); + if (ret == -WD_EAGAIN) { + if (cnt++ > MAX_WAIT_CNT) + return ret; + usleep(1); + continue; + } else if (ret) { + return ret; + } + break; + } + + data = VA_ADDR(hw_msg.hi_out, hw_msg.low_out); + hsz = (hw_msg.task_len1 + 1) * BYTE_BITS; + dst = *(struct wd_ecc_msg **)((uintptr_t)data + + hsz * ECDH_OUT_PARAM_NUM); + ret = ecc_sqe_parse((struct hisi_qp *)h_qp, dst, &hw_msg); + msg->result = dst->result; + *second = dst; + + return ret; +} + +static int sm2_enc_parse(handle_t h_qp, struct wd_ecc_msg *msg, + struct hisi_hpre_sqe *hw_msg) +{ + __u16 tag = LW_U16(hw_msg->low_tag); + struct wd_ecc_msg *second = NULL; + struct wd_ecc_msg *first; + struct wd_ecc_msg src; + void *data; + __u32 hsz; + int ret; + + msg->tag = tag; + data = VA_ADDR(hw_msg->hi_out, hw_msg->low_out); + hsz = (hw_msg->task_len1 + 1) * BYTE_BITS; + first = *(struct wd_ecc_msg **)((uintptr_t)data + + hsz * ECDH_OUT_PARAM_NUM); + memcpy(&src, first + 1, sizeof(src)); + + /* parse first sqe */ + ret = ecc_sqe_parse((struct hisi_qp *)h_qp, first, hw_msg); + if (ret) { + WD_ERR("failed to parse first BD, ret = %d!\n", ret); + goto free_first; + } + + /* parse second sqe */ + ret = parse_second_sqe(h_qp, msg, &second); + if (unlikely(ret)) { + WD_ERR("failed to parse second BD, ret = %d!\n", ret); + goto free_first; + } + + ret = sm2_convert_enc_out(&src, first, second); + if (unlikely(ret)) { + WD_ERR("failed to convert sm2 std format, ret = %d!\n", ret); + goto free_second; + } + +free_second: + free_req(second); +free_first: + free_req(first); + + return ret; +} + +static int sm2_dec_parse(handle_t ctx, struct wd_ecc_msg *msg, + struct hisi_hpre_sqe *hw_msg) +{ + __u16 tag = LW_U16(hw_msg->low_tag); + struct wd_ecc_msg *dst; + struct wd_ecc_msg src; + void *data; + __u32 hsz; + int ret; + + data = VA_ADDR(hw_msg->hi_out, hw_msg->low_out); + hsz = (hw_msg->task_len1 + 1) * BYTE_BITS; + dst = *(struct wd_ecc_msg **)((uintptr_t)data + + hsz * ECDH_OUT_PARAM_NUM); + memcpy(&src, dst + 1, sizeof(src)); + + /* parse first sqe */ + ret = ecc_sqe_parse((struct hisi_qp *)ctx, dst, hw_msg); + if (ret) { + WD_ERR("failed to parse decode BD, ret = %d!\n", ret); + goto fail; + } + msg->result = dst->result; + msg->tag = tag; + + ret = sm2_convert_dec_out(&src, dst); + if (unlikely(ret)) { + WD_ERR("failed to convert sm2 decode out, ret = %d!\n", ret); + goto fail; + } + +fail: + free(dst->req.dst); + free(dst); + + return ret; +} + +static int ecc_recv(handle_t ctx, void *ecc_msg) +{ + handle_t h_qp = (handle_t)wd_ctx_get_priv(ctx); + struct wd_ecc_msg *msg = ecc_msg; + struct hisi_hpre_sqe hw_msg; + __u16 recv_cnt = 0; + int ret; + + ret = hisi_qm_recv(h_qp, &hw_msg, 1, &recv_cnt); + if (ret) + return ret; + + ret = hisi_check_bd_id(h_qp, msg->tag, hw_msg.low_tag); + if (ret) + return ret; + + if (hw_msg.alg == HPRE_ALG_ECDH_MULTIPLY && + hw_msg.sm2_mlen == HPRE_SM2_ENC) + return sm2_enc_parse(h_qp, msg, &hw_msg); + else if (hw_msg.alg == HPRE_ALG_ECDH_MULTIPLY && + hw_msg.sm2_mlen == HPRE_SM2_DEC) + return sm2_dec_parse(h_qp, msg, &hw_msg); + + return ecc_sqe_parse((struct hisi_qp *)h_qp, msg, &hw_msg); +} + +static struct wd_ecc_driver ecc_hisi_hpre = { + .drv_name = "hisi_hpre", + .alg_name = "ecc", + .drv_ctx_size = sizeof(struct hisi_hpre_ctx), + .init = hpre_init, + .exit = hpre_exit, + .send = ecc_send, + .recv = ecc_recv, +}; + +WD_RSA_SET_DRIVER(rsa_hisi_hpre); +WD_DH_SET_DRIVER(dh_hisi_hpre); +WD_ECC_SET_DRIVER(ecc_hisi_hpre); diff --git a/uadk/drv/hisi_qm_udrv.c b/uadk/drv/hisi_qm_udrv.c new file mode 100644 index 0000000..6647840 --- /dev/null +++ b/uadk/drv/hisi_qm_udrv.c @@ -0,0 +1,1022 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. */ + +#include +#include +#include +#include +#include + +#include "hisi_qm_udrv.h" + +#define QM_DBELL_CMD_SQ 0 +#define QM_DBELL_CMD_CQ 1 +#define QM_DBELL_OFFSET 0x340 +#define QM_DBELL_OFFSET_V2 0x1000 +#define QM_DBELL_CMD_SHIFT 16 +#define QM_DBELL_CMD_SHIFT_V2 12 +#define QM_DBELL_PRI_SHIFT 16 +#define QM_DBELL_HLF_SHIFT 32 +#define QM_DBELL_SQN_MASK 0x3ff +#define QM_DBELL_CMD_MASK 0xf +#define QM_Q_DEPTH 1024 +#define CQE_PHASE(cq) (__le16_to_cpu((cq)->w7) & 0x1) +#define CQE_SQ_HEAD_INDEX(cq) (__le16_to_cpu((cq)->sq_head) & 0xffff) +#define VERSION_ID_SHIFT 9 + +#define UACCE_CMD_QM_SET_QP_CTX _IOWR('H', 10, struct hisi_qp_ctx) +#define UACCE_CMD_QM_SET_QP_INFO _IOWR('H', 11, struct hisi_qp_info) +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +/* the max sge num in one sgl */ +#define HISI_SGE_NUM_IN_SGL 255 + +/* the max sge num in on BD, QM user it be the sgl pool size */ +#define HISI_SGL_NUM_IN_BD 256 + +/* sgl address must be 64 bytes aligned */ +#define HISI_SGL_ALIGE 64 + +#define HISI_MAX_SIZE_IN_SGE (1024 * 1024 * 8) + +#define ADDR_ALIGN_64(addr) ((((uintptr_t)(addr) >> 6) + 1) << 6) + +struct hisi_qm_type { + __u16 qm_ver; + int qm_db_offs; + int (*hacc_db)(struct hisi_qm_queue_info *q, __u8 cmd, + __u16 idx, __u8 prority); +}; + +struct cqe { + __le32 rsvd0; + __le16 cmd_id; + __le16 rsvd1; + __le16 sq_head; + __le16 sq_num; + __le16 rsvd2; + __le16 w7; +}; + +struct hisi_qp_ctx { + __u16 id; + __u16 qc_type; +}; + +struct hisi_qp_info { + __u32 sqe_size; + __u16 sq_depth; + __u16 cq_depth; + __u64 reserved; +}; + +struct hisi_sge { + uintptr_t buff; + void *page_ctrl; + __le32 len; + __le32 pad; + __le32 pad0; + __le32 pad1; +}; + +/* use default hw sgl head size 64B, in little-endian */ +struct hisi_sgl { + /* the next sgl address */ + uintptr_t next_dma; + /* the sge num of all the sgl */ + __le16 entry_sum_in_chain; + /* valid sge(has buff) num in this sgl */ + __le16 entry_sum_in_sgl; + /* the sge num in this sgl */ + __le16 entry_length_in_sgl; + __le16 pad0; + __le64 pad1[5]; + /* valid sge buffs total size */ + __le64 entry_size_in_sgl; + struct hisi_sge sge_entries[]; +}; + +struct hisi_sgl_pool { + /* the addr64 align offset base sgl */ + void **sgl_align; + /* the sgl src address array */ + void **sgl; + /* the sgl pool stack depth */ + __u32 depth; + __u32 top; + __u32 sge_num; + __u32 sgl_num; + pthread_spinlock_t lock; +}; + +static int hacc_db_v1(struct hisi_qm_queue_info *q, __u8 cmd, + __u16 idx, __u8 priority) +{ + void *base = q->db_base; + __u16 sqn = q->sqn; + __u64 doorbell; + + doorbell = (__u64)sqn | ((__u64)cmd << QM_DBELL_CMD_SHIFT); + doorbell |= ((__u64)idx | ((__u64)priority << QM_DBELL_CMD_SHIFT)) + << QM_DBELL_HLF_SHIFT; + wd_iowrite64(base, doorbell); + + return 0; +} + +static int hacc_db_v2(struct hisi_qm_queue_info *q, __u8 cmd, + __u16 idx, __u8 priority) +{ + __u16 sqn = q->sqn & QM_DBELL_SQN_MASK; + void *base = q->db_base; + __u64 doorbell; + + doorbell = (__u64)sqn | ((__u64)(cmd & QM_DBELL_CMD_MASK) << + QM_DBELL_CMD_SHIFT_V2); + doorbell |= ((__u64)idx | ((__u64)priority << QM_DBELL_CMD_SHIFT)) + << QM_DBELL_HLF_SHIFT; + wd_iowrite64(base, doorbell); + + return 0; +} + +static struct hisi_qm_type qm_type[] = { + { + .qm_ver = HISI_QM_API_VER_BASE, + .qm_db_offs = QM_DBELL_OFFSET, + .hacc_db = hacc_db_v1, + }, { + .qm_ver = HISI_QM_API_VER2_BASE, + .qm_db_offs = QM_DBELL_OFFSET_V2, + .hacc_db = hacc_db_v2, + } +}; + +static void hisi_qm_fill_sqe(const void *sqe, struct hisi_qm_queue_info *info, + __u16 tail, __u16 num) +{ + int sqe_size = info->sqe_size; + void *sq_base = info->sq_base; + int idx; + + if (tail + num < info->sq_depth) { + memcpy((void *)((uintptr_t)sq_base + tail * sqe_size), + sqe, sqe_size * num); + } else { + idx = info->sq_depth - tail; + memcpy((void *)((uintptr_t)sq_base + tail * sqe_size), + sqe, sqe_size * idx); + memcpy(sq_base, (void *)((uintptr_t)sqe + sqe_size * idx), + sqe_size * (num - idx)); + } +} + +static int hisi_qm_setup_region(handle_t h_ctx, + struct hisi_qm_queue_info *q_info) +{ + q_info->sq_base = wd_ctx_mmap_qfr(h_ctx, UACCE_QFRT_DUS); + if (!q_info->sq_base) { + WD_DEV_ERR(h_ctx, "failed to mmap dus!\n"); + return -WD_ENOMEM; + } + + q_info->mmio_base = wd_ctx_mmap_qfr(h_ctx, UACCE_QFRT_MMIO); + if (!q_info->mmio_base) { + wd_ctx_unmap_qfr(h_ctx, UACCE_QFRT_DUS); + WD_DEV_ERR(h_ctx, "failed to mmap mmio!\n"); + return -WD_ENOMEM; + } + + return 0; +} + +static void hisi_qm_unset_region(handle_t h_ctx, + struct hisi_qm_queue_info *q_info) +{ + wd_ctx_unmap_qfr(h_ctx, UACCE_QFRT_DUS); + wd_ctx_unmap_qfr(h_ctx, UACCE_QFRT_MMIO); + q_info->sq_base = NULL; + q_info->mmio_base = NULL; +} + +static __u32 get_version_id(handle_t h_ctx) +{ + char *api_name, *id; + unsigned long ver; + + api_name = wd_ctx_get_api(h_ctx); + if (!api_name || strlen(api_name) <= VERSION_ID_SHIFT) { + WD_DEV_ERR(h_ctx, "invalid: api name is %s!\n", api_name); + return 0; + } + + id = api_name + VERSION_ID_SHIFT; + ver = strtoul(id, NULL, 10); + if (!ver || ver == ULONG_MAX) { + WD_DEV_ERR(h_ctx, "failed to strtoul, ver = %lu!\n", ver); + return 0; + } + + return (__u32)ver; +} + +static int hisi_qm_setup_db(handle_t h_ctx, struct hisi_qm_queue_info *q_info) +{ + __u32 ver_id; + int i, size; + + ver_id = get_version_id(h_ctx); + if (!ver_id) + return -WD_EINVAL; + + q_info->hw_type = ver_id; + size = ARRAY_SIZE(qm_type); + for (i = 0; i < size; i++) { + if (qm_type[i].qm_ver == ver_id) { + q_info->db = qm_type[i].hacc_db; + q_info->db_base = q_info->mmio_base + + qm_type[i].qm_db_offs; + break; + } + } + + if (i == size) { + q_info->db = hacc_db_v2; + q_info->db_base = q_info->mmio_base + QM_DBELL_OFFSET_V2; + } + + return 0; +} + +static int his_qm_set_qp_ctx(handle_t h_ctx, struct hisi_qm_priv *config, + struct hisi_qm_queue_info *q_info) +{ + struct hisi_qp_info qp_cfg; + struct hisi_qp_ctx qp_ctx; + int ret; + + memset(&qp_ctx, 0, sizeof(struct hisi_qp_ctx)); + qp_ctx.qc_type = config->op_type; + q_info->qc_type = qp_ctx.qc_type; + ret = wd_ctx_set_io_cmd(h_ctx, UACCE_CMD_QM_SET_QP_CTX, &qp_ctx); + if (ret < 0) { + WD_DEV_ERR(h_ctx, "failed to set qc_type!\n"); + return ret; + } + q_info->sqn = qp_ctx.id; + + ret = wd_ctx_set_io_cmd(h_ctx, UACCE_CMD_QM_SET_QP_INFO, &qp_cfg); + if (ret < 0) { + WD_INFO("getting qp information is not supported, use default value!\n"); + + q_info->sq_depth = QM_Q_DEPTH; + q_info->cq_depth = QM_Q_DEPTH; + q_info->sqe_size = config->sqe_size; + } else { + q_info->sq_depth = qp_cfg.sq_depth; + q_info->cq_depth = qp_cfg.cq_depth; + q_info->sqe_size = qp_cfg.sqe_size; + } + + return 0; +} + +static int hisi_qm_get_qfrs_offs(handle_t h_ctx, + struct hisi_qm_queue_info *q_info) +{ + enum uacce_qfrt type; + + type = UACCE_QFRT_DUS; + q_info->region_size[type] = wd_ctx_get_region_size(h_ctx, type); + if (!q_info->region_size[type]) { + WD_DEV_ERR(h_ctx, "failed to get DUS qfrs offset!\n"); + return -WD_EINVAL; + } + + type = UACCE_QFRT_MMIO; + q_info->region_size[type] = wd_ctx_get_region_size(h_ctx, type); + if (!q_info->region_size[type]) { + WD_DEV_ERR(h_ctx, "failed to get MMIO qfrs offset!\n"); + return -WD_EINVAL; + } + + return 0; +} + +static int hisi_qm_setup_info(struct hisi_qp *qp, struct hisi_qm_priv *config) +{ + struct hisi_qm_queue_info *q_info = NULL; + int ret; + + q_info = &qp->q_info; + ret = hisi_qm_setup_region(qp->h_ctx, q_info); + if (ret) { + WD_DEV_ERR(qp->h_ctx, "failed to setup region!\n"); + return ret; + } + + ret = hisi_qm_get_qfrs_offs(qp->h_ctx, q_info); + if (ret) { + WD_DEV_ERR(qp->h_ctx, "failed to get dev qfrs offset!\n"); + goto err_out; + } + + ret = hisi_qm_setup_db(qp->h_ctx, q_info); + if (ret) { + WD_DEV_ERR(qp->h_ctx, "failed to setup db!\n"); + goto err_out; + } + + ret = his_qm_set_qp_ctx(qp->h_ctx, config, q_info); + if (ret) { + WD_DEV_ERR(qp->h_ctx, "failed to setup io cmd!\n"); + goto err_out; + } + + q_info->qp_mode = config->qp_mode; + q_info->epoll_en = config->epoll_en; + q_info->idx = config->idx; + q_info->cqc_phase = 1; + q_info->cq_base = q_info->sq_base + (__u64)config->sqe_size * q_info->sq_depth; + /* The last 32 bits of DUS show device or qp statuses */ + q_info->ds_tx_base = q_info->sq_base + + q_info->region_size[UACCE_QFRT_DUS] - sizeof(uint32_t); + q_info->ds_rx_base = q_info->ds_tx_base - sizeof(uint32_t); + + ret = pthread_spin_init(&q_info->rv_lock, PTHREAD_PROCESS_SHARED); + if (ret) { + WD_DEV_ERR(qp->h_ctx, "failed to init qinfo rv_lock!\n"); + goto err_out; + } + + ret = pthread_spin_init(&q_info->sd_lock, PTHREAD_PROCESS_SHARED); + if (ret) { + WD_DEV_ERR(qp->h_ctx, "failed to init qinfo sd_lock!\n"); + goto err_destroy_lock; + } + + return 0; + +err_destroy_lock: + pthread_spin_destroy(&q_info->rv_lock); +err_out: + hisi_qm_unset_region(qp->h_ctx, q_info); + return ret; +} + +static void hisi_qm_clear_info(struct hisi_qp *qp) +{ + struct hisi_qm_queue_info *q_info = &qp->q_info; + + pthread_spin_destroy(&q_info->sd_lock); + pthread_spin_destroy(&q_info->rv_lock); + hisi_qm_unset_region(qp->h_ctx, q_info); +} + +static int get_free_num(struct hisi_qm_queue_info *q_info) +{ + /* The device should reserve one buffer. */ + return (q_info->sq_depth - 1) - + __atomic_load_n(&q_info->used_num, __ATOMIC_RELAXED); +} + +int hisi_qm_get_free_sqe_num(handle_t h_qp) +{ + struct hisi_qp *qp = (struct hisi_qp *)h_qp; + + return get_free_num(&qp->q_info); +} + +handle_t hisi_qm_alloc_qp(struct hisi_qm_priv *config, handle_t ctx) +{ + struct hisi_qp *qp; + int ret; + + if (!config) + goto out; + + if (!config->sqe_size) { + WD_ERR("invalid: sqe size is zero!\n"); + goto out; + } + + qp = calloc(1, sizeof(struct hisi_qp)); + if (!qp) + goto out; + + qp->h_ctx = ctx; + + ret = hisi_qm_setup_info(qp, config); + if (ret) + goto out_qp; + + qp->h_sgl_pool = hisi_qm_create_sglpool(HISI_SGL_NUM_IN_BD, + HISI_SGE_NUM_IN_SGL); + if (!qp->h_sgl_pool) + goto free_info; + + ret = wd_ctx_start(qp->h_ctx); + if (ret) + goto free_pool; + + ret = wd_ctx_set_priv(qp->h_ctx, qp); + if (ret) { + wd_release_ctx_force(qp->h_ctx); + goto free_pool; + } + + return (handle_t)qp; + +free_pool: + hisi_qm_destroy_sglpool(qp->h_sgl_pool); +free_info: + hisi_qm_clear_info(qp); +out_qp: + free(qp); +out: + return (handle_t)NULL; +} + +void hisi_qm_free_qp(handle_t h_qp) +{ + struct hisi_qp *qp = (struct hisi_qp *)h_qp; + + if (!qp) { + WD_ERR("invalid: h_qp is NULL!\n"); + return; + } + + wd_release_ctx_force(qp->h_ctx); + wd_ctx_unmap_qfr(qp->h_ctx, UACCE_QFRT_MMIO); + wd_ctx_unmap_qfr(qp->h_ctx, UACCE_QFRT_DUS); + if (qp->h_sgl_pool) + hisi_qm_destroy_sglpool(qp->h_sgl_pool); + + free(qp); +} + +int hisi_qm_send(handle_t h_qp, const void *req, __u16 expect, __u16 *count) +{ + struct hisi_qp *qp = (struct hisi_qp *)h_qp; + struct hisi_qm_queue_info *q_info; + __u16 free_num, send_num; + __u16 tail; + + if (unlikely(!qp || !req || !count)) + return -WD_EINVAL; + + q_info = &qp->q_info; + + if (unlikely(wd_ioread32(q_info->ds_tx_base) == 1)) { + WD_ERR("wd queue hw error happened before qm send!\n"); + return -WD_HW_EACCESS; + } + + pthread_spin_lock(&q_info->sd_lock); + free_num = get_free_num(q_info); + if (!free_num) { + pthread_spin_unlock(&q_info->sd_lock); + return -WD_EBUSY; + } + + send_num = expect > free_num ? free_num : expect; + + tail = q_info->sq_tail_index; + hisi_qm_fill_sqe(req, q_info, tail, send_num); + tail = (tail + send_num) % q_info->sq_depth; + q_info->db(q_info, QM_DBELL_CMD_SQ, tail, 0); + q_info->sq_tail_index = tail; + + /* Make sure used_num is changed before the next thread gets free sqe. */ + __atomic_add_fetch(&q_info->used_num, send_num, __ATOMIC_RELAXED); + *count = send_num; + + pthread_spin_unlock(&q_info->sd_lock); + + return 0; +} + +static int hisi_qm_recv_single(struct hisi_qm_queue_info *q_info, void *resp) +{ + struct hisi_qp *qp = container_of(q_info, struct hisi_qp, q_info); + struct cqe *cqe; + __u16 i, j; + + pthread_spin_lock(&q_info->rv_lock); + i = q_info->cq_head_index; + cqe = q_info->cq_base + i * sizeof(struct cqe); + + if (q_info->cqc_phase == CQE_PHASE(cqe)) { + j = CQE_SQ_HEAD_INDEX(cqe); + if (unlikely(j >= q_info->sq_depth)) { + pthread_spin_unlock(&q_info->rv_lock); + WD_DEV_ERR(qp->h_ctx, "CQE_SQ_HEAD_INDEX(%u) error!\n", j); + return -WD_EIO; + } + memcpy(resp, (void *)((uintptr_t)q_info->sq_base + + j * q_info->sqe_size), q_info->sqe_size); + } else { + pthread_spin_unlock(&q_info->rv_lock); + return -WD_EAGAIN; + } + + if (i == q_info->cq_depth - 1) { + q_info->cqc_phase = !(q_info->cqc_phase); + i = 0; + } else { + i++; + } + + q_info->db(q_info, QM_DBELL_CMD_CQ, i, q_info->epoll_en); + + /* only support one thread poll one queue, so no need protect */ + q_info->cq_head_index = i; + + __atomic_sub_fetch(&q_info->used_num, 1, __ATOMIC_RELAXED); + pthread_spin_unlock(&q_info->rv_lock); + + return 0; +} + +int hisi_qm_recv(handle_t h_qp, void *resp, __u16 expect, __u16 *count) +{ + struct hisi_qp *qp = (struct hisi_qp *)h_qp; + struct hisi_qm_queue_info *q_info; + int recv_num = 0; + int i, ret, offset; + + if (unlikely(!resp || !qp || !count)) + return -WD_EINVAL; + + if (unlikely(!expect)) + return 0; + + q_info = &qp->q_info; + if (unlikely(wd_ioread32(q_info->ds_rx_base) == 1)) { + WD_DEV_ERR(qp->h_ctx, "wd queue hw error happened before qm receive!\n"); + return -WD_HW_EACCESS; + } + + for (i = 0; i < expect; i++) { + offset = i * q_info->sqe_size; + ret = hisi_qm_recv_single(q_info, resp + offset); + if (ret) + break; + recv_num++; + } + + *count = recv_num; + if (unlikely(wd_ioread32(q_info->ds_rx_base) == 1)) { + WD_DEV_ERR(qp->h_ctx, "wd queue hw error happened in qm receive!\n"); + return -WD_HW_EACCESS; + } + + return ret; +} + +int hisi_check_bd_id(handle_t h_qp, __u32 mid, __u32 bid) +{ + struct hisi_qp *qp = (struct hisi_qp *)h_qp; + __u8 mode = qp->q_info.qp_mode; + + if (mode == CTX_MODE_SYNC && mid != bid) { + WD_DEV_ERR(qp->h_ctx, "failed to recv self bd, send id: %u, recv id: %u\n", + mid, bid); + return -WD_EINVAL; + } + + return 0; +} + +void hisi_set_msg_id(handle_t h_qp, __u32 *tag) +{ + static __thread __u64 rand_seed = 0x330eabcd; + struct hisi_qp *qp = (struct hisi_qp *)h_qp; + __u8 mode = qp->q_info.qp_mode; + __u16 seeds[3] = {0}; + __u64 id; + + /* + * The random message id on a single queue is obtained through the + * system's pseudo-random number generation algorithm to ensure + * that 1024 packets on a queue will not have duplicate id + */ + if (mode == CTX_MODE_SYNC) { + seeds[0] = LW_U16(rand_seed); + seeds[1] = LW_U16(rand_seed >> 16); + id = nrand48(seeds); + *tag = LW_U32(id); + rand_seed = id; + } +} + +static void *hisi_qm_create_sgl(__u32 sge_num) +{ + void *sgl; + int size; + + size = sizeof(struct hisi_sgl) + + sge_num * (sizeof(struct hisi_sge)) + HISI_SGL_ALIGE; + sgl = calloc(1, size); + if (!sgl) { + WD_ERR("failed to create sgl!\n"); + return NULL; + } + + return sgl; +} + +static struct hisi_sgl *hisi_qm_align_sgl(const void *sgl, __u32 sge_num) +{ + struct hisi_sgl *sgl_align; + + /* Hardware require the address must be 64 bytes aligned */ + sgl_align = (struct hisi_sgl *)ADDR_ALIGN_64(sgl); + sgl_align->entry_sum_in_chain = sge_num; + sgl_align->entry_sum_in_sgl = 0; + sgl_align->entry_length_in_sgl = sge_num; + sgl_align->next_dma = 0; + + return sgl_align; +} + +static void hisi_qm_free_sglpool(struct hisi_sgl_pool *pool) +{ + int i; + + if (pool->sgl) { + for (i = 0; i < pool->sgl_num; i++) + if (pool->sgl[i]) + free(pool->sgl[i]); + + free(pool->sgl); + } + + if (pool->sgl_align) + free(pool->sgl_align); + free(pool); +} + +handle_t hisi_qm_create_sglpool(__u32 sgl_num, __u32 sge_num) +{ + struct hisi_sgl_pool *sgl_pool; + int i, ret; + + if (!sgl_num || !sge_num || sge_num > HISI_SGE_NUM_IN_SGL) { + WD_ERR("failed to create sgl_pool, sgl_num=%u, sge_num=%u!\n", + sgl_num, sge_num); + return 0; + } + + sgl_pool = calloc(1, sizeof(struct hisi_sgl_pool)); + if (!sgl_pool) { + WD_ERR("failed to alloc memory for sgl_pool!\n"); + return 0; + } + + sgl_pool->sgl = calloc(sgl_num, sizeof(void *)); + if (!sgl_pool->sgl) { + WD_ERR("failed to alloc memory for sgl!\n"); + goto err_out; + } + + sgl_pool->sgl_align = calloc(sgl_num, sizeof(void *)); + if (!sgl_pool->sgl_align) { + WD_ERR("failed to alloc memory for sgl align!\n"); + goto err_out; + } + + /* base the sgl_num create the sgl chain */ + for (i = 0; i < sgl_num; i++) { + sgl_pool->sgl[i] = hisi_qm_create_sgl(sge_num); + if (!sgl_pool->sgl[i]) + goto err_out; + + sgl_pool->sgl_align[i] = hisi_qm_align_sgl(sgl_pool->sgl[i], + sge_num); + } + + sgl_pool->sgl_num = sgl_num; + sgl_pool->sge_num = sge_num; + sgl_pool->depth = sgl_num; + sgl_pool->top = sgl_num; + ret = pthread_spin_init(&sgl_pool->lock, PTHREAD_PROCESS_SHARED); + if (ret) { + WD_ERR("failed to init sgl pool lock!\n"); + goto err_out; + } + + return (handle_t)sgl_pool; + +err_out: + hisi_qm_free_sglpool(sgl_pool); + return (handle_t)0; +} + +void hisi_qm_destroy_sglpool(handle_t sgl_pool) +{ + struct hisi_sgl_pool *pool; + + if (!sgl_pool) { + WD_ERR("invalid: sgl_pool is NULL!\n"); + return; + } + + pool = (struct hisi_sgl_pool *)sgl_pool; + pthread_spin_destroy(&pool->lock); + hisi_qm_free_sglpool(pool); +} + +static struct hisi_sgl *hisi_qm_sgl_pop(struct hisi_sgl_pool *pool) +{ + struct hisi_sgl *hw_sgl; + + pthread_spin_lock(&pool->lock); + + if (pool->top == 0) { + WD_ERR("invalid: the sgl pool is empty!\n"); + pthread_spin_unlock(&pool->lock); + return NULL; + } + + pool->top--; + hw_sgl = pool->sgl_align[pool->top]; + pthread_spin_unlock(&pool->lock); + return hw_sgl; +} + +static int hisi_qm_sgl_push(struct hisi_sgl_pool *pool, struct hisi_sgl *hw_sgl) +{ + pthread_spin_lock(&pool->lock); + if (pool->top >= pool->depth) { + WD_ERR("invalid: the sgl pool is full!\n"); + pthread_spin_unlock(&pool->lock); + return -WD_EINVAL; + } + + hw_sgl->next_dma = 0; + hw_sgl->entry_sum_in_sgl = 0; + hw_sgl->entry_sum_in_chain = pool->sge_num; + hw_sgl->entry_length_in_sgl = pool->sge_num; + hw_sgl->entry_size_in_sgl = 0; + + pool->sgl_align[pool->top] = hw_sgl; + pool->top++; + pthread_spin_unlock(&pool->lock); + + return 0; +} + +void hisi_qm_put_hw_sgl(handle_t sgl_pool, void *hw_sgl) +{ + struct hisi_sgl_pool *pool = (struct hisi_sgl_pool *)sgl_pool; + struct hisi_sgl *cur = (struct hisi_sgl *)hw_sgl; + struct hisi_sgl *next = (struct hisi_sgl *)hw_sgl; + int ret; + + if (!pool) + return; + + while (cur) { + next = (struct hisi_sgl *)cur->next_dma; + ret = hisi_qm_sgl_push(pool, cur); + if (ret) + break; + + cur = next; + } + + return; +} + +static void hisi_qm_dump_sgl(void *sgl) +{ + struct hisi_sgl *tmp = (struct hisi_sgl *)sgl; + bool need_debug = wd_need_debug(); + int k = 0; + int i; + + if (!need_debug) + return; + + while (tmp) { + WD_DEBUG("[sgl-%d]->entry_sum_in_chain: %u\n", k, + tmp->entry_sum_in_chain); + WD_DEBUG("[sgl-%d]->entry_sum_in_sgl: %u\n", k, + tmp->entry_sum_in_sgl); + WD_DEBUG("[sgl-%d]->entry_length_in_sgl: %u\n", k, + tmp->entry_length_in_sgl); + for (i = 0; i < tmp->entry_sum_in_sgl; i++) + WD_DEBUG("[sgl-%d]->sge_entries[%d].len: %u\n", k, i, + tmp->sge_entries[i].len); + + tmp = (struct hisi_sgl *)tmp->next_dma; + k++; + + if (!tmp) { + WD_DEBUG("debug: sgl num size:%d\n", k); + return; + } + } +} + +void *hisi_qm_get_hw_sgl(handle_t sgl_pool, struct wd_datalist *sgl) +{ + struct hisi_sgl_pool *pool = (struct hisi_sgl_pool *)sgl_pool; + struct wd_datalist *tmp = sgl; + struct hisi_sgl *head, *next, *cur; + int i = 0; + + if (!pool || !sgl) { + WD_ERR("invalid: hw sgl pool or sgl is NULL!\n"); + return NULL; + } + + head = hisi_qm_sgl_pop(pool); + if (!head) + return NULL; + + cur = head; + tmp = sgl; + while (tmp) { + /* if the user's data is NULL, jump next one */ + if (!tmp->data || !tmp->len) { + tmp = tmp->next; + continue; + } + + if (tmp->len > HISI_MAX_SIZE_IN_SGE) { + WD_ERR("invalid: the data len is %u!\n", tmp->len); + goto err_out; + } + + cur->sge_entries[i].buff = (uintptr_t)tmp->data; + cur->sge_entries[i].len = tmp->len; + cur->entry_sum_in_sgl++; + cur->entry_size_in_sgl += tmp->len; + i++; + + /* + * If current sgl chain is full and there is still user sgl data, + * we should allocate another hardware sgl to hold up them until + * the sgl pool is not enough or all the data is transform to + * hardware sgl. + */ + if (i == pool->sge_num && tmp->next) { + next = hisi_qm_sgl_pop(pool); + if (!next) { + WD_ERR("invalid: the sgl pool is not enough!\n"); + goto err_out; + } + cur->next_dma = (uintptr_t)next; + cur = next; + head->entry_sum_in_chain += pool->sge_num; + /* In the new sgl chain, the subscript must be reset */ + i = 0; + } + + tmp = tmp->next; + } + + /* There is no data, recycle the hardware sgl head to pool */ + if (!head->entry_sum_in_chain) + goto err_out; + + hisi_qm_dump_sgl(head); + + return head; +err_out: + hisi_qm_put_hw_sgl(sgl_pool, head); + return NULL; +} + +handle_t hisi_qm_get_sglpool(handle_t h_qp) +{ + struct hisi_qp *qp = (struct hisi_qp *)h_qp; + + return qp->h_sgl_pool; +} + +static void hisi_qm_sgl_copy_inner(void *pbuff, struct hisi_sgl *hw_sgl, + int begin_sge, __u32 sge_offset, __u32 size) +{ + struct hisi_sgl *tmp = hw_sgl; + int i = begin_sge + 1; + __u32 offset; + void *src; + + src = (void *)tmp->sge_entries[begin_sge].buff + sge_offset; + offset = tmp->sge_entries[begin_sge].len - sge_offset; + /* the first one is enough for copy size, copy and return */ + if (offset >= size) { + memcpy(pbuff, src, size); + return; + } + + memcpy(pbuff, src, offset); + + while (tmp) { + for (; i < tmp->entry_sum_in_sgl; i++) { + src = (void *)tmp->sge_entries[i].buff; + if (offset + tmp->sge_entries[i].len >= size) { + memcpy(pbuff + offset, src, size - offset); + return; + } + + memcpy(pbuff + offset, src, tmp->sge_entries[i].len); + offset += tmp->sge_entries[i].len; + } + + tmp = (struct hisi_sgl *)tmp->next_dma; + i = 0; + } +} + +static void hisi_qm_pbuff_copy_inner(void *pbuff, struct hisi_sgl *hw_sgl, + int begin_sge, __u32 sge_offset, + __u32 size) +{ + struct hisi_sgl *tmp = hw_sgl; + int i = begin_sge + 1; + __u32 offset = 0; + void *dst; + + if (tmp->sge_entries[begin_sge].len - sge_offset >= size) { + dst = (void *)tmp->sge_entries[begin_sge].buff + sge_offset; + memcpy(dst, pbuff, size); + return; + } + + while (tmp) { + for (; i < tmp->entry_sum_in_sgl; i++) { + dst = (void *)tmp->sge_entries[i].buff; + if (offset + tmp->sge_entries[i].len >= size) { + memcpy(dst, pbuff + offset, size - offset); + return; + } + + memcpy(dst, pbuff + offset, tmp->sge_entries[i].len); + offset += tmp->sge_entries[i].len; + } + + tmp = (struct hisi_sgl *)tmp->next_dma; + i = 0; + } +} + +void hisi_qm_sgl_copy(void *pbuff, void *hw_sgl, __u32 offset, __u32 size, + __u8 direct) +{ + struct hisi_sgl *tmp = hw_sgl; + __u32 sge_offset = 0; + __u32 len = 0; + int begin_sge = 0; + int i; + + if (!pbuff || !size || !tmp) + return; + + while (len + tmp->entry_size_in_sgl <= offset) { + tmp = (struct hisi_sgl *)tmp->next_dma; + if (!tmp) + return; + + len += tmp->entry_size_in_sgl; + } + + /* find the start sge position and start offset */ + for (i = 0; i < tmp->entry_sum_in_sgl; i++) { + if (len + tmp->sge_entries[i].len > offset) { + begin_sge = i; + sge_offset = offset - len; + break; + } + if (len + tmp->sge_entries[i].len == offset) { + begin_sge = i + 1; + sge_offset = 0; + break; + } + + len += tmp->sge_entries[i].len; + } + + if (direct == COPY_SGL_TO_PBUFF) + hisi_qm_sgl_copy_inner(pbuff, tmp, begin_sge, sge_offset, size); + else + hisi_qm_pbuff_copy_inner(pbuff, tmp, begin_sge, sge_offset, + size); +} + +__u32 hisi_qm_get_list_size(struct wd_datalist *start_node, + struct wd_datalist *end_node) +{ + struct wd_datalist *cur = start_node; + __u32 lits_size = 0; + + while (cur != end_node) { + lits_size += cur->len; + cur = cur->next; + } + + return lits_size; +} diff --git a/uadk/drv/hisi_sec.c b/uadk/drv/hisi_sec.c new file mode 100644 index 0000000..5b676e9 --- /dev/null +++ b/uadk/drv/hisi_sec.c @@ -0,0 +1,2615 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. */ + +#include +#include +#include +#include "../include/drv/wd_cipher_drv.h" +#include "../include/drv/wd_digest_drv.h" +#include "../include/drv/wd_aead_drv.h" +#include "hisi_qm_udrv.h" +#include "wd_cipher.h" +#include "wd_digest.h" +#include "wd_aead.h" +#include "wd.h" + +#define SEC_DIGEST_ALG_OFFSET 11 +#define WORD_ALIGNMENT_MASK 0x3 +#define CTR_MODE_LEN_SHIFT 4 +#define WORD_BYTES 4 +#define BYTE_BITS 8 +#define SQE_BYTES_NUMS 128 +#define SEC_FLAG_OFFSET 7 +#define SEC_AUTH_KEY_OFFSET 5 +#define SEC_HW_ICV_ERR 0x2 +#define SEC_HW_TASK_DONE 0x1 +#define SEC_DONE_MASK 0x0001 +#define SEC_ICV_MASK 0x000E +#define SEC_AUTH_MASK 0x3F + +#define SEC_IPSEC_SCENE 0x1 +#define SEC_STREAM_SCENE 0x7 +#define SEC_SCENE_OFFSET 3 +#define SEC_DE_OFFSET 1 +#define SEC_AUTH_OFFSET 6 +#define SEC_CMODE_OFFSET 12 +#define SEC_CKEY_OFFSET 9 +#define SEC_CIPHER_OFFSET 4 +#define XTS_MODE_KEY_DIVISOR 2 +#define SEC_CTR_CNT_OFFSET 25 +#define SEC_CTR_CNT_ROLLOVER 2 + +#define SEC_DE_OFFSET_V3 9 +#define SEC_SCENE_OFFSET_V3 5 +#define SEC_CWIDTH_OFFSET_V3 10 +#define SEC_CKEY_OFFSET_V3 13 +#define SEC_CALG_OFFSET_V3 4 +#define SEC_AKEY_OFFSET_V3 9 +#define SEC_MAC_OFFSET_V3 4 +#define SEC_AUTH_ALG_OFFSET_V3 15 +#define SEC_CIPHER_AUTH_V3 0xbf +#define SEC_AUTH_CIPHER_V3 0x40 +#define SEC_AI_GEN_OFFSET_V3 2 +#define SEC_SEQ_OFFSET_V3 6 +#define SEC_AUTH_MASK_V3 0xFFFFFFFC + +#define SEC_SGL_MODE_MASK_V3 0x4800 +#define SEC_PBUFF_MODE_MASK_V3 0x800 +#define SEC_SGL_SDS_MASK 0x80 +#define SEC_SGL_SDM_MASK 0x04 +#define SEC_MAC_LEN_MASK 0x1F +#define SEC_AUTH_LEN_MASK 0x3F + +#define DES_KEY_SIZE 8 +#define SEC_3DES_2KEY_SIZE (2 * DES_KEY_SIZE) +#define SEC_3DES_3KEY_SIZE (3 * DES_KEY_SIZE) +#define AES_KEYSIZE_128 16 +#define AES_KEYSIZE_192 24 +#define AES_KEYSIZE_256 32 + +#define DES3_BLOCK_SIZE 8 +#define AES_BLOCK_SIZE 16 +#define CTR_128BIT_COUNTER 16 + +/* The max BD data length is 16M-512B */ +#define MAX_INPUT_DATA_LEN 0xFFFE00 +#define MAX_CCM_AAD_LEN 65279 +#define SHA1_ALIGN_SZ 64U +#define SHA512_ALIGN_SZ 128U + +#define AUTHPAD_OFFSET 2 +#define AUTHTYPE_OFFSET 6 +#define MAC_LEN_OFFSET 5 +#define AUTH_ALG_OFFSET 11 +#define WD_CIPHER_THEN_DIGEST 0x0 +#define WD_DIGEST_THEN_CIPHER 0x1 + +enum C_ALG { + C_ALG_DES = 0x0, + C_ALG_3DES = 0x1, + C_ALG_AES = 0x2, + C_ALG_SM4 = 0x3, +}; + +enum A_ALG { + A_ALG_SHA1 = 0x0, + A_ALG_SHA256 = 0x1, + A_ALG_MD5 = 0x2, + A_ALG_SHA224 = 0x3, + A_ALG_SHA384 = 0x4, + A_ALG_SHA512 = 0x5, + A_ALG_SHA512_224 = 0x6, + A_ALG_SHA512_256 = 0x7, + A_ALG_HMAC_SHA1 = 0x10, + A_ALG_HMAC_SHA256 = 0x11, + A_ALG_HMAC_MD5 = 0x12, + A_ALG_HMAC_SHA224 = 0x13, + A_ALG_HMAC_SHA384 = 0x14, + A_ALG_HMAC_SHA512 = 0x15, + A_ALG_HMAC_SHA512_224 = 0x16, + A_ALG_HMAC_SHA512_256 = 0x17, + A_ALG_AES_XCBC_MAC_96 = 0x20, + A_ALG_AES_XCBC_PRF_128 = 0x20, + A_ALG_AES_CMAC = 0x21, + A_ALG_AES_GMAC = 0x22, + A_ALG_SM3 = 0x25, + A_ALG_HMAC_SM3 = 0x26 +}; + +/* The long hash mode requires full-length mac output */ +enum SEC_MAX_MAC_LEN { + SEC_HMAC_SM3_MAC_LEN = 0x8, + SEC_HMAC_MD5_MAC_LEN = 0x4, + SEC_HMAC_SHA1_MAC_LEN = 0x5, + SEC_HMAC_SHA256_MAC_LEN = 0x8, + SEC_HMAC_SHA224_MAC_LEN = 0x7, + SEC_HMAC_SHA384_MAC_LEN = 0xc, + SEC_HMAC_SHA512_MAC_LEN = 0x10, + SEC_HMAC_SHA512_224_MAC_LEN = 0x7, + SEC_HMAC_SHA512_256_MAC_LEN = 0x8 +}; + +enum C_MODE { + C_MODE_ECB = 0x0, + C_MODE_CBC = 0x1, + C_MODE_CFB = 0x2, + C_MODE_OFB = 0x3, + C_MODE_CTR = 0x4, + C_MODE_CCM = 0x5, + C_MODE_GCM = 0x6, + C_MODE_XTS = 0x7, + C_MODE_CBC_CS = 0x9, +}; + +enum C_KEY_LEN { + CKEY_LEN_128BIT = 0x0, + CKEY_LEN_192BIT = 0x1, + CKEY_LEN_256BIT = 0x2, + CKEY_LEN_SM4 = 0x0, + CKEY_LEN_DES = 0x1, + CKEY_LEN_3DES_3KEY = 0x1, + CKEY_LEN_3DES_2KEY = 0x3, +}; + +enum { + NO_AUTH = 0x0, + AUTH_HMAC_CALCULATE = 0x1, + AUTH_MAC_VERIFY = 0x2, +}; + +enum { + DATA_DST_ADDR_DISABLE = 0x0, + DATA_DST_ADDR_ENABLE = 0x1, +}; + +enum { + AI_GEN_INNER = 0x0, + AI_GEN_IVIN_ADDR = 0x1, + AI_GEN_CAL_IV_ADDR = 0x2, + AI_GEN_TRNG = 0x3, +}; + +enum { + AUTHPAD_PAD = 0x0, + AUTHPAD_NOPAD = 0x1, +}; + +enum sec_cipher_dir { + SEC_CIPHER_ENC = 0x1, + SEC_CIPHER_DEC = 0x2, +}; + +enum sec_bd_type { + BD_TYPE1 = 0x1, + BD_TYPE2 = 0x2, + BD_TYPE3 = 0x3, +}; + +enum sec_c_width { + C_WIDTH_CS1 = 0x1, + C_WIDTH_CS2 = 0x2, + C_WIDTH_CS3 = 0x3, +}; + +struct hisi_sec_ctx { + struct wd_ctx_config_internal config; +}; + +struct hisi_sec_sqe_type2 { + /* + * mac_len: 0~4 bits + * a_key_len: 5~10 bits + * a_alg: 11~16 bits + */ + __u32 mac_key_alg; + + /* + * c_icv_len: 0~5 bits + * c_width: 6~8 bits + * c_key_len: 9~11 bits + * c_mode: 12~15 bits + */ + __u16 icvw_kmode; + + /* c_alg: 0~3 bits */ + __u8 c_alg; + + __u8 rsvd4; + /* + * a_len: 0~23 bits + * iv_offset_l: 24~31 bits + */ + __u32 alen_ivllen; + + /* + * c_len: 0~23 bits + * iv_offset_h: 24~31 bits + */ + __u32 clen_ivhlen; + + __u16 auth_src_offset; + __u16 cipher_src_offset; + __u16 cs_ip_header_offset; + __u16 cs_udp_header_offset; + __u16 pass_word_len; + __u16 dk_len; + __u8 salt3; + __u8 salt2; + __u8 salt1; + __u8 salt0; + + __u16 tag; + __u16 rsvd5; + + /* + * c_pad_type: 0~3 bits + * c_pad_len: 4~11 bits + * c_pad_data_type: 12~15 bits + */ + __u16 cph_pad; + /* c_pad_len_field: 0~1 bits */ + + __u16 c_pad_len_field; + + __u64 long_a_data_len; + __u64 a_ivin_addr; + + __u64 a_key_addr; + + __u64 mac_addr; + __u64 c_ivin_addr; + __u64 c_key_addr; + + __u64 data_src_addr; + __u64 data_dst_addr; + + /* + * done: 0 bit + * icv: 1~3 bits + * csc: 4~6 bits + * flag: 7~10 bits + * dif_check: 11~13 bits + */ + __u16 done_flag; + + __u8 error_type; + __u8 warning_type; + __u8 mac_i3; + __u8 mac_i2; + __u8 mac_i1; + __u8 mac_i0; + __u16 check_sum_i; + __u8 tls_pad_len_i; + __u8 rsvd12; + __u32 counter; +}; + +struct hisi_sec_sqe { + /* + * type: 0~3 bits; + * cipher: 4~5 bits; + * auth: 6~7 bits; + */ + __u8 type_auth_cipher; + /* + * seq: 0 bits; + * de: 1~2 bits; + * scene: 3~6 bits; + * src_addr_type: 7 bits; + */ + __u8 sds_sa_type; + /* + * src_addr_type: 0~1 bits not used now. + * dst_addr_type: 2~4 bits; + * mac_addr_type: 5~7 bits; + */ + __u8 sdm_addr_type; + + __u8 rsvd0; + /* + * nonce_len(type): 0~3 bits; + */ + __u8 huk_ci_key; + /* + * ai_gen: 0~1 bits; + */ + __u8 ai_apd_cs; + /* + * rhf(type2): 0 bit; + * c_key_type: 1~2 bits; + * a_key_type: 3~4 bits + * write_frame_len(type2): 5~7bits; + */ + __u8 rca_key_frm; + + __u8 iv_tls_ld; + + struct hisi_sec_sqe_type2 type2; +}; + +struct bd3_auth_ivin { + __le64 a_ivin_addr; + __le32 rsvd0; + __le32 rsvd1; +} __attribute__((packed, aligned(4))); + +struct bd3_skip_data { + __le32 rsvd0; + + /* + * gran_num: 0~15 bits + * reserved: 16~31 bits + */ + __le32 gran_num; + + /* + * src_skip_data_len: 0~24 bits + * reserved: 25~31 bits + */ + __le32 src_skip_data_len; + + /* + * dst_skip_data_len: 0~24 bits + * reserved: 25~31 bits + */ + __le32 dst_skip_data_len; +}; + +struct bd3_stream_scene { + __le64 c_ivin_addr; + __le64 long_a_data_len; + + /* + * auth_pad: 0~1 bits + * stream_protocol: 2~4 bits + * reserved: 5~7 bits + */ + __u8 stream_auth_pad; + __u8 plaintext_type; + __le16 pad_len_1p3; +} __attribute__((packed, aligned(4))); + +struct bd3_no_scene { + __le64 c_ivin_addr; + __le32 rsvd0; + __le32 rsvd1; + __le32 rsvd2; +} __attribute__((packed, aligned(4))); + +struct bd3_check_sum { + __u8 rsvd0; + __u8 hac_sva_status; + __le16 check_sum_i; +}; + +struct bd3_tls_type_back { + __u8 tls_1p3_type_back; + __u8 hac_sva_status; + __le16 pad_len_1p3_back; +}; + +struct hisi_sec_sqe3 { + /* + * type: 0~3 bit + * bd_invalid: 4 bit + * scene: 5~8 bit + * de: 9~10 bit + * src_addr_type: 11~13 bit + * dst_addr_type: 14~16 bit + * mac_addr_type: 17~19 bit + * reserved: 20~31 bits + */ + __le32 bd_param; + + /* + * cipher: 0~1 bits + * ci_gen: 2~3 bit + * c_icv_len: 4~9 bit + * c_width: 10~12 bits + * c_key_len: 13~15 bits + */ + __le16 c_icv_key; + + /* + * c_mode : 0~3 bits + * c_alg : 4~7 bits + */ + __u8 c_mode_alg; + + /* + * nonce_len : 0~3 bits + * huk : 4 bits + * cal_iv_addr_en : 5 bits + * seq : 6 bits + * reserved : 7 bits + */ + __u8 huk_iv_seq; + + __le64 tag; + __le64 data_src_addr; + __le64 a_key_addr; + union { + struct bd3_auth_ivin auth_ivin; + struct bd3_skip_data skip_data; + }; + + __le64 c_key_addr; + + /* + * auth: 0~1 bits + * ai_gen: 2~3 bits + * mac_len: 4~8 bits + * akey_len: 9~14 bits + * a_alg: 15~20 bits + * key_sel: 21~24 bits + * ctr_count_mode/sm4_xts: 25~26 bits + * sva_prefetch: 27 bits + * key_wrap_num:28~30 bits + * update_key: 31 bits + */ + __le32 auth_mac_key; + __le32 salt; + __le16 auth_src_offset; + __le16 cipher_src_offset; + + /* + * auth_len: 0~23 bit + * auth_key_offset: 24~31 bits + */ + __le32 a_len_key; + + /* + * cipher_len: 0~23 bit + * auth_ivin_offset: 24~31 bits + */ + __le32 c_len_ivin; + __le64 data_dst_addr; + __le64 mac_addr; + union { + struct bd3_stream_scene stream_scene; + struct bd3_no_scene no_scene; + }; + + /* + * done: 0 bit + * icv: 1~3 bit + * csc: 4~6 bit + * flag: 7~10 bit + * reserved: 11~15 bit + */ + __le16 done_flag; + __u8 error_type; + __u8 warning_type; + union { + __le32 mac_i; + __le32 kek_key_addr_l; + }; + + union { + __le32 kek_key_addr_h; + struct bd3_check_sum check_sum; + struct bd3_tls_type_back tls_type_back; + }; + __le32 counter; +} __attribute__((packed, aligned(4))); + +static int g_digest_a_alg[WD_DIGEST_TYPE_MAX] = { + A_ALG_SM3, A_ALG_MD5, A_ALG_SHA1, A_ALG_SHA256, A_ALG_SHA224, + A_ALG_SHA384, A_ALG_SHA512, A_ALG_SHA512_224, A_ALG_SHA512_256 +}; + +static int g_hmac_a_alg[WD_DIGEST_TYPE_MAX] = { + A_ALG_HMAC_SM3, A_ALG_HMAC_MD5, A_ALG_HMAC_SHA1, + A_ALG_HMAC_SHA256, A_ALG_HMAC_SHA224, A_ALG_HMAC_SHA384, + A_ALG_HMAC_SHA512, A_ALG_HMAC_SHA512_224, A_ALG_HMAC_SHA512_256, + A_ALG_AES_XCBC_MAC_96, A_ALG_AES_XCBC_PRF_128, A_ALG_AES_CMAC, + A_ALG_AES_GMAC +}; + +static __u32 g_sec_hmac_full_len[WD_DIGEST_TYPE_MAX] = { + SEC_HMAC_SM3_MAC_LEN, SEC_HMAC_MD5_MAC_LEN, SEC_HMAC_SHA1_MAC_LEN, + SEC_HMAC_SHA256_MAC_LEN, SEC_HMAC_SHA224_MAC_LEN, SEC_HMAC_SHA384_MAC_LEN, + SEC_HMAC_SHA512_MAC_LEN, SEC_HMAC_SHA512_224_MAC_LEN, SEC_HMAC_SHA512_256_MAC_LEN +}; + +int hisi_sec_init(struct wd_ctx_config_internal *config, void *priv); +void hisi_sec_exit(void *priv); + +static void dump_sec_msg(void *msg, const char *alg) +{ + struct wd_cipher_msg *cmsg; + struct wd_digest_msg *dmsg; + struct wd_aead_msg *amsg; + + WD_ERR("dump %s alg message after a task error occurs.\n", alg); + + if (!strcmp(alg, "cipher")) { + cmsg = (struct wd_cipher_msg *)msg; + WD_ERR("type:%u alg:%u op_type:%u mode:%u data_fmt:%u\n", + cmsg->alg_type, cmsg->alg, cmsg->op_type, cmsg->mode, + cmsg->data_fmt); + WD_ERR("key_bytes:%u iv_bytes:%u in_bytes:%u out_bytes:%u\n", + cmsg->key_bytes, cmsg->iv_bytes, cmsg->in_bytes, cmsg->out_bytes); + } else if (!strcmp(alg, "digest")) { + dmsg = (struct wd_digest_msg *)msg; + WD_ERR("type:%u alg:%u has_next:%u mode:%u data_fmt:%u\n", + dmsg->alg_type, dmsg->alg, dmsg->has_next, dmsg->mode, dmsg->data_fmt); + WD_ERR("key_bytes:%u iv_bytes:%u in_bytes:%u out_bytes:%u\n", + dmsg->key_bytes, dmsg->iv_bytes, dmsg->in_bytes, dmsg->out_bytes); + } else if (!strcmp(alg, "aead")) { + amsg = (struct wd_aead_msg *)msg; + WD_ERR("type:%u calg:%u op_type:%u cmode:%u\n", + amsg->alg_type, amsg->calg, amsg->op_type, amsg->cmode); + WD_ERR("data_fmt:%u ckey_bytes:%u auth_bytes:%u\n", + amsg->data_fmt, amsg->ckey_bytes, amsg->auth_bytes); + WD_ERR("assoc_bytes:%u in_bytes:%u out_bytes:%u\n", + amsg->assoc_bytes, amsg->in_bytes, amsg->out_bytes); + } +} + +static __u8 get_data_fmt_v3(__u32 bd_param) +{ + /* Only check the src addr type */ + if (bd_param & SEC_PBUFF_MODE_MASK_V3) + return WD_SGL_BUF; + + return WD_FLAT_BUF; +} + +static __u8 get_data_fmt_v2(__u32 sds_sa_type) +{ + /* Only check the src addr type */ + if (sds_sa_type & SEC_SGL_SDS_MASK) + return WD_SGL_BUF; + + return WD_FLAT_BUF; +} + +/* increment counter (128-bit int) by software */ +static void ctr_iv_inc(__u8 *counter, __u32 len) +{ + __u32 n = CTR_128BIT_COUNTER; + __u32 c = len; + + do { + --n; + c += counter[n]; + counter[n] = (__u8)c; + c >>= BYTE_BITS; + } while (n); +} + +static void update_iv(struct wd_cipher_msg *msg) +{ + switch (msg->mode) { + case WD_CIPHER_CBC: + case WD_CIPHER_CBC_CS1: + case WD_CIPHER_CBC_CS2: + case WD_CIPHER_CBC_CS3: + if (msg->op_type == WD_CIPHER_ENCRYPTION && + msg->out_bytes >= msg->iv_bytes) + memcpy(msg->iv, msg->out + msg->out_bytes - + msg->iv_bytes, msg->iv_bytes); + if (msg->op_type == WD_CIPHER_DECRYPTION && + msg->in_bytes >= msg->iv_bytes) + memcpy(msg->iv, msg->in + msg->in_bytes - + msg->iv_bytes, msg->iv_bytes); + break; + case WD_CIPHER_OFB: + case WD_CIPHER_CFB: + if (msg->out_bytes >= msg->iv_bytes) + memcpy(msg->iv, msg->out + msg->out_bytes - + msg->iv_bytes, msg->iv_bytes); + break; + case WD_CIPHER_CTR: + ctr_iv_inc(msg->iv, msg->iv_bytes >> + CTR_MODE_LEN_SHIFT); + break; + default: + break; + } +} + +static void update_iv_sgl(struct wd_cipher_msg *msg) +{ + switch (msg->mode) { + case WD_CIPHER_CBC: + if (msg->op_type == WD_CIPHER_ENCRYPTION && + msg->out_bytes >= msg->iv_bytes) + hisi_qm_sgl_copy(msg->iv, msg->out, + msg->out_bytes - msg->iv_bytes, + msg->iv_bytes, COPY_SGL_TO_PBUFF); + + if (msg->op_type == WD_CIPHER_DECRYPTION && + msg->in_bytes >= msg->iv_bytes) + hisi_qm_sgl_copy(msg->iv, msg->in, + msg->in_bytes - msg->iv_bytes, + msg->iv_bytes, COPY_SGL_TO_PBUFF); + + break; + case WD_CIPHER_OFB: + case WD_CIPHER_CFB: + if (msg->out_bytes >= msg->iv_bytes) + hisi_qm_sgl_copy(msg->iv, msg->out, + msg->out_bytes - msg->iv_bytes, + msg->iv_bytes, COPY_SGL_TO_PBUFF); + + break; + case WD_CIPHER_CTR: + ctr_iv_inc(msg->iv, msg->iv_bytes >> + CTR_MODE_LEN_SHIFT); + break; + default: + break; + } +} + +static int get_3des_c_key_len(struct wd_cipher_msg *msg, __u8 *c_key_len) +{ + if (msg->key_bytes == SEC_3DES_2KEY_SIZE) { + *c_key_len = CKEY_LEN_3DES_2KEY; + } else if (msg->key_bytes == SEC_3DES_3KEY_SIZE) { + *c_key_len = CKEY_LEN_3DES_3KEY; + } else { + WD_ERR("failed to check 3des key size, size = %u\n", + msg->key_bytes); + return -WD_EINVAL; + } + + return 0; +} + +static int get_aes_c_key_len(struct wd_cipher_msg *msg, __u8 *c_key_len) +{ + __u16 len; + + len = msg->key_bytes; + if (msg->mode == WD_CIPHER_XTS) + len = len / XTS_MODE_KEY_DIVISOR; + + switch (len) { + case AES_KEYSIZE_128: + *c_key_len = CKEY_LEN_128BIT; + break; + case AES_KEYSIZE_192: + *c_key_len = CKEY_LEN_192BIT; + break; + case AES_KEYSIZE_256: + *c_key_len = CKEY_LEN_256BIT; + break; + default: + WD_ERR("failed to check AES key size, size = %u\n", len); + return -WD_EINVAL; + } + + return 0; +} + +static int fill_cipher_bd2_alg(struct wd_cipher_msg *msg, + struct hisi_sec_sqe *sqe) +{ + __u8 c_key_len = 0; + int ret = 0; + + switch (msg->alg) { + case WD_CIPHER_SM4: + sqe->type2.c_alg = C_ALG_SM4; + sqe->type2.icvw_kmode = CKEY_LEN_SM4 << SEC_CKEY_OFFSET; + break; + case WD_CIPHER_AES: + sqe->type2.c_alg = C_ALG_AES; + ret = get_aes_c_key_len(msg, &c_key_len); + sqe->type2.icvw_kmode = (__u16)c_key_len << SEC_CKEY_OFFSET; + break; + case WD_CIPHER_DES: + sqe->type2.c_alg = C_ALG_DES; + sqe->type2.icvw_kmode = CKEY_LEN_DES; + break; + case WD_CIPHER_3DES: + sqe->type2.c_alg = C_ALG_3DES; + ret = get_3des_c_key_len(msg, &c_key_len); + sqe->type2.icvw_kmode = (__u16)c_key_len << SEC_CKEY_OFFSET; + break; + default: + WD_ERR("failed to check cipher alg type, alg = %u\n", msg->alg); + return -WD_EINVAL; + } + + return ret; +} + +static int fill_cipher_bd2_mode(struct wd_cipher_msg *msg, + struct hisi_sec_sqe *sqe) +{ + __u16 c_mode; + + switch (msg->mode) { + case WD_CIPHER_ECB: + c_mode = C_MODE_ECB; + break; + case WD_CIPHER_CBC: + c_mode = C_MODE_CBC; + break; + case WD_CIPHER_XTS: + c_mode = C_MODE_XTS; + break; + default: + WD_ERR("failed to check cipher mode type, mode = %u\n", + msg->mode); + return -WD_EINVAL; + } + sqe->type2.icvw_kmode |= (__u16)(c_mode) << SEC_CMODE_OFFSET; + + return 0; +} + +static void fill_cipher_bd2_addr(struct wd_cipher_msg *msg, + struct hisi_sec_sqe *sqe) +{ + sqe->type2.data_src_addr = (__u64)(uintptr_t)msg->in; + sqe->type2.data_dst_addr = (__u64)(uintptr_t)msg->out; + sqe->type2.c_ivin_addr = (__u64)(uintptr_t)msg->iv; + sqe->type2.c_key_addr = (__u64)(uintptr_t)msg->key; +} + +static void parse_cipher_bd2(struct hisi_qp *qp, struct hisi_sec_sqe *sqe, + struct wd_cipher_msg *recv_msg) +{ + struct wd_cipher_msg *temp_msg; + __u16 done; + __u32 tag; + + done = sqe->type2.done_flag & SEC_DONE_MASK; + if (done != SEC_HW_TASK_DONE || sqe->type2.error_type) { + WD_ERR("failed to parse cipher BD2! done=0x%x, etype=0x%x\n", + done, sqe->type2.error_type); + recv_msg->result = WD_IN_EPARA; + } else { + recv_msg->result = WD_SUCCESS; + } + + tag = sqe->type2.tag; + recv_msg->tag = tag; + + if (qp->q_info.qp_mode == CTX_MODE_ASYNC) { + recv_msg->alg_type = WD_CIPHER; + recv_msg->data_fmt = get_data_fmt_v2(sqe->sds_sa_type); + recv_msg->in = (__u8 *)(uintptr_t)sqe->type2.data_src_addr; + recv_msg->out = (__u8 *)(uintptr_t)sqe->type2.data_dst_addr; + temp_msg = wd_cipher_get_msg(qp->q_info.idx, tag); + if (!temp_msg) { + recv_msg->result = WD_IN_EPARA; + WD_ERR("failed to get send msg! idx = %u, tag = %u.\n", + qp->q_info.idx, tag); + return; + } + } else { + /* The synchronization mode uses the same message */ + temp_msg = recv_msg; + } + + if (temp_msg->data_fmt != WD_SGL_BUF) + update_iv(temp_msg); + else + update_iv_sgl(temp_msg); + + if (unlikely(recv_msg->result != WD_SUCCESS)) + dump_sec_msg(temp_msg, "cipher"); +} + +static int aes_sm4_len_check(struct wd_cipher_msg *msg) +{ + if ((msg->mode == WD_CIPHER_CBC_CS1 || + msg->mode == WD_CIPHER_CBC_CS2 || + msg->mode == WD_CIPHER_CBC_CS3) && + msg->alg == WD_CIPHER_AES && + msg->in_bytes <= AES_BLOCK_SIZE) { + WD_ERR("failed to check input bytes of AES_CBC_CS_X, size = %u\n", + msg->in_bytes); + return -WD_EINVAL; + } + + if ((msg->mode == WD_CIPHER_CBC || msg->mode == WD_CIPHER_ECB) && + msg->in_bytes & (AES_BLOCK_SIZE - 1)) { + WD_ERR("failed to check input bytes of AES or SM4, size = %u\n", + msg->in_bytes); + return -WD_EINVAL; + } + + return 0; +} + +static int cipher_len_check(struct wd_cipher_msg *msg) +{ + int ret; + + if (msg->in_bytes > MAX_INPUT_DATA_LEN || + !msg->in_bytes) { + WD_ERR("input cipher length is error, size = %u\n", + msg->in_bytes); + return -WD_EINVAL; + } + + if (msg->mode == WD_CIPHER_OFB || + msg->mode == WD_CIPHER_CFB || + msg->mode == WD_CIPHER_CTR) + return 0; + + if (msg->mode == WD_CIPHER_XTS) { + if (msg->in_bytes < AES_BLOCK_SIZE) { + WD_ERR("input cipher length is too small, size = %u\n", + msg->in_bytes); + return -WD_EINVAL; + } + return 0; + } + + if (msg->alg == WD_CIPHER_3DES || msg->alg == WD_CIPHER_DES) { + if (msg->in_bytes & (DES3_BLOCK_SIZE - 1)) { + WD_ERR("failed to check input bytes of 3DES or DES, size = %u\n", + msg->in_bytes); + return -WD_EINVAL; + } + return 0; + } + + if (msg->alg == WD_CIPHER_AES || msg->alg == WD_CIPHER_SM4) { + ret = aes_sm4_len_check(msg); + if (ret) + return ret; + } + + return 0; +} + +static void hisi_sec_put_sgl(handle_t h_qp, __u8 alg_type, void *in, void *out) +{ + handle_t h_sgl_pool; + + h_sgl_pool = hisi_qm_get_sglpool(h_qp); + if (!h_sgl_pool) + return; + + hisi_qm_put_hw_sgl(h_sgl_pool, in); + + if (alg_type != WD_DIGEST) + hisi_qm_put_hw_sgl(h_sgl_pool, out); +} + +static int hisi_sec_fill_sgl(handle_t h_qp, __u8 **in, __u8 **out, + struct hisi_sec_sqe *sqe, __u8 type) +{ + handle_t h_sgl_pool; + void *hw_sgl_in; + void *hw_sgl_out; + + h_sgl_pool = hisi_qm_get_sglpool(h_qp); + if (!h_sgl_pool) { + WD_ERR("failed to get sglpool for hw_v2!\n"); + return -WD_EINVAL; + } + + hw_sgl_in = hisi_qm_get_hw_sgl(h_sgl_pool, (struct wd_datalist *)(*in)); + if (!hw_sgl_in) { + WD_ERR("failed to get sgl in for hw_v2!\n"); + return -WD_EINVAL; + } + + if (type == WD_DIGEST) { + hw_sgl_out = *out; + } else { + hw_sgl_out = hisi_qm_get_hw_sgl(h_sgl_pool, + (struct wd_datalist *)(*out)); + if (!hw_sgl_out) { + WD_ERR("failed to get hw sgl out for hw_v2!\n"); + hisi_qm_put_hw_sgl(h_sgl_pool, hw_sgl_in); + return -WD_EINVAL; + } + + sqe->sdm_addr_type |= SEC_SGL_SDM_MASK; + } + + sqe->sds_sa_type |= SEC_SGL_SDS_MASK; + *in = hw_sgl_in; + *out = hw_sgl_out; + + return 0; +} + +static int hisi_sec_fill_sgl_v3(handle_t h_qp, __u8 **in, __u8 **out, + struct hisi_sec_sqe3 *sqe, __u8 type) +{ + handle_t h_sgl_pool; + void *hw_sgl_in; + void *hw_sgl_out; + + h_sgl_pool = hisi_qm_get_sglpool(h_qp); + if (!h_sgl_pool) { + WD_ERR("failed to get sglpool for hw_v3!\n"); + return -WD_EINVAL; + } + + hw_sgl_in = hisi_qm_get_hw_sgl(h_sgl_pool, (struct wd_datalist *)(*in)); + if (!hw_sgl_in) { + WD_ERR("failed to get sgl in for hw_v3!\n"); + return -WD_EINVAL; + } + + if (type == WD_DIGEST) { + hw_sgl_out = *out; + sqe->bd_param |= SEC_PBUFF_MODE_MASK_V3; + } else { + hw_sgl_out = hisi_qm_get_hw_sgl(h_sgl_pool, + (struct wd_datalist *)(*out)); + if (!hw_sgl_out) { + WD_ERR("failed to get hw sgl out for hw_v3!\n"); + hisi_qm_put_hw_sgl(h_sgl_pool, hw_sgl_in); + return -WD_EINVAL; + } + + /* + * src_addr_type: 11~13 bit + * dst_addr_type: 14~16 bit + */ + sqe->bd_param |= SEC_SGL_MODE_MASK_V3; + } + + *in = hw_sgl_in; + *out = hw_sgl_out; + + return 0; +} + +static int fill_cipher_bd2(struct wd_cipher_msg *msg, struct hisi_sec_sqe *sqe) +{ + __u8 scene, cipher, de; + int ret; + + /* config BD type */ + sqe->type_auth_cipher = BD_TYPE2; + /* config scene */ + scene = SEC_IPSEC_SCENE << SEC_SCENE_OFFSET; + de = DATA_DST_ADDR_ENABLE << SEC_DE_OFFSET; + sqe->sds_sa_type = (__u8)(de | scene); + + if (msg->op_type == WD_CIPHER_ENCRYPTION) + cipher = SEC_CIPHER_ENC << SEC_CIPHER_OFFSET; + else + cipher = SEC_CIPHER_DEC << SEC_CIPHER_OFFSET; + + sqe->type_auth_cipher |= cipher; + + ret = cipher_len_check(msg); + if (ret) + return ret; + + ret = fill_cipher_bd2_alg(msg, sqe); + if (ret) { + WD_ERR("failed to fill bd alg!\n"); + return ret; + } + + ret = fill_cipher_bd2_mode(msg, sqe); + if (ret) { + WD_ERR("failed to fill bd mode!\n"); + return ret; + } + + return 0; +} + +int hisi_sec_cipher_send(handle_t ctx, void *cipher_msg) +{ + handle_t h_qp = (handle_t)wd_ctx_get_priv(ctx); + struct wd_cipher_msg *msg = cipher_msg; + struct hisi_sec_sqe sqe; + __u16 count = 0; + int ret; + + if (!msg) { + WD_ERR("invalid: input cipher msg is NULL!\n"); + return -WD_EINVAL; + } + + memset(&sqe, 0, sizeof(struct hisi_sec_sqe)); + ret = fill_cipher_bd2(msg, &sqe); + if (ret) + return ret; + + if (msg->data_fmt == WD_SGL_BUF) { + ret = hisi_sec_fill_sgl(h_qp, &msg->in, &msg->out, &sqe, + msg->alg_type); + if (ret) + return ret; + } + + hisi_set_msg_id(h_qp, &msg->tag); + sqe.type2.clen_ivhlen |= (__u32)msg->in_bytes; + sqe.type2.tag = (__u16)msg->tag; + fill_cipher_bd2_addr(msg, &sqe); + + ret = hisi_qm_send(h_qp, &sqe, 1, &count); + if (ret < 0) { + if (ret != -WD_EBUSY) + WD_ERR("cipher send sqe is err(%d)!\n", ret); + + if (msg->data_fmt == WD_SGL_BUF) + hisi_sec_put_sgl(h_qp, msg->alg_type, msg->in, + msg->out); + + return ret; + } + + return 0; +} + +int hisi_sec_cipher_recv(handle_t ctx, void *cipher_msg) +{ + handle_t h_qp = (handle_t)wd_ctx_get_priv(ctx); + struct wd_cipher_msg *recv_msg = cipher_msg; + struct hisi_sec_sqe sqe; + __u16 count = 0; + int ret; + + ret = hisi_qm_recv(h_qp, &sqe, 1, &count); + if (ret < 0) + return ret; + + ret = hisi_check_bd_id(h_qp, (__u16)recv_msg->tag, sqe.type2.tag); + if (ret) + return ret; + + parse_cipher_bd2((struct hisi_qp *)h_qp, &sqe, recv_msg); + + if (recv_msg->data_fmt == WD_SGL_BUF) + hisi_sec_put_sgl(h_qp, recv_msg->alg_type, recv_msg->in, + recv_msg->out); + + return 0; +} + +static struct wd_cipher_driver hisi_cipher_driver = { + .drv_name = "hisi_sec2", + .alg_name = "cipher", + .drv_ctx_size = sizeof(struct hisi_sec_ctx), + .init = hisi_sec_init, + .exit = hisi_sec_exit, +}; + +WD_CIPHER_SET_DRIVER(hisi_cipher_driver); + +static int fill_cipher_bd3_alg(struct wd_cipher_msg *msg, + struct hisi_sec_sqe3 *sqe) +{ + __u8 c_key_len = 0; + int ret = 0; + + switch (msg->alg) { + case WD_CIPHER_SM4: + sqe->c_mode_alg |= C_ALG_SM4 << SEC_CALG_OFFSET_V3; + sqe->c_icv_key |= CKEY_LEN_SM4 << SEC_CKEY_OFFSET_V3; + break; + case WD_CIPHER_AES: + sqe->c_mode_alg |= C_ALG_AES << SEC_CALG_OFFSET_V3; + ret = get_aes_c_key_len(msg, &c_key_len); + sqe->c_icv_key |= (__u16)c_key_len << SEC_CKEY_OFFSET_V3; + break; + case WD_CIPHER_DES: + sqe->c_mode_alg |= C_ALG_DES << SEC_CALG_OFFSET_V3; + sqe->c_icv_key |= CKEY_LEN_DES << SEC_CKEY_OFFSET_V3; + break; + case WD_CIPHER_3DES: + sqe->c_mode_alg |= C_ALG_3DES << SEC_CALG_OFFSET_V3; + ret = get_3des_c_key_len(msg, &c_key_len); + sqe->c_icv_key |= (__u16)c_key_len << SEC_CKEY_OFFSET_V3; + break; + default: + WD_ERR("failed to check cipher alg type, alg = %u\n", msg->alg); + return -WD_EINVAL; + } + + return ret; +} + +static int fill_cipher_bd3_mode(struct wd_cipher_msg *msg, + struct hisi_sec_sqe3 *sqe) +{ + __u16 c_mode; + + switch (msg->mode) { + case WD_CIPHER_ECB: + c_mode = C_MODE_ECB; + break; + case WD_CIPHER_CBC: + c_mode = C_MODE_CBC; + break; + case WD_CIPHER_OFB: + c_mode = C_MODE_OFB; + break; + case WD_CIPHER_CTR: + c_mode = C_MODE_CTR; + /* Set the CTR counter mode is 128bit rollover */ + sqe->auth_mac_key = (__u32)(SEC_CTR_CNT_ROLLOVER << + SEC_CTR_CNT_OFFSET); + break; + case WD_CIPHER_XTS: + c_mode = C_MODE_XTS; + break; + case WD_CIPHER_CFB: + c_mode = C_MODE_CFB; + break; + case WD_CIPHER_CBC_CS1: + c_mode = C_MODE_CBC_CS; + sqe->c_icv_key |= C_WIDTH_CS1 << SEC_CWIDTH_OFFSET_V3; + break; + case WD_CIPHER_CBC_CS2: + c_mode = C_MODE_CBC_CS; + sqe->c_icv_key |= C_WIDTH_CS2 << SEC_CWIDTH_OFFSET_V3; + break; + case WD_CIPHER_CBC_CS3: + c_mode = C_MODE_CBC_CS; + sqe->c_icv_key |= C_WIDTH_CS3 << SEC_CWIDTH_OFFSET_V3; + break; + default: + WD_ERR("failed to check cipher mode type, mode = %u\n", + msg->mode); + return -WD_EINVAL; + } + sqe->c_mode_alg |= (__u16)c_mode; + + return 0; +} + +static void fill_cipher_bd3_addr(struct wd_cipher_msg *msg, + struct hisi_sec_sqe3 *sqe) +{ + sqe->data_src_addr = (__u64)(uintptr_t)msg->in; + sqe->data_dst_addr = (__u64)(uintptr_t)msg->out; + sqe->no_scene.c_ivin_addr = (__u64)(uintptr_t)msg->iv; + sqe->c_key_addr = (__u64)(uintptr_t)msg->key; +} + +static int fill_cipher_bd3(struct wd_cipher_msg *msg, struct hisi_sec_sqe3 *sqe) +{ + __u16 scene, de; + int ret; + + /* config BD type */ + sqe->bd_param = BD_TYPE3; + /* config scene */ + scene = SEC_IPSEC_SCENE << SEC_SCENE_OFFSET_V3; + de = DATA_DST_ADDR_ENABLE << SEC_DE_OFFSET_V3; + sqe->bd_param |= (__u16)(de | scene); + + if (msg->op_type == WD_CIPHER_ENCRYPTION) + sqe->c_icv_key = SEC_CIPHER_ENC; + else + sqe->c_icv_key = SEC_CIPHER_DEC; + + ret = cipher_len_check(msg); + if (ret) + return ret; + + ret = fill_cipher_bd3_alg(msg, sqe); + if (ret) { + WD_ERR("failed to fill bd alg!\n"); + return ret; + } + + ret = fill_cipher_bd3_mode(msg, sqe); + if (ret) { + WD_ERR("failed to fill bd mode!\n"); + return ret; + } + + return 0; +} + +int hisi_sec_cipher_send_v3(handle_t ctx, void *cipher_msg) +{ + handle_t h_qp = (handle_t)wd_ctx_get_priv(ctx); + struct wd_cipher_msg *msg = cipher_msg; + struct hisi_sec_sqe3 sqe; + __u16 count = 0; + int ret; + + if (!msg) { + WD_ERR("invalid: input cipher msg is NULL!\n"); + return -WD_EINVAL; + } + + memset(&sqe, 0, sizeof(struct hisi_sec_sqe3)); + ret = fill_cipher_bd3(msg, &sqe); + if (ret) + return ret; + + if (msg->data_fmt == WD_SGL_BUF) { + ret = hisi_sec_fill_sgl_v3(h_qp, &msg->in, &msg->out, &sqe, + msg->alg_type); + if (ret) + return ret; + } + + hisi_set_msg_id(h_qp, &msg->tag); + sqe.c_len_ivin = (__u32)msg->in_bytes; + sqe.tag = (__u64)(uintptr_t)msg->tag; + fill_cipher_bd3_addr(msg, &sqe); + + ret = hisi_qm_send(h_qp, &sqe, 1, &count); + if (ret < 0) { + if (ret != -WD_EBUSY) + WD_ERR("cipher send sqe is err(%d)!\n", ret); + + if (msg->data_fmt == WD_SGL_BUF) + hisi_sec_put_sgl(h_qp, msg->alg_type, msg->in, + msg->out); + + return ret; + } + + return 0; +} + +static void parse_cipher_bd3(struct hisi_qp *qp, struct hisi_sec_sqe3 *sqe, + struct wd_cipher_msg *recv_msg) +{ + struct wd_cipher_msg *temp_msg; + __u16 done; + __u32 tag; + + done = sqe->done_flag & SEC_DONE_MASK; + if (done != SEC_HW_TASK_DONE || sqe->error_type) { + WD_ERR("failed to parse cipher BD3! done=0x%x, etype=0x%x\n", + done, sqe->error_type); + recv_msg->result = WD_IN_EPARA; + } else { + recv_msg->result = WD_SUCCESS; + } + + tag = sqe->tag; + + recv_msg->tag = tag; + if (qp->q_info.qp_mode == CTX_MODE_ASYNC) { + recv_msg->alg_type = WD_CIPHER; + recv_msg->data_fmt = get_data_fmt_v3(sqe->bd_param); + recv_msg->in = (__u8 *)(uintptr_t)sqe->data_src_addr; + recv_msg->out = (__u8 *)(uintptr_t)sqe->data_dst_addr; + temp_msg = wd_cipher_get_msg(qp->q_info.idx, tag); + if (!temp_msg) { + recv_msg->result = WD_IN_EPARA; + WD_ERR("failed to get send msg! idx = %u, tag = %u.\n", + qp->q_info.idx, tag); + return; + } + } else { + /* The synchronization mode uses the same message */ + temp_msg = recv_msg; + } + + if (temp_msg->data_fmt != WD_SGL_BUF) + update_iv(temp_msg); + else + update_iv_sgl(temp_msg); + + if (unlikely(recv_msg->result != WD_SUCCESS)) + dump_sec_msg(temp_msg, "cipher"); +} + +int hisi_sec_cipher_recv_v3(handle_t ctx, void *cipher_msg) +{ + handle_t h_qp = (handle_t)wd_ctx_get_priv(ctx); + struct wd_cipher_msg *recv_msg = cipher_msg; + struct hisi_sec_sqe3 sqe; + __u16 count = 0; + int ret; + + ret = hisi_qm_recv(h_qp, &sqe, 1, &count); + if (ret < 0) + return ret; + + ret = hisi_check_bd_id(h_qp, recv_msg->tag, sqe.tag); + if (ret) + return ret; + + parse_cipher_bd3((struct hisi_qp *)h_qp, &sqe, recv_msg); + + if (recv_msg->data_fmt == WD_SGL_BUF) + hisi_sec_put_sgl(h_qp, recv_msg->alg_type, recv_msg->in, + recv_msg->out); + + return 0; +} + +static int fill_digest_bd2_alg(struct wd_digest_msg *msg, + struct hisi_sec_sqe *sqe) +{ + if (msg->alg >= WD_DIGEST_TYPE_MAX) { + WD_ERR("failed to check digest alg type, alg = %u\n", msg->alg); + return -WD_EINVAL; + } + + /* + * Long hash mode must config full output length, 0 mac len indicates + * the output full length. + */ + if (!msg->has_next) + sqe->type2.mac_key_alg = msg->out_bytes / WORD_BYTES; + + /* SM3 can't config 0 in normal mode */ + if (msg->has_next && msg->mode == WD_DIGEST_NORMAL && + msg->alg == WD_DIGEST_SM3) + sqe->type2.mac_key_alg = g_sec_hmac_full_len[msg->alg]; + + if (msg->has_next && msg->mode == WD_DIGEST_HMAC) + sqe->type2.mac_key_alg = g_sec_hmac_full_len[msg->alg]; + + if (msg->mode == WD_DIGEST_NORMAL) + sqe->type2.mac_key_alg |= + (__u32)g_digest_a_alg[msg->alg] << AUTH_ALG_OFFSET; + else if (msg->mode == WD_DIGEST_HMAC) { + if (msg->key_bytes & WORD_ALIGNMENT_MASK) { + WD_ERR("failed to check digest key_bytes, size = %u\n", + msg->key_bytes); + return -WD_EINVAL; + } + sqe->type2.mac_key_alg |= (__u32)(msg->key_bytes / + WORD_BYTES) << MAC_LEN_OFFSET; + sqe->type2.a_key_addr = (__u64)(uintptr_t)msg->key; + + sqe->type2.mac_key_alg |= + (__u32)g_hmac_a_alg[msg->alg] << AUTH_ALG_OFFSET; + } else { + WD_ERR("failed to check digest mode, mode = %u\n", msg->mode); + return -WD_EINVAL; + } + + return WD_SUCCESS; +} + +static int long_hash_param_check(handle_t h_qp, struct wd_digest_msg *msg) +{ + struct hisi_qp *qp = (struct hisi_qp *)h_qp; + + if (qp->q_info.qp_mode == CTX_MODE_ASYNC && msg->has_next) { + WD_ERR("invalid: async mode not supports long hash!\n"); + return -WD_EINVAL; + } + + if (msg->data_fmt == WD_SGL_BUF && msg->has_next) { + WD_ERR("invalid: sgl mode not supports long hash!\n"); + return -WD_EINVAL; + } + + return 0; +} + +static int fill_digest_long_hash(handle_t h_qp, struct wd_digest_msg *msg, + struct hisi_sec_sqe *sqe) +{ + __u64 total_bits; + int ret; + + ret = long_hash_param_check(h_qp, msg); + if (ret) + return ret; + + if (msg->has_next && !msg->iv_bytes) { + /* Long hash first */ + sqe->ai_apd_cs = AI_GEN_INNER; + sqe->ai_apd_cs |= AUTHPAD_NOPAD << AUTHPAD_OFFSET; + } + + if (msg->has_next && msg->iv_bytes) { + /* Long hash middle */ + sqe->ai_apd_cs = AI_GEN_IVIN_ADDR; + sqe->ai_apd_cs |= AUTHPAD_NOPAD << AUTHPAD_OFFSET; + sqe->type2.a_ivin_addr = sqe->type2.mac_addr; + } + + if (!msg->has_next && msg->iv_bytes) { + /* Long hash end */ + sqe->ai_apd_cs = AI_GEN_IVIN_ADDR; + sqe->ai_apd_cs |= AUTHPAD_PAD << AUTHPAD_OFFSET; + sqe->type2.a_ivin_addr = sqe->type2.mac_addr; + + /* The max total_bits length is LONG_MAX */ + total_bits = msg->long_data_len * BYTE_BITS; + sqe->type2.long_a_data_len = total_bits; + } + + return 0; +} + +static void parse_digest_bd2(struct hisi_qp *qp, struct hisi_sec_sqe *sqe, + struct wd_digest_msg *recv_msg) +{ + struct wd_digest_msg *temp_msg; + __u16 done; + + done = sqe->type2.done_flag & SEC_DONE_MASK; + if (done != SEC_HW_TASK_DONE || sqe->type2.error_type) { + WD_ERR("failed to parse digest BD2! done=0x%x, etype=0x%x\n", + done, sqe->type2.error_type); + recv_msg->result = WD_IN_EPARA; + } else { + recv_msg->result = WD_SUCCESS; + } + + recv_msg->tag = sqe->type2.tag; + + if (qp->q_info.qp_mode == CTX_MODE_ASYNC) { + recv_msg->alg_type = WD_DIGEST; + recv_msg->data_fmt = get_data_fmt_v2(sqe->sds_sa_type); + recv_msg->in = (__u8 *)(uintptr_t)sqe->type2.data_src_addr; + temp_msg = wd_digest_get_msg(qp->q_info.idx, recv_msg->tag); + if (!temp_msg) { + recv_msg->result = WD_IN_EPARA; + WD_ERR("failed to get send msg! idx = %u, tag = %u.\n", + qp->q_info.idx, recv_msg->tag); + return; + } + } else { + /* The synchronization mode uses the same message */ + temp_msg = recv_msg; + } + + if (unlikely(recv_msg->result != WD_SUCCESS)) + dump_sec_msg(temp_msg, "digest"); +} + +static int digest_long_bd_align_check(struct wd_digest_msg *msg) +{ + __u32 alg_align_sz; + + alg_align_sz = msg->alg >= WD_DIGEST_SHA384 ? + SHA512_ALIGN_SZ - 1 : SHA1_ALIGN_SZ - 1; + + if (msg->in_bytes & alg_align_sz) + return -WD_EINVAL; + + return 0; +} + +static int aes_auth_len_check(struct wd_digest_msg *msg) +{ + if ((msg->alg == WD_DIGEST_AES_XCBC_MAC_96 || + msg->alg == WD_DIGEST_AES_XCBC_PRF_128 || + msg->alg == WD_DIGEST_AES_CMAC) && !msg->in_bytes) { + WD_ERR("digest mode: %u not supports 0 size!\n", msg->alg); + return -WD_EINVAL; + } + + return 0; +} + +static int digest_len_check(struct wd_digest_msg *msg, enum sec_bd_type type) +{ + int ret; + + /* End BD not need to check the input zero bytes */ + if (unlikely(type == BD_TYPE2 && !msg->has_next && !msg->in_bytes)) { + WD_ERR("kunpeng 920, digest mode not support 0 size!\n"); + return -WD_EINVAL; + } + + if (type == BD_TYPE3) { + ret = aes_auth_len_check(msg); + if (ret) + return ret; + } + + if (unlikely(msg->in_bytes > MAX_INPUT_DATA_LEN)) { + WD_ERR("digest input length is too long, size = %u\n", + msg->in_bytes); + return -WD_EINVAL; + } + + if (unlikely(msg->out_bytes & WORD_ALIGNMENT_MASK)) { + WD_ERR("digest out length is error, size = %u\n", + msg->out_bytes); + return -WD_EINVAL; + } + + if (msg->has_next) { + ret = digest_long_bd_align_check(msg); + if (ret) { + WD_ERR("input data isn't aligned, size = %u\n", + msg->in_bytes); + return -WD_EINVAL; + } + } + + return 0; +} + +int hisi_sec_digest_send(handle_t ctx, void *digest_msg) +{ + handle_t h_qp = (handle_t)wd_ctx_get_priv(ctx); + struct wd_digest_msg *msg = digest_msg; + struct hisi_sec_sqe sqe; + __u16 count = 0; + __u8 scene; + __u8 de; + int ret; + + if (!msg) { + WD_ERR("invalid: input digest msg is NULL!\n"); + return -WD_EINVAL; + } + + ret = digest_len_check(msg, BD_TYPE2); + if (unlikely(ret)) + return ret; + + memset(&sqe, 0, sizeof(struct hisi_sec_sqe)); + /* config BD type */ + sqe.type_auth_cipher = BD_TYPE2; + sqe.type_auth_cipher |= AUTH_HMAC_CALCULATE << AUTHTYPE_OFFSET; + + /* config scene */ + scene = SEC_IPSEC_SCENE << SEC_SCENE_OFFSET; + de = DATA_DST_ADDR_DISABLE << SEC_DE_OFFSET; + + if (msg->data_fmt == WD_SGL_BUF) { + ret = hisi_sec_fill_sgl(h_qp, &msg->in, &msg->out, &sqe, + msg->alg_type); + if (ret) + return ret; + } + + sqe.sds_sa_type |= (__u8)(de | scene); + sqe.type2.alen_ivllen |= (__u32)msg->in_bytes; + sqe.type2.data_src_addr = (__u64)(uintptr_t)msg->in; + sqe.type2.mac_addr = (__u64)(uintptr_t)msg->out; + + ret = fill_digest_bd2_alg(msg, &sqe); + if (ret) + goto put_sgl; + + ret = fill_digest_long_hash(h_qp, msg, &sqe); + if (ret) + goto put_sgl; + + hisi_set_msg_id(h_qp, &msg->tag); + sqe.type2.tag = (__u16)msg->tag; + ret = hisi_qm_send(h_qp, &sqe, 1, &count); + if (ret < 0) { + if (ret != -WD_EBUSY) + WD_ERR("digest send sqe is err(%d)!\n", ret); + + goto put_sgl; + } + + return 0; + +put_sgl: + if (msg->data_fmt == WD_SGL_BUF) + hisi_sec_put_sgl(h_qp, msg->alg_type, msg->in, msg->out); + + return ret; +} + +int hisi_sec_digest_recv(handle_t ctx, void *digest_msg) +{ + handle_t h_qp = (handle_t)wd_ctx_get_priv(ctx); + struct wd_digest_msg *recv_msg = digest_msg; + struct hisi_sec_sqe sqe; + __u16 count = 0; + int ret; + + ret = hisi_qm_recv(h_qp, &sqe, 1, &count); + if (ret < 0) + return ret; + + ret = hisi_check_bd_id(h_qp, (__u16)recv_msg->tag, sqe.type2.tag); + if (ret) + return ret; + + parse_digest_bd2((struct hisi_qp *)h_qp, &sqe, recv_msg); + + if (recv_msg->data_fmt == WD_SGL_BUF) + hisi_sec_put_sgl(h_qp, recv_msg->alg_type, recv_msg->in, + recv_msg->out); + + return 0; +} + +static struct wd_digest_driver hisi_digest_driver = { + .drv_name = "hisi_sec2", + .alg_name = "digest", + .drv_ctx_size = sizeof(struct hisi_sec_ctx), + .init = hisi_sec_init, + .exit = hisi_sec_exit, +}; + +WD_DIGEST_SET_DRIVER(hisi_digest_driver); + +static int hmac_key_len_check(struct wd_digest_msg *msg) +{ + switch (msg->alg) { + case WD_DIGEST_AES_XCBC_MAC_96: + case WD_DIGEST_AES_XCBC_PRF_128: + case WD_DIGEST_AES_CMAC: + if (msg->key_bytes != AES_KEYSIZE_128) { + WD_ERR("failed to check digest key bytes, size = %u\n", + msg->key_bytes); + return -WD_EINVAL; + } + break; + default: + if (msg->key_bytes & WORD_ALIGNMENT_MASK) { + WD_ERR("failed to check digest key bytes, size = %u\n", + msg->key_bytes); + return -WD_EINVAL; + } + break; + } + + return 0; +} + +static int fill_digest_bd3_alg(struct wd_digest_msg *msg, + struct hisi_sec_sqe3 *sqe) +{ + int ret; + + if (msg->alg >= WD_DIGEST_TYPE_MAX) { + WD_ERR("failed to check digest type, alg = %u\n", msg->alg); + return -WD_EINVAL; + } + + /* + * Long hash mode must config full output length, 0 mac len indicates + * the output full length. + */ + if (!msg->has_next) + sqe->auth_mac_key |= (msg->out_bytes / WORD_BYTES) << + SEC_MAC_OFFSET_V3; + + /* SM3 can't config 0 in normal mode */ + if (msg->has_next && msg->mode == WD_DIGEST_NORMAL && + msg->alg == WD_DIGEST_SM3) + sqe->auth_mac_key |= g_sec_hmac_full_len[msg->alg] << + SEC_MAC_OFFSET_V3; + + if (msg->has_next && msg->mode == WD_DIGEST_HMAC) + sqe->auth_mac_key |= g_sec_hmac_full_len[msg->alg] << + SEC_MAC_OFFSET_V3; + + if (msg->mode == WD_DIGEST_NORMAL) { + sqe->auth_mac_key |= + (__u32)g_digest_a_alg[msg->alg] << SEC_AUTH_ALG_OFFSET_V3; + } else if (msg->mode == WD_DIGEST_HMAC) { + ret = hmac_key_len_check(msg); + if (ret) + return ret; + + sqe->auth_mac_key |= (__u32)(msg->key_bytes / + WORD_BYTES) << SEC_AKEY_OFFSET_V3; + sqe->a_key_addr = (__u64)(uintptr_t)msg->key; + sqe->auth_mac_key |= + (__u32)g_hmac_a_alg[msg->alg] << SEC_AUTH_ALG_OFFSET_V3; + + if (msg->alg == WD_DIGEST_AES_GMAC) { + sqe->auth_mac_key |= AI_GEN_IVIN_ADDR << SEC_AI_GEN_OFFSET_V3; + sqe->auth_ivin.a_ivin_addr = (__u64)(uintptr_t)msg->iv; + } + } else { + WD_ERR("failed to check digest mode, mode = %u\n", msg->mode); + return -WD_EINVAL; + } + + return WD_SUCCESS; +} + +static int aes_auth_long_hash_check(struct wd_digest_msg *msg) +{ + if ((msg->alg == WD_DIGEST_AES_XCBC_MAC_96 || + msg->alg == WD_DIGEST_AES_XCBC_PRF_128 || + msg->alg == WD_DIGEST_AES_CMAC || + msg->alg == WD_DIGEST_AES_GMAC) && msg->has_next) { + WD_ERR("aes auth algs not supports long hash mode!\n"); + return -WD_EINVAL; + } + + return 0; +} + +static int fill_digest_long_hash3(handle_t h_qp, struct wd_digest_msg *msg, + struct hisi_sec_sqe3 *sqe) +{ + __u64 total_bits; + int ret; + + ret = long_hash_param_check(h_qp, msg); + if (ret) + return ret; + + ret = aes_auth_long_hash_check(msg); + if (ret) + return ret; + + if (msg->has_next && !msg->iv_bytes) { + /* Long hash first */ + sqe->auth_mac_key |= AI_GEN_INNER << SEC_AI_GEN_OFFSET_V3; + sqe->stream_scene.stream_auth_pad = AUTHPAD_NOPAD; + } + + if (msg->has_next && msg->iv_bytes) { + /* Long hash middle */ + sqe->auth_mac_key |= AI_GEN_IVIN_ADDR << SEC_AI_GEN_OFFSET_V3; + sqe->stream_scene.stream_auth_pad = AUTHPAD_NOPAD; + sqe->auth_ivin.a_ivin_addr = sqe->mac_addr; + } + + if (!msg->has_next && msg->iv_bytes) { + /* Long hash end */ + sqe->auth_mac_key |= AI_GEN_IVIN_ADDR << SEC_AI_GEN_OFFSET_V3; + sqe->stream_scene.stream_auth_pad = AUTHPAD_PAD; + sqe->auth_ivin.a_ivin_addr = sqe->mac_addr; + + /* The max total_bits length is LONG_MAX */ + total_bits = msg->long_data_len * BYTE_BITS; + sqe->stream_scene.long_a_data_len = total_bits; + } + + return 0; +} + +static void fill_digest_v3_scene(struct hisi_sec_sqe3 *sqe, + struct wd_digest_msg *msg) +{ + __u16 scene, de; + + /* config BD type */ + sqe->bd_param = BD_TYPE3; + + /* config scene */ + if (msg->alg == WD_DIGEST_AES_GMAC) + scene = SEC_IPSEC_SCENE << SEC_SCENE_OFFSET_V3; + else + scene = SEC_STREAM_SCENE << SEC_SCENE_OFFSET_V3; + + de = DATA_DST_ADDR_DISABLE << SEC_DE_OFFSET_V3; + + sqe->bd_param |= (__u16)(de | scene); +} + +int hisi_sec_digest_send_v3(handle_t ctx, void *digest_msg) +{ + handle_t h_qp = (handle_t)wd_ctx_get_priv(ctx); + struct wd_digest_msg *msg = digest_msg; + struct hisi_sec_sqe3 sqe; + __u16 count = 0; + int ret; + + if (!msg) { + WD_ERR("invalid: input digest msg is NULL!\n"); + return -WD_EINVAL; + } + + ret = digest_len_check(msg, BD_TYPE3); + if (unlikely(ret)) + return ret; + + memset(&sqe, 0, sizeof(struct hisi_sec_sqe3)); + fill_digest_v3_scene(&sqe, msg); + + sqe.auth_mac_key = AUTH_HMAC_CALCULATE; + + if (msg->data_fmt == WD_SGL_BUF) { + ret = hisi_sec_fill_sgl_v3(h_qp, &msg->in, &msg->out, &sqe, + msg->alg_type); + if (ret) + return ret; + } + + sqe.a_len_key = (__u32)msg->in_bytes; + sqe.data_src_addr = (__u64)(uintptr_t)msg->in; + sqe.mac_addr = (__u64)(uintptr_t)msg->out; + + ret = fill_digest_bd3_alg(msg, &sqe); + if (ret) + goto put_sgl; + + ret = fill_digest_long_hash3(h_qp, msg, &sqe); + if (ret) + goto put_sgl; + + hisi_set_msg_id(h_qp, &msg->tag); + sqe.tag = (__u64)(uintptr_t)msg->tag; + + ret = hisi_qm_send(h_qp, &sqe, 1, &count); + if (ret < 0) { + if (ret != -WD_EBUSY) + WD_ERR("digest send sqe is err(%d)!\n", ret); + + goto put_sgl; + } + + return 0; + +put_sgl: + if (msg->data_fmt == WD_SGL_BUF) + hisi_sec_put_sgl(h_qp, msg->alg_type, msg->in, msg->out); + + return ret; +} + +static void parse_digest_bd3(struct hisi_qp *qp, struct hisi_sec_sqe3 *sqe, + struct wd_digest_msg *recv_msg) +{ + struct wd_digest_msg *temp_msg; + __u16 done; + + done = sqe->done_flag & SEC_DONE_MASK; + if (done != SEC_HW_TASK_DONE || sqe->error_type) { + WD_ERR("failed to parse digest BD3! done=0x%x, etype=0x%x\n", + done, sqe->error_type); + recv_msg->result = WD_IN_EPARA; + } else { + recv_msg->result = WD_SUCCESS; + } + + recv_msg->tag = sqe->tag; + + if (qp->q_info.qp_mode == CTX_MODE_ASYNC) { + recv_msg->alg_type = WD_DIGEST; + recv_msg->data_fmt = get_data_fmt_v3(sqe->bd_param); + recv_msg->in = (__u8 *)(uintptr_t)sqe->data_src_addr; + temp_msg = wd_digest_get_msg(qp->q_info.idx, recv_msg->tag); + if (!temp_msg) { + recv_msg->result = WD_IN_EPARA; + WD_ERR("failed to get send msg! idx = %u, tag = %u.\n", + qp->q_info.idx, recv_msg->tag); + return; + } + } else { + /* The synchronization mode uses the same message */ + temp_msg = recv_msg; + } + + if (unlikely(recv_msg->result != WD_SUCCESS)) + dump_sec_msg(temp_msg, "digest"); +} + +int hisi_sec_digest_recv_v3(handle_t ctx, void *digest_msg) +{ + handle_t h_qp = (handle_t)wd_ctx_get_priv(ctx); + struct wd_digest_msg *recv_msg = digest_msg; + struct hisi_sec_sqe3 sqe; + __u16 count = 0; + int ret; + + ret = hisi_qm_recv(h_qp, &sqe, 1, &count); + if (ret < 0) + return ret; + + ret = hisi_check_bd_id(h_qp, recv_msg->tag, sqe.tag); + if (ret) + return ret; + + parse_digest_bd3((struct hisi_qp *)h_qp, &sqe, recv_msg); + + if (recv_msg->data_fmt == WD_SGL_BUF) + hisi_sec_put_sgl(h_qp, recv_msg->alg_type, recv_msg->in, + recv_msg->out); + + return 0; +} + +static int aead_get_aes_key_len(struct wd_aead_msg *msg, __u8 *key_len) +{ + switch (msg->ckey_bytes) { + case AES_KEYSIZE_128: + *key_len = CKEY_LEN_128BIT; + break; + case AES_KEYSIZE_192: + *key_len = CKEY_LEN_192BIT; + break; + case AES_KEYSIZE_256: + *key_len = CKEY_LEN_256BIT; + break; + default: + WD_ERR("failed to check AES key size, size = %u\n", + msg->ckey_bytes); + return -WD_EINVAL; + } + + return 0; +} + +static int aead_akey_len_check(struct wd_aead_msg *msg) +{ + if (unlikely(msg->akey_bytes & WORD_ALIGNMENT_MASK)) { + WD_ERR("failed to check aead auth key bytes, size = %u\n", + msg->akey_bytes); + return -WD_EINVAL; + } + + return 0; +} + +static int fill_aead_bd2_alg(struct wd_aead_msg *msg, + struct hisi_sec_sqe *sqe) +{ + __u8 c_key_len = 0; + __u32 d_alg = 0; + int ret = 0; + + switch (msg->calg) { + case WD_CIPHER_AES: + sqe->type2.c_alg = C_ALG_AES; + ret = aead_get_aes_key_len(msg, &c_key_len); + sqe->type2.icvw_kmode = (__u16)c_key_len << SEC_CKEY_OFFSET; + break; + default: + WD_ERR("failed to check aead calg type, calg = %u\n", + msg->calg); + return -WD_EINVAL; + } + + /* CCM/GCM this region is set to 0 */ + if (msg->cmode == WD_CIPHER_CCM || msg->cmode == WD_CIPHER_GCM) + return ret; + + sqe->type2.mac_key_alg = msg->auth_bytes / WORD_BYTES; + + ret = aead_akey_len_check(msg); + if (ret) + return ret; + + sqe->type2.mac_key_alg |= (__u32)(msg->akey_bytes / + WORD_BYTES) << MAC_LEN_OFFSET; + + switch (msg->dalg) { + case WD_DIGEST_SHA1: + d_alg = A_ALG_HMAC_SHA1 << AUTH_ALG_OFFSET; + break; + case WD_DIGEST_SHA256: + d_alg = A_ALG_HMAC_SHA256 << AUTH_ALG_OFFSET; + break; + case WD_DIGEST_SHA512: + d_alg = A_ALG_HMAC_SHA512 << AUTH_ALG_OFFSET; + break; + default: + WD_ERR("failed to check aead dalg type, dalg = %u\n", + msg->dalg); + ret = -WD_EINVAL; + } + sqe->type2.mac_key_alg |= d_alg; + + return ret; +} + +static int fill_aead_bd2_mode(struct wd_aead_msg *msg, + struct hisi_sec_sqe *sqe) +{ + __u16 c_mode; + + switch (msg->cmode) { + case WD_CIPHER_CBC: + c_mode = C_MODE_CBC; + break; + case WD_CIPHER_CCM: + c_mode = C_MODE_CCM; + sqe->type_auth_cipher &= SEC_AUTH_MASK; + sqe->type2.alen_ivllen = msg->assoc_bytes; + sqe->type2.icvw_kmode |= msg->auth_bytes; + break; + case WD_CIPHER_GCM: + c_mode = C_MODE_GCM; + sqe->type_auth_cipher &= SEC_AUTH_MASK; + sqe->type2.alen_ivllen = msg->assoc_bytes; + sqe->type2.icvw_kmode |= msg->auth_bytes; + break; + default: + WD_ERR("failed to check aead cmode type, cmode = %u\n", + msg->cmode); + return -WD_EINVAL; + } + sqe->type2.icvw_kmode |= (__u16)(c_mode) << SEC_CMODE_OFFSET; + + return 0; +} + +static void set_aead_auth_iv(struct wd_aead_msg *msg) +{ +#define IV_LAST_BYTE1 1 +#define IV_LAST_BYTE2 2 +#define IV_CTR_INIT 1 +#define IV_CM_CAL_NUM 2 +#define IV_CL_MASK 0x7 +#define IV_FLAGS_OFFSET 0x6 +#define IV_CM_OFFSET 0x3 +#define IV_LAST_BYTE_MASK 0xFF +#define IV_BYTE_OFFSET 0x8 + + __u32 data_size = msg->in_bytes; + __u8 flags = 0x00; + __u8 cl, cm; + + /* CCM need to cal a_iv, GCM same as c_iv */ + memcpy(msg->aiv, msg->iv, msg->iv_bytes); + if (msg->cmode == WD_CIPHER_CCM) { + msg->iv[msg->iv_bytes - IV_LAST_BYTE2] = 0x00; + msg->iv[msg->iv_bytes - IV_LAST_BYTE1] = IV_CTR_INIT; + + /* the last 3bit is L' */ + cl = msg->iv[0] & IV_CL_MASK; + flags |= cl; + + /* the M' is bit3~bit5, the Flags is bit6 */ + cm = (msg->auth_bytes - IV_CM_CAL_NUM) / IV_CM_CAL_NUM; + flags |= cm << IV_CM_OFFSET; + if (msg->assoc_bytes > 0) + flags |= 0x01 << IV_FLAGS_OFFSET; + + msg->aiv[0] = flags; + /* + * the last 32bit is counter's initial number, + * but the nonce uses the first 16bit + * the tail 16bit fill with the cipher length + */ + msg->aiv[msg->iv_bytes - IV_LAST_BYTE1] = + data_size & IV_LAST_BYTE_MASK; + data_size >>= IV_BYTE_OFFSET; + msg->aiv[msg->iv_bytes - IV_LAST_BYTE2] = + data_size & IV_LAST_BYTE_MASK; + } +} + +static void fill_aead_bd2_addr(struct wd_aead_msg *msg, + struct hisi_sec_sqe *sqe) +{ + sqe->type2.data_src_addr = (__u64)(uintptr_t)msg->in; + sqe->type2.data_dst_addr = (__u64)(uintptr_t)msg->out; + sqe->type2.mac_addr = (__u64)(uintptr_t)msg->mac; + sqe->type2.c_key_addr = (__u64)(uintptr_t)msg->ckey; + sqe->type2.a_key_addr = (__u64)(uintptr_t)msg->akey; + sqe->type2.c_ivin_addr = (__u64)(uintptr_t)msg->iv; + + /* CCM/GCM should init a_iv */ + set_aead_auth_iv(msg); + + sqe->type2.a_ivin_addr = (__u64)(uintptr_t)msg->aiv; +} + +static int aead_len_check(struct wd_aead_msg *msg) +{ + if (unlikely(msg->in_bytes + msg->assoc_bytes > MAX_INPUT_DATA_LEN)) { + WD_ERR("aead input data length is too long, size = %u\n", + msg->in_bytes + msg->assoc_bytes); + return -WD_EINVAL; + } + + if (unlikely(msg->cmode == WD_CIPHER_CCM && + msg->assoc_bytes > MAX_CCM_AAD_LEN)) { + WD_ERR("aead ccm aad length is too long, size = %u\n", + msg->assoc_bytes); + return -WD_EINVAL; + } + + return 0; +} + +static int fill_aead_bd2(struct wd_aead_msg *msg, struct hisi_sec_sqe *sqe) +{ + __u8 scene, cipher, de; + int ret; + + /* config BD type */ + sqe->type_auth_cipher = BD_TYPE2; + /* config scene */ + scene = SEC_IPSEC_SCENE << SEC_SCENE_OFFSET; + de = DATA_DST_ADDR_ENABLE << SEC_DE_OFFSET; + + if (msg->op_type == WD_CIPHER_ENCRYPTION_DIGEST) { + cipher = SEC_CIPHER_ENC << SEC_CIPHER_OFFSET; + sqe->sds_sa_type = WD_CIPHER_THEN_DIGEST; + sqe->type_auth_cipher |= AUTH_HMAC_CALCULATE << + SEC_AUTH_OFFSET; + } else if (msg->op_type == WD_CIPHER_DECRYPTION_DIGEST) { + cipher = SEC_CIPHER_DEC << SEC_CIPHER_OFFSET; + sqe->sds_sa_type = WD_DIGEST_THEN_CIPHER; + sqe->type_auth_cipher |= AUTH_MAC_VERIFY << + SEC_AUTH_OFFSET; + } else { + WD_ERR("failed to check aead op type, op = %u\n", msg->op_type); + return -WD_EINVAL; + } + sqe->sds_sa_type |= (__u8)(de | scene); + sqe->type_auth_cipher |= cipher; + + sqe->type2.clen_ivhlen = msg->in_bytes; + sqe->type2.cipher_src_offset = msg->assoc_bytes; + sqe->type2.alen_ivllen = msg->in_bytes + msg->assoc_bytes; + + ret = fill_aead_bd2_alg(msg, sqe); + if (ret) { + WD_ERR("failed to fill aead bd alg!\n"); + return ret; + } + + ret = fill_aead_bd2_mode(msg, sqe); + if (ret) { + WD_ERR("failed to fill aead bd mode!\n"); + return ret; + } + + return 0; +} + +int hisi_sec_aead_send(handle_t ctx, void *aead_msg) +{ + handle_t h_qp = (handle_t)wd_ctx_get_priv(ctx); + struct wd_aead_msg *msg = aead_msg; + struct hisi_sec_sqe sqe; + __u16 count = 0; + int ret; + + if (unlikely(!msg)) { + WD_ERR("failed to check input aead msg!\n"); + return -WD_EINVAL; + } + + if (unlikely(msg->cmode != WD_CIPHER_CBC && !msg->in_bytes)) { + WD_ERR("ccm or gcm not supports 0 packet size at hw_v2!\n"); + return -WD_EINVAL; + } + + ret = aead_len_check(msg); + if (unlikely(ret)) + return ret; + + memset(&sqe, 0, sizeof(struct hisi_sec_sqe)); + ret = fill_aead_bd2(msg, &sqe); + if (unlikely(ret)) + return ret; + + if (msg->data_fmt == WD_SGL_BUF) { + ret = hisi_sec_fill_sgl(h_qp, &msg->in, &msg->out, + &sqe, msg->alg_type); + if (ret) + return ret; + } + + fill_aead_bd2_addr(msg, &sqe); + hisi_set_msg_id(h_qp, &msg->tag); + sqe.type2.tag = (__u16)msg->tag; + + ret = hisi_qm_send(h_qp, &sqe, 1, &count); + if (ret < 0) { + if (ret != -WD_EBUSY) + WD_ERR("aead send sqe is err(%d)!\n", ret); + + if (msg->data_fmt == WD_SGL_BUF) + hisi_sec_put_sgl(h_qp, msg->alg_type, msg->in, + msg->out); + + return ret; + } + + return 0; +} + +static void parse_aead_bd2(struct hisi_qp *qp, struct hisi_sec_sqe *sqe, + struct wd_aead_msg *recv_msg) +{ + struct wd_aead_msg *temp_msg; + __u16 done, icv; + + done = sqe->type2.done_flag & SEC_DONE_MASK; + icv = (sqe->type2.done_flag & SEC_ICV_MASK) >> 1; + if (done != SEC_HW_TASK_DONE || sqe->type2.error_type || + icv == SEC_HW_ICV_ERR) { + WD_ERR("failed to parse aead BD2! done=0x%x, etype=0x%x, icv=0x%x\n", + done, sqe->type2.error_type, icv); + recv_msg->result = WD_IN_EPARA; + } else { + recv_msg->result = WD_SUCCESS; + } + + recv_msg->tag = sqe->type2.tag; + + if (qp->q_info.qp_mode == CTX_MODE_ASYNC) { + recv_msg->alg_type = WD_AEAD; + recv_msg->data_fmt = get_data_fmt_v2(sqe->sds_sa_type); + recv_msg->in = (__u8 *)(uintptr_t)sqe->type2.data_src_addr; + recv_msg->out = (__u8 *)(uintptr_t)sqe->type2.data_dst_addr; + temp_msg = wd_aead_get_msg(qp->q_info.idx, recv_msg->tag); + if (!temp_msg) { + recv_msg->result = WD_IN_EPARA; + WD_ERR("failed to get send msg! idx = %u, tag = %u.\n", + qp->q_info.idx, recv_msg->tag); + return; + } + } else { + /* The synchronization mode uses the same message */ + temp_msg = recv_msg; + } + + if (unlikely(recv_msg->result != WD_SUCCESS)) + dump_sec_msg(temp_msg, "aead"); +} + +int hisi_sec_aead_recv(handle_t ctx, void *aead_msg) +{ + handle_t h_qp = (handle_t)wd_ctx_get_priv(ctx); + struct wd_aead_msg *recv_msg = aead_msg; + struct hisi_sec_sqe sqe; + __u16 count = 0; + int ret; + + ret = hisi_qm_recv(h_qp, &sqe, 1, &count); + if (ret < 0) + return ret; + + ret = hisi_check_bd_id(h_qp, (__u16)recv_msg->tag, sqe.type2.tag); + if (ret) + return ret; + + parse_aead_bd2((struct hisi_qp *)h_qp, &sqe, recv_msg); + + if (recv_msg->data_fmt == WD_SGL_BUF) + hisi_sec_put_sgl(h_qp, recv_msg->alg_type, recv_msg->in, + recv_msg->out); + + return 0; +} + +static struct wd_aead_driver hisi_aead_driver = { + .drv_name = "hisi_sec2", + .alg_name = "aead", + .drv_ctx_size = sizeof(struct hisi_sec_ctx), + .init = hisi_sec_init, + .exit = hisi_sec_exit, +}; + +WD_AEAD_SET_DRIVER(hisi_aead_driver); + +static int fill_aead_bd3_alg(struct wd_aead_msg *msg, + struct hisi_sec_sqe3 *sqe) +{ + __u8 c_key_len = 0; + __u32 d_alg = 0; + int ret = 0; + + switch (msg->calg) { + case WD_CIPHER_SM4: + sqe->c_mode_alg |= C_ALG_SM4 << SEC_CALG_OFFSET_V3; + sqe->c_icv_key |= CKEY_LEN_SM4 << SEC_CKEY_OFFSET_V3; + break; + case WD_CIPHER_AES: + sqe->c_mode_alg |= C_ALG_AES << SEC_CALG_OFFSET_V3; + ret = aead_get_aes_key_len(msg, &c_key_len); + sqe->c_icv_key |= (__u16)c_key_len << SEC_CKEY_OFFSET_V3; + break; + default: + WD_ERR("failed to check aead calg type, calg = %u\n", + msg->calg); + return -WD_EINVAL; + } + + /* CCM/GCM this region is set to 0 */ + if (msg->cmode == WD_CIPHER_CCM || msg->cmode == WD_CIPHER_GCM) + return ret; + + ret = aead_akey_len_check(msg); + if (ret) + return ret; + + sqe->auth_mac_key |= (msg->auth_bytes / + WORD_BYTES) << SEC_MAC_OFFSET_V3; + + sqe->auth_mac_key |= (msg->akey_bytes / + WORD_BYTES) << SEC_AKEY_OFFSET_V3; + + switch (msg->dalg) { + case WD_DIGEST_SHA1: + d_alg = A_ALG_HMAC_SHA1 << SEC_AUTH_ALG_OFFSET_V3; + break; + case WD_DIGEST_SHA256: + d_alg = A_ALG_HMAC_SHA256 << SEC_AUTH_ALG_OFFSET_V3; + break; + case WD_DIGEST_SHA512: + d_alg = A_ALG_HMAC_SHA512 << SEC_AUTH_ALG_OFFSET_V3; + break; + default: + WD_ERR("failed to check aead dalg type, dalg = %u\n", + msg->dalg); + ret = -WD_EINVAL; + } + sqe->auth_mac_key |= d_alg; + + return ret; +} + +static int fill_aead_bd3_mode(struct wd_aead_msg *msg, + struct hisi_sec_sqe3 *sqe) +{ + switch (msg->cmode) { + case WD_CIPHER_CBC: + sqe->c_mode_alg |= C_MODE_CBC; + break; + case WD_CIPHER_CCM: + sqe->c_mode_alg |= C_MODE_CCM; + sqe->auth_mac_key &= SEC_AUTH_MASK_V3; + sqe->a_len_key = msg->assoc_bytes; + sqe->c_icv_key |= msg->auth_bytes << SEC_MAC_OFFSET_V3; + break; + case WD_CIPHER_GCM: + sqe->c_mode_alg |= C_MODE_GCM; + sqe->auth_mac_key &= SEC_AUTH_MASK_V3; + sqe->a_len_key = msg->assoc_bytes; + sqe->c_icv_key |= msg->auth_bytes << SEC_MAC_OFFSET_V3; + break; + default: + WD_ERR("failed to check aead cmode type, cmode = %u\n", + msg->cmode); + return -WD_EINVAL; + } + + return 0; +} + +static void fill_aead_bd3_addr(struct wd_aead_msg *msg, + struct hisi_sec_sqe3 *sqe) +{ + sqe->data_src_addr = (__u64)(uintptr_t)msg->in; + sqe->data_dst_addr = (__u64)(uintptr_t)msg->out; + + sqe->mac_addr = (__u64)(uintptr_t)msg->mac; + sqe->c_key_addr = (__u64)(uintptr_t)msg->ckey; + sqe->a_key_addr = (__u64)(uintptr_t)msg->akey; + sqe->no_scene.c_ivin_addr = (__u64)(uintptr_t)msg->iv; + + /* CCM/GCM should init a_iv */ + set_aead_auth_iv(msg); + + sqe->auth_ivin.a_ivin_addr = (__u64)(uintptr_t)msg->aiv; +} + + +static int fill_aead_bd3(struct wd_aead_msg *msg, struct hisi_sec_sqe3 *sqe) +{ + __u16 scene, de; + int ret; + + /* config BD type */ + sqe->bd_param = BD_TYPE3; + /* config scene */ + scene = SEC_IPSEC_SCENE << SEC_SCENE_OFFSET_V3; + de = DATA_DST_ADDR_ENABLE << SEC_DE_OFFSET_V3; + + if (msg->op_type == WD_CIPHER_ENCRYPTION_DIGEST) { + sqe->c_icv_key = SEC_CIPHER_ENC; + sqe->auth_mac_key = AUTH_HMAC_CALCULATE; + sqe->huk_iv_seq = WD_CIPHER_THEN_DIGEST << SEC_SEQ_OFFSET_V3; + } else if (msg->op_type == WD_CIPHER_DECRYPTION_DIGEST) { + sqe->c_icv_key = SEC_CIPHER_DEC; + sqe->auth_mac_key = AUTH_MAC_VERIFY; + sqe->huk_iv_seq = WD_DIGEST_THEN_CIPHER << SEC_SEQ_OFFSET_V3; + } else { + WD_ERR("failed to check aead op type, op = %u\n", msg->op_type); + return -WD_EINVAL; + } + sqe->bd_param |= (__u16)(de | scene); + + sqe->c_len_ivin = msg->in_bytes; + sqe->cipher_src_offset = msg->assoc_bytes; + sqe->a_len_key = msg->in_bytes + msg->assoc_bytes; + + ret = fill_aead_bd3_alg(msg, sqe); + if (ret) { + WD_ERR("failed to fill aead bd alg!\n"); + return ret; + } + + ret = fill_aead_bd3_mode(msg, sqe); + if (ret) { + WD_ERR("failed to fill aead bd mode!\n"); + return ret; + } + + return 0; +} + +int hisi_sec_aead_send_v3(handle_t ctx, void *aead_msg) +{ + handle_t h_qp = (handle_t)wd_ctx_get_priv(ctx); + struct wd_aead_msg *msg = aead_msg; + struct hisi_sec_sqe3 sqe; + __u16 count = 0; + int ret; + + if (!msg) { + WD_ERR("failed to check input aead msg!\n"); + return -WD_EINVAL; + } + + ret = aead_len_check(msg); + if (unlikely(ret)) + return ret; + + memset(&sqe, 0, sizeof(struct hisi_sec_sqe3)); + ret = fill_aead_bd3(msg, &sqe); + if (unlikely(ret)) + return ret; + + if (msg->data_fmt == WD_SGL_BUF) { + ret = hisi_sec_fill_sgl_v3(h_qp, &msg->in, &msg->out, &sqe, + msg->alg_type); + if (ret) + return ret; + } + + fill_aead_bd3_addr(msg, &sqe); + hisi_set_msg_id(h_qp, &msg->tag); + sqe.tag = msg->tag; + ret = hisi_qm_send(h_qp, &sqe, 1, &count); + if (ret < 0) { + if (ret != -WD_EBUSY) + WD_ERR("aead send sqe is err(%d)!\n", ret); + + if (msg->data_fmt == WD_SGL_BUF) + hisi_sec_put_sgl(h_qp, msg->alg_type, msg->in, + msg->out); + + return ret; + } + + return 0; +} + +static void parse_aead_bd3(struct hisi_qp *qp, struct hisi_sec_sqe3 *sqe, + struct wd_aead_msg *recv_msg) +{ + struct wd_aead_msg *temp_msg; + __u16 done, icv; + + done = sqe->done_flag & SEC_DONE_MASK; + icv = (sqe->done_flag & SEC_ICV_MASK) >> 1; + if (done != SEC_HW_TASK_DONE || sqe->error_type || + icv == SEC_HW_ICV_ERR) { + WD_ERR("failed to parse aead BD3! done=0x%x, etype=0x%x, icv=0x%x\n", + done, sqe->error_type, icv); + recv_msg->result = WD_IN_EPARA; + } else { + recv_msg->result = WD_SUCCESS; + } + + recv_msg->tag = sqe->tag; + + if (qp->q_info.qp_mode == CTX_MODE_ASYNC) { + recv_msg->alg_type = WD_AEAD; + recv_msg->data_fmt = get_data_fmt_v3(sqe->bd_param); + recv_msg->in = (__u8 *)(uintptr_t)sqe->data_src_addr; + recv_msg->out = (__u8 *)(uintptr_t)sqe->data_dst_addr; + temp_msg = wd_aead_get_msg(qp->q_info.idx, recv_msg->tag); + if (!temp_msg) { + recv_msg->result = WD_IN_EPARA; + WD_ERR("failed to get send msg! idx = %u, tag = %u.\n", + qp->q_info.idx, recv_msg->tag); + return; + } + } else { + /* The synchronization mode uses the same message */ + temp_msg = recv_msg; + } + + if (unlikely(recv_msg->result != WD_SUCCESS)) + dump_sec_msg(temp_msg, "aead"); +} + +int hisi_sec_aead_recv_v3(handle_t ctx, void *aead_msg) +{ + handle_t h_qp = (handle_t)wd_ctx_get_priv(ctx); + struct wd_aead_msg *recv_msg = aead_msg; + struct hisi_sec_sqe3 sqe; + __u16 count = 0; + int ret; + + ret = hisi_qm_recv(h_qp, &sqe, 1, &count); + if (ret < 0) + return ret; + + ret = hisi_check_bd_id(h_qp, recv_msg->tag, sqe.tag); + if (ret) + return ret; + + parse_aead_bd3((struct hisi_qp *)h_qp, &sqe, recv_msg); + + if (recv_msg->data_fmt == WD_SGL_BUF) + hisi_sec_put_sgl(h_qp, recv_msg->alg_type, + recv_msg->in, recv_msg->out); + + return 0; +} + +static void hisi_sec_driver_adapter(struct hisi_qp *qp) +{ + struct hisi_qm_queue_info q_info = qp->q_info; + + if (q_info.hw_type == HISI_QM_API_VER2_BASE) { + WD_ERR("hisi sec init Kunpeng920!\n"); + hisi_cipher_driver.cipher_send = hisi_sec_cipher_send; + hisi_cipher_driver.cipher_recv = hisi_sec_cipher_recv; + + hisi_digest_driver.digest_send = hisi_sec_digest_send; + hisi_digest_driver.digest_recv = hisi_sec_digest_recv; + + hisi_aead_driver.aead_send = hisi_sec_aead_send; + hisi_aead_driver.aead_recv = hisi_sec_aead_recv; + } else { + WD_ERR("hisi sec init Kunpeng930!\n"); + hisi_cipher_driver.cipher_send = hisi_sec_cipher_send_v3; + hisi_cipher_driver.cipher_recv = hisi_sec_cipher_recv_v3; + + hisi_digest_driver.digest_send = hisi_sec_digest_send_v3; + hisi_digest_driver.digest_recv = hisi_sec_digest_recv_v3; + + hisi_aead_driver.aead_send = hisi_sec_aead_send_v3; + hisi_aead_driver.aead_recv = hisi_sec_aead_recv_v3; + } +} + +int hisi_sec_init(struct wd_ctx_config_internal *config, void *priv) +{ + struct hisi_sec_ctx *sec_ctx = priv; + struct hisi_qm_priv qm_priv; + handle_t h_qp = 0; + handle_t h_ctx; + int i, j; + + if (!config->ctx_num) { + WD_ERR("invalid: sec init config ctx num is 0!\n"); + return -WD_EINVAL; + } + + qm_priv.sqe_size = sizeof(struct hisi_sec_sqe); + /* allocate qp for each context */ + for (i = 0; i < config->ctx_num; i++) { + h_ctx = config->ctxs[i].ctx; + /* setting the type is 0 for sqc_type */ + qm_priv.op_type = 0; + qm_priv.qp_mode = config->ctxs[i].ctx_mode; + /* Setting the epoll en to 0 for ASYNC ctx */ + qm_priv.epoll_en = (qm_priv.qp_mode == CTX_MODE_SYNC) ? + config->epoll_en : 0; + qm_priv.idx = i; + h_qp = hisi_qm_alloc_qp(&qm_priv, h_ctx); + if (!h_qp) + goto out; + } + memcpy(&sec_ctx->config, config, sizeof(struct wd_ctx_config_internal)); + hisi_sec_driver_adapter((struct hisi_qp *)h_qp); + + return 0; + +out: + for (j = i - 1; j >= 0; j--) { + h_qp = (handle_t)wd_ctx_get_priv(config->ctxs[j].ctx); + hisi_qm_free_qp(h_qp); + } + return -WD_EINVAL; +} + +void hisi_sec_exit(void *priv) +{ + struct hisi_sec_ctx *sec_ctx = priv; + struct wd_ctx_config_internal *config; + handle_t h_qp; + int i; + + if (!sec_ctx) { + WD_ERR("hisi sec exit input parameter is err!\n"); + return; + } + + config = &sec_ctx->config; + for (i = 0; i < config->ctx_num; i++) { + h_qp = (handle_t)wd_ctx_get_priv(config->ctxs[i].ctx); + hisi_qm_free_qp(h_qp); + } +} diff --git a/uadk/include/drv/wd_aead_drv.h b/uadk/include/drv/wd_aead_drv.h new file mode 100644 index 0000000..de4a7d7 --- /dev/null +++ b/uadk/include/drv/wd_aead_drv.h @@ -0,0 +1,99 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. */ + +#ifndef __WD_AEAD_DRV_H +#define __WD_AEAD_DRV_H + +#include "../wd_common.h" +#include "../wd_alg_common.h" +#include "../wd_aead.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct wd_aead_msg { + struct wd_aead_req req; + /* Request identifier */ + __u32 tag; + /* Denoted by enum wcrypto_type */ + __u8 alg_type; + /* Denoted by enum wcrypto_cipher_type */ + __u8 calg; + /* Denoted by enum wcrypto_cipher_mode_type */ + __u8 cmode; + /* Denoted by enum wcrypto_digest_type */ + __u8 dalg; + /* Denoted by enum wcrypto_digest_mode_type */ + __u8 dmode; + /* Denoted by enum wcrypto_aead_op_type */ + __u8 op_type; + /* Data format, include pbuffer and sgl */ + __u8 data_fmt; + /* Operation result, denoted by WD error code */ + __u8 result; + + /* in bytes */ + __u32 in_bytes; + /* out_bytes */ + __u32 out_bytes; + /* iv bytes */ + __u16 iv_bytes; + /* cipher key bytes */ + __u16 ckey_bytes; + /* authentication key bytes */ + __u16 akey_bytes; + /* Input associated data bytes */ + __u16 assoc_bytes; + /* Outpue authentication bytes */ + __u16 auth_bytes; + + /* input cipher key pointer */ + __u8 *ckey; + /* input authentication key pointer */ + __u8 *akey; + /* input iv pointer */ + __u8 *iv; + /* input auth iv pointer */ + __u8 aiv[MAX_IV_SIZE]; + /* input data pointer */ + __u8 *in; + /* output data pointer */ + __u8 *out; + /* mac */ + __u8 *mac; +}; + +struct wd_aead_driver { + const char *drv_name; + const char *alg_name; + __u32 drv_ctx_size; + int (*init)(struct wd_ctx_config_internal *config, void *priv); + void (*exit)(void *priv); + int (*aead_send)(handle_t ctx, void *aead_msg); + int (*aead_recv)(handle_t ctx, void *aead_msg); +}; + +void wd_aead_set_driver(struct wd_aead_driver *drv); +struct wd_aead_driver *wd_aead_get_driver(void); +struct wd_aead_msg *wd_aead_get_msg(__u32 idx, __u32 tag); + +#ifdef WD_STATIC_DRV +#define WD_AEAD_SET_DRIVER(drv) \ +struct wd_aead_driver *wd_aead_get_driver(void) \ +{ \ + return &drv; \ +} +#else +#define WD_AEAD_SET_DRIVER(drv) \ +static void __attribute__((constructor)) set_aead_driver(void) \ +{ \ + wd_aead_set_driver(&(drv)); \ +} +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __WD_AEAD_DRV_H */ diff --git a/uadk/include/drv/wd_cipher_drv.h b/uadk/include/drv/wd_cipher_drv.h new file mode 100644 index 0000000..f2417a8 --- /dev/null +++ b/uadk/include/drv/wd_cipher_drv.h @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. */ + +#ifndef __WD_CIPHER_DRV_H +#define __WD_CIPHER_DRV_H + +#include +#include "../wd_common.h" +#include "../wd_alg_common.h" +#include "../wd_cipher.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* fixme wd_cipher_msg */ +struct wd_cipher_msg { + struct wd_cipher_req req; + /* request identifier */ + __u32 tag; + /* Denoted by enum wcrypto_type */ + __u8 alg_type; + /* Denoted by enum wcrypto_cipher_type */ + __u8 alg; + /* Denoted by enum wcrypto_cipher_op_type */ + __u8 op_type; + /* Denoted by enum wcrypto_cipher_mode_type */ + __u8 mode; + /* Data format, include pbuffer and sgl */ + __u8 data_fmt; + /* Operation result, denoted by WD error code */ + __u8 result; + + /* Key bytes */ + __u16 key_bytes; + /* iv bytes */ + __u16 iv_bytes; + /* in bytes */ + __u32 in_bytes; + /* out_bytes */ + __u32 out_bytes; + + /* input key pointer */ + __u8 *key; + /* input iv pointer */ + __u8 *iv; + /* input data pointer */ + __u8 *in; + /* output data pointer */ + __u8 *out; +}; + +struct wd_cipher_driver { + const char *drv_name; + const char *alg_name; + __u32 drv_ctx_size; + int (*init)(struct wd_ctx_config_internal *config, void *priv); + void (*exit)(void *priv); + int (*cipher_send)(handle_t ctx, void *cipher_msg); + int (*cipher_recv)(handle_t ctx, void *cipher_msg); +}; + +void wd_cipher_set_driver(struct wd_cipher_driver *drv); +struct wd_cipher_driver *wd_cipher_get_driver(void); +struct wd_cipher_msg *wd_cipher_get_msg(__u32 idx, __u32 tag); + +#ifdef WD_STATIC_DRV +#define WD_CIPHER_SET_DRIVER(drv) \ +struct wd_cipher_driver *wd_cipher_get_driver(void) \ +{ \ + return &drv; \ +} +#else +#define WD_CIPHER_SET_DRIVER(drv) \ +static void __attribute__((constructor)) set_cipher_driver(void) \ +{ \ + wd_cipher_set_driver(&(drv)); \ +} +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __WD_CIPHER_DRV_H */ diff --git a/uadk/include/drv/wd_comp_drv.h b/uadk/include/drv/wd_comp_drv.h new file mode 100644 index 0000000..4c37116 --- /dev/null +++ b/uadk/include/drv/wd_comp_drv.h @@ -0,0 +1,91 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. */ + +#ifndef __WD_COMP_DRV_H +#define __WD_COMP_DRV_H + +#include +#include +#include "../wd_common.h" +#include "../wd_alg_common.h" +#include "../wd_comp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum wd_comp_strm_pos { + WD_COMP_STREAM_NEW, + WD_COMP_STREAM_OLD, +}; + +enum wd_comp_state { + WD_COMP_STATEFUL, + WD_COMP_STATELESS, +}; + +/* fixme wd_comp_msg */ +struct wd_comp_msg { + struct wd_comp_req req; + /* Denoted HW ctx cache, for stream mode */ + void *ctx_buf; + /* Denoted by enum wd_comp_alg_type */ + enum wd_comp_alg_type alg_type; + /* Denoted by enum wd_comp_level */ + enum wd_comp_level comp_lv; + /* Denoted by enum wd_comp_winsz_type */ + enum wd_comp_winsz_type win_sz; + /* Denoted by enum wd_comp_state */ + enum wd_comp_state stream_mode; + /* Denoted by enum wd_comp_strm_pos */ + enum wd_comp_strm_pos stream_pos; + /* Denoted by enum wd_buff_type */ + enum wd_buff_type data_fmt; + /* Output buffer size */ + __u32 avail_out; + /* Consumed bytes of input data */ + __u32 in_cons; + /* Produced bytes of current operation */ + __u32 produced; + /* Denoted by gzip isize */ + __u32 isize; + /* Denoted by zlib/gzip CRC */ + __u32 checksum; + /* Request identifier */ + __u32 tag; +}; + +struct wd_comp_driver { + const char *drv_name; + const char *alg_name; + __u32 drv_ctx_size; + int (*init)(struct wd_ctx_config_internal *config, void *priv); + void (*exit)(void *priv); + int (*comp_send)(handle_t ctx, void *comp_msg); + int (*comp_recv)(handle_t ctx, void *comp_msg); +}; + +void wd_comp_set_driver(struct wd_comp_driver *drv); +struct wd_comp_driver *wd_comp_get_driver(void); + +struct wd_comp_msg *wd_comp_get_msg(__u32 idx, __u32 tag); + +#ifdef WD_STATIC_DRV +#define WD_COMP_SET_DRIVER(drv) \ +struct wd_comp_driver *wd_comp_get_driver(void) \ +{ \ + return &drv; \ +} +#else +#define WD_COMP_SET_DRIVER(drv) \ +static void __attribute__((constructor)) set_comp_driver(void) \ +{ \ + wd_comp_set_driver(&(drv)); \ +} +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __WD_COMP_DRV_H */ diff --git a/uadk/include/drv/wd_dh_drv.h b/uadk/include/drv/wd_dh_drv.h new file mode 100644 index 0000000..57f774d --- /dev/null +++ b/uadk/include/drv/wd_dh_drv.h @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. */ + +#ifndef __WD_DH_DRV_H +#define __WD_DH_DRV_H + +#include +#include "../wd_alg_common.h" +#include "../wd_dh.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* DH message format */ +struct wd_dh_msg { + struct wd_dh_req req; + __u32 tag; /* User-defined request identifier */ + void *g; + __u16 gbytes; + __u16 key_bytes; /* Input key bytes */ + __u8 is_g2; + __u8 result; /* Data format, denoted by WD error code */ +}; + +struct wd_dh_driver { + const char *drv_name; + const char *alg_name; + __u32 drv_ctx_size; + int (*init)(struct wd_ctx_config_internal *config, void *priv, + const char *alg_name); + void (*exit)(void *priv); + int (*send)(handle_t sess, void *dh_msg); + int (*recv)(handle_t sess, void *dh_msg); +}; + +void wd_dh_set_driver(struct wd_dh_driver *drv); +struct wd_dh_driver *wd_dh_get_driver(void); +struct wd_dh_msg *wd_dh_get_msg(__u32 idx, __u32 tag); + +#ifdef WD_STATIC_DRV +#define WD_DH_SET_DRIVER(drv) \ +struct wd_dh_driver *wd_dh_get_driver(void) \ +{ \ + return &drv; \ +} +#else +#define WD_DH_SET_DRIVER(drv) \ +static void __attribute__((constructor)) set_driver_dh(void) \ +{ \ + wd_dh_set_driver(&(drv)); \ +} +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __WD_DH_DRV_H */ diff --git a/uadk/include/drv/wd_digest_drv.h b/uadk/include/drv/wd_digest_drv.h new file mode 100644 index 0000000..7ba1c30 --- /dev/null +++ b/uadk/include/drv/wd_digest_drv.h @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. */ +#ifndef __WD_DIGEST_DRV_H +#define __WD_DIGEST_DRV_H + +#include "../wd_common.h" +#include "../wd_alg_common.h" +#include "../wd_digest.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* fixme wd_digest_msg */ +struct wd_digest_msg { + struct wd_digest_req req; + /* request identifier */ + __u32 tag; + /* Denoted by enum wcrypto_type */ + __u8 alg_type; + /* Denoted by enum wcrypto_digest_type */ + __u8 alg; + /* is there next block data */ + __u8 has_next; + /* Denoted by enum wcrypto_digest_mode_type */ + __u8 mode; + /* Data format, include pbuffer and sgl */ + __u8 data_fmt; + /* Operation result, denoted by WD error code */ + __u8 result; + /* user identifier: struct wcrypto_cb_tag */ + __u64 usr_data; + + /* Key bytes */ + __u16 key_bytes; + /* iv bytes */ + __u16 iv_bytes; + /* in bytes */ + __u32 in_bytes; + /* out_bytes */ + __u32 out_bytes; + + /* input key pointer */ + __u8 *key; + /* input iv pointer */ + __u8 *iv; + /* input data pointer */ + __u8 *in; + /* output data pointer */ + __u8 *out; + /* total of data for stream mode */ + __u64 long_data_len; +}; + +struct wd_digest_driver { + const char *drv_name; + const char *alg_name; + __u32 drv_ctx_size; + int (*init)(struct wd_ctx_config_internal *config, void *priv); + void (*exit)(void *priv); + int (*digest_send)(handle_t ctx, void *digest_msg); + int (*digest_recv)(handle_t ctx, void *digest_msg); +}; + +void wd_digest_set_driver(struct wd_digest_driver *drv); +struct wd_digest_driver *wd_digest_get_driver(void); +struct wd_digest_msg *wd_digest_get_msg(__u32 idx, __u32 tag); + +#ifdef WD_STATIC_DRV +#define WD_DIGEST_SET_DRIVER(drv) \ +struct wd_digest_driver *wd_digest_get_driver(void) \ +{ \ + return &drv; \ +} +#else +#define WD_DIGEST_SET_DRIVER(drv) \ +static void __attribute__((constructor)) set_digest_drivers(void) \ +{ \ + wd_digest_set_driver(&(drv)); \ +} +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __WD_DIGEST_DRV_H */ diff --git a/uadk/include/drv/wd_ecc_drv.h b/uadk/include/drv/wd_ecc_drv.h new file mode 100644 index 0000000..ddf5e5b --- /dev/null +++ b/uadk/include/drv/wd_ecc_drv.h @@ -0,0 +1,211 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. */ + +#ifndef __WD_ECC_DRV_H +#define __WD_ECC_DRV_H + +#include +#include + +#include "../wd.h" +#include "../wd_ecc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* ECC */ +#define ECDH_IN_PARAM_NUM 2 +#define ECDH_OUT_PARAM_NUM 2 +#define ECC_SIGN_IN_PARAM_NUM 2 +#define ECC_SIGN_OUT_PARAM_NUM 2 +#define ECC_VERF_IN_PARAM_NUM 3 +#define ECC_PRIKEY_PARAM_NUM 7 +#define ECDH_HW_KEY_PARAM_NUM 5 +#define ECC_PUBKEY_PARAM_NUM 8 +#define SM2_KG_OUT_PARAM_NUM 3 +#define ECC_POINT_PARAM_NUM 2 +#define ECDH_HW_KEY_SZ(hsz) ((hsz) * ECDH_HW_KEY_PARAM_NUM) +#define ECC_PRIKEY_SZ(hsz) ((hsz) * ECC_PRIKEY_PARAM_NUM) +#define ECC_PUBKEY_SZ(hsz) ((hsz) * ECC_PUBKEY_PARAM_NUM) +#define ECDH_OUT_PARAMS_SZ(hsz) ((hsz) * ECDH_OUT_PARAM_NUM) + +/* x25519/x448 */ +#define X_DH_OUT_PARAM_NUM 1 +#define X_DH_HW_KEY_PARAM_NUM 3 + +#define X_DH_OUT_PARAMS_SZ(hsz) ((hsz) * X_DH_OUT_PARAM_NUM) +#define X_DH_HW_KEY_SZ(hsz) ((hsz) * X_DH_HW_KEY_PARAM_NUM) +#define ECC_SIGN_IN_PARAMS_SZ(hsz) ((hsz) * ECC_SIGN_IN_PARAM_NUM) +#define ECC_SIGN_OUT_PARAMS_SZ(hsz) ((hsz) * ECC_SIGN_OUT_PARAM_NUM) +#define ECC_VERF_IN_PARAMS_SZ(hsz) ((hsz) * ECC_VERF_IN_PARAM_NUM) +#define ECC_VERF_OUT_PARAMS_SZ 1 + +#define WD_X25519 0x1 +#define WD_X448 0x2 +#define WD_SM2P256 0x3 + +/* ECC message format */ +struct wd_ecc_msg { + struct wd_ecc_req req; + struct wd_hash_mt hash; + __u32 tag; /* User-defined request identifier */ + __u8 *key; /* Input key VA, should be DMA buffer */ + __u16 key_bytes; /* key bytes */ + __u8 curve_id; /* Ec curve denoted by enum wd_ecc_curve_type */ + __u8 result; /* alg op error code */ +}; + +struct wd_ecc_pubkey { + struct wd_dtb p; + struct wd_dtb a; + struct wd_dtb b; + struct wd_dtb n; + struct wd_ecc_point g; + struct wd_ecc_point pub; + __u32 size; + void *data; +}; + +struct wd_ecc_prikey { + struct wd_dtb p; + struct wd_dtb a; + struct wd_dtb d; + struct wd_dtb b; + struct wd_dtb n; + struct wd_ecc_point g; + __u32 size; + void *data; +}; + +struct wd_ecc_key { + struct wd_ecc_pubkey *pubkey; + struct wd_ecc_prikey *prikey; + struct wd_ecc_curve *cv; + struct wd_ecc_point *pub; + struct wd_dtb *d; +}; + +struct wd_ecc_dh_in { + struct wd_ecc_point pbk; +}; + +struct wd_ecc_sign_in { + struct wd_dtb dgst; /* hash msg */ + struct wd_dtb k; /* random */ + struct wd_dtb plaintext; /* original text before hash */ + __u8 k_set; /* 1 - k parameter set 0 - not set */ + __u8 dgst_set; /* 1 - dgst parameter set 0 - not set */ +}; + +struct wd_ecc_verf_in { + struct wd_dtb dgst; /* hash msg */ + struct wd_dtb s; /* signature s parameter */ + struct wd_dtb r; /* signature r parameter */ + struct wd_dtb plaintext; /* original text before hash */ + __u8 dgst_set; /* 1 - dgst parameter set 0 - not set */ +}; + +struct wd_ecc_dh_out { + struct wd_ecc_point out; +}; + +struct wd_ecc_sign_out { + struct wd_dtb r; /* signature r parameter */ + struct wd_dtb s; /* signature s parameter */ +}; + +struct wd_sm2_enc_in { + struct wd_dtb k; /* random */ + struct wd_dtb plaintext; /* original text */ + __u8 k_set; /* 0 - not set 1 - set */ +}; + +struct wd_sm2_enc_out { + struct wd_ecc_point c1; + struct wd_dtb c2; + struct wd_dtb c3; +}; + +struct wd_sm2_dec_in { + struct wd_ecc_point c1; + struct wd_dtb c2; + struct wd_dtb c3; +}; + +struct wd_sm2_kg_in { + struct wd_ecc_point g; +}; + +struct wd_sm2_dec_out { + struct wd_dtb plaintext; +}; + +struct wd_sm2_kg_out { + struct wd_ecc_point pub; + struct wd_dtb priv; +}; + +typedef union { + struct wd_ecc_dh_in dh_in; + struct wd_ecc_sign_in sin; + struct wd_ecc_verf_in vin; + struct wd_sm2_enc_in ein; + struct wd_sm2_dec_in din; + struct wd_sm2_kg_in kin; +} wd_ecc_in_param; + +typedef union { + struct wd_ecc_dh_out dh_out; + struct wd_ecc_sign_out sout; + struct wd_sm2_enc_out eout; + struct wd_sm2_dec_out dout; + struct wd_sm2_kg_out kout; +} wd_ecc_out_param; + +struct wd_ecc_in { + wd_ecc_in_param param; + __u64 size; + char data[]; +}; + +struct wd_ecc_out { + wd_ecc_out_param param; + __u64 size; + char data[]; +}; + +struct wd_ecc_driver { + const char *drv_name; + const char *alg_name; + __u32 drv_ctx_size; + int (*init)(struct wd_ctx_config_internal *config, void *priv, + const char *alg_name); + void (*exit)(void *priv); + int (*send)(handle_t sess, void *ecc_msg); + int (*recv)(handle_t sess, void *ecc_msg); +}; + +void wd_ecc_set_driver(struct wd_ecc_driver *drv); +struct wd_ecc_driver *wd_ecc_get_driver(void); +struct wd_ecc_msg *wd_ecc_get_msg(__u32 idx, __u32 tag); + +#ifdef WD_STATIC_DRV +#define WD_ECC_SET_DRIVER(drv) \ +struct wd_ecc_driver *wd_ecc_get_driver(void) \ +{ \ + return &drv; \ +} +#else +#define WD_ECC_SET_DRIVER(drv) \ +static void __attribute__((constructor)) set_driver_ecc(void) \ +{ \ + wd_ecc_set_driver(&(drv)); \ +} +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __WD_ECC_DRV_H */ diff --git a/uadk/include/drv/wd_rsa_drv.h b/uadk/include/drv/wd_rsa_drv.h new file mode 100644 index 0000000..108c2a3 --- /dev/null +++ b/uadk/include/drv/wd_rsa_drv.h @@ -0,0 +1,84 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. */ +#ifndef __WD_RSA_DRV_H +#define __WD_RSA_DRV_H + +#include + +#include "../wd_rsa.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct wd_rsa_kg_in { + __u8 *e; + __u8 *p; + __u8 *q; + __u32 ebytes; + __u32 pbytes; + __u32 qbytes; + __u32 key_size; + void *data[]; +}; + +struct wd_rsa_kg_out { + __u8 *d; + __u8 *n; + __u8 *qinv; + __u8 *dq; + __u8 *dp; + __u32 key_size; + __u32 dbytes; + __u32 nbytes; + __u32 dpbytes; + __u32 dqbytes; + __u32 qinvbytes; + __u32 size; + void *data[]; +}; + +/* RSA message format */ +struct wd_rsa_msg { + struct wd_rsa_req req; + __u32 tag; /* User-defined request identifier */ + __u16 key_bytes; /* Input key bytes */ + __u8 key_type; /* Denoted by enum wd_rsa_key_type */ + __u8 result; /* Data format, denoted by WD error code */ + __u8 *key; /* Input key VA pointer, should be DMA buffer */ +}; + +struct wd_rsa_driver { + const char *drv_name; + const char *alg_name; + __u32 drv_ctx_size; + int (*init)(struct wd_ctx_config_internal *config, void *priv, + const char *alg_name); + void (*exit)(void *priv); + int (*send)(handle_t sess, void *rsa_msg); + int (*recv)(handle_t sess, void *rsa_msg); +}; + +void wd_rsa_set_driver(struct wd_rsa_driver *drv); +struct wd_rsa_driver *wd_rsa_get_driver(void); +struct wd_rsa_msg *wd_rsa_get_msg(__u32 idx, __u32 tag); + +#ifdef WD_STATIC_DRV +#define WD_RSA_SET_DRIVER(drv) \ +struct wd_rsa_driver *wd_rsa_get_driver(void) \ +{ \ + return &drv; \ +} +#else +#define WD_RSA_SET_DRIVER(drv) \ +static void __attribute__((constructor)) set_driver_rsa(void) \ +{ \ + wd_rsa_set_driver(&(drv)); \ +} +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __WD_RSA_DRV_H */ diff --git a/uadk/include/hisi_qm_udrv.h b/uadk/include/hisi_qm_udrv.h new file mode 100644 index 0000000..dda320d --- /dev/null +++ b/uadk/include/hisi_qm_udrv.h @@ -0,0 +1,213 @@ +// SPDX-License-Identifier: Apache-2.0 +/* Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. */ + +#ifndef __HZIP_DRV_H__ +#define __HZIP_DRV_H__ + +#include +#include +#include +#include + +#include "config.h" +#include "wd.h" +#include "wd_alg_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define WD_CAPA_PRIV_DATA_SIZE 64 + +#define QM_L32BITS_MASK 0xffffffff +#define QM_L16BITS_MASK 0xffff +#define QM_HADDR_SHIFT 32 +#define LW_U32(pa) ((__u32)((pa) & QM_L32BITS_MASK)) +#define HI_U32(pa) ((__u32)(((pa) >> QM_HADDR_SHIFT) & QM_L32BITS_MASK)) +#define VA_ADDR(hi, lo) ((void *)(((uintptr_t)(hi) << 32) | (uintptr_t)(lo))) +#define LW_U16(val) ((__u16)((val) & QM_L16BITS_MASK)) + +#define BYTE_BITS 8 +#define BYTE_BITS_SHIFT 3 + +#define container_of(ptr, type, member) ({ \ + typeof(((type *)0)->member)(*__mptr) = (ptr); \ + (type *)((char *)__mptr - offsetof(type, member)); }) + +enum hisi_qm_sgl_copy_dir { + COPY_SGL_TO_PBUFF, + COPY_PBUFF_TO_SGL +}; + +enum hisi_hw_type { + HISI_QM_API_VER_BASE = 1, + HISI_QM_API_VER2_BASE, + HISI_QM_API_VER3_BASE +}; + +struct hisi_qm_priv { + /* flag for SYNC or ASYNC */ + __u8 qp_mode; + __u16 sqe_size; + __u16 op_type; + /* index of ctxs */ + __u32 idx; + bool epoll_en; +}; + +struct hisi_qm_queue_info { + void *sq_base; + void *cq_base; + int sqe_size; + void *mmio_base; + void *db_base; + int (*db)(struct hisi_qm_queue_info *q, __u8 cmd, + __u16 index, __u8 priority); + void *ds_tx_base; + void *ds_rx_base; + __u8 qp_mode; + __u16 sq_tail_index; + __u16 cq_head_index; + __u16 sq_depth; + __u16 cq_depth; + __u16 sqn; + __u16 qc_type; + __u16 used_num; + __u16 hw_type; + __u32 idx; + bool cqc_phase; + pthread_spinlock_t sd_lock; + pthread_spinlock_t rv_lock; + unsigned long region_size[UACCE_QFRT_MAX]; + bool epoll_en; +}; + +struct hisi_qp { + struct hisi_qm_queue_info q_info; + handle_t h_sgl_pool; + handle_t h_ctx; +}; + +/* Capabilities */ +struct hisi_qm_capa { + char *alg; + int throughput; + int latency; + __u32 flags; + /* For algorithm parameters */ + __u8 priv[WD_CAPA_PRIV_DATA_SIZE]; +}; + +/** + * hisi_qm_send - Send req to the queue of the device. + * @h_qp: Handle of the qp. + * @req: User req from the alg driver. + * @expect: User send req num. + * @count: The count of actual sending message. + * + * There is not one locked in the qm internal, Alg should + * ensure resource non-reentrant. + * If the free queue num is zero, the return value is -WD_EBUSY + */ +int hisi_qm_send(handle_t h_qp, const void *req, __u16 expect, __u16 *count); + +/** + * hisi_qm_recv - Recieve msg from qm of the device. + * @h_qp: Handle of the qp. + * @resp: Msg out buffer of the user. + * @expect: User recieve req num. + * @count: The count of actual recieving message. + */ +int hisi_qm_recv(handle_t h_qp, void *resp, __u16 expect, __u16 *count); + +handle_t hisi_qm_alloc_qp(struct hisi_qm_priv *config, handle_t ctx); +void hisi_qm_free_qp(handle_t h_qp); + +/** + * hisi_check_bd_id - Check the SQE BD's id and send msg id. + * @h_qp: Handle of the qp. + * @mid: send message id. + * @bid: recv BD id. + */ +int hisi_check_bd_id(handle_t h_qp, __u32 mid, __u32 bid); + +/** + * hisi_set_msg_id - set the message tag id. + * @h_qp: Handle of the qp. + * @tag: the message tag id. + */ +void hisi_set_msg_id(handle_t h_qp, __u32 *tag); + +/** + * hisi_qm_create_sglpool - Create sgl pool in qm. + * @sgl_num: the sgl number. + * @sge_num: the sge num in every sgl num. + * + * Fixed me: the sge buff's size now is Fixed. + */ +handle_t hisi_qm_create_sglpool(__u32 sgl_num, __u32 sge_num); + +/** + * hisi_qm_destroy_sglpool - Destroy sgl pool in qm. + * @sgl_pool: Handle of the sgl pool. + */ +void hisi_qm_destroy_sglpool(handle_t sgl_pool); + +/** + * hisi_qm_get_hw_sgl - Get sgl pointer from sgl pool. + * @sgl_pool: Handle of the sgl pool. + * @sgl: The user sgl info's pointer. + * + * Return the hw sgl addr which can fill into the sqe. + */ +void *hisi_qm_get_hw_sgl(handle_t sgl_pool, struct wd_datalist *sgl); + +/** + * hisi_qm_put_hw_sgl - Reback the hw sgl to the sgl pool. + * @sgl_pool: Handle of the sgl pool. + * @hw_sgl: The pointer of the hw sgl which get from sgl pool. + */ +void hisi_qm_put_hw_sgl(handle_t sgl_pool, void *hw_sgl); + +/** + * hisi_qm_get_sglpool - Get the qp's hw sgl pool handle + * @h_qp: Handle of the qp. + */ +handle_t hisi_qm_get_sglpool(handle_t h_qp); + +/** + * hisi_qm_sgl_copy: Buffer copying from hw sgl to pbuff or pbuff to sgl + * @pbuff: pbuff point + * @hw_sgl: Src hw sgl point + * @offset: Offset in hw sgl chain + * @size: Copy size + * @direct: 0:sgl to pbuff, 1:pbuff to sgl, from enum hisi_qm_sgl_copy_dir + * + * If the len of sgl is not enough, will copy much as soon as + * possible before the offset to end of the sgl. + */ +void hisi_qm_sgl_copy(void *pbuff, void *hw_sgl, __u32 offset, + __u32 size, __u8 direct); + +/** + * hisi_qm_get_free_sqe_num - Get the qp's available sqe num + * @h_qp: Handle of the qp. + * + * This interface does not add locks, guaranteed by the caller + */ +int hisi_qm_get_free_sqe_num(handle_t h_qp); + +/** + * hisi_qm_get_list_size - Calculate the total length between two nodes. + * Excludes the length of the end_node. + * @start_node: The start node. + * @end_node: The end node. + */ +__u32 hisi_qm_get_list_size(struct wd_datalist *start_node, + struct wd_datalist *end_node); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/uadk/include/uacce.h b/uadk/include/uacce.h new file mode 100644 index 0000000..fb3fb22 --- /dev/null +++ b/uadk/include/uacce.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. + * Copyright 2020-2021 Linaro ltd. + */ + +#ifndef _UAPIUUACCE_H +#define _UAPIUUACCE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define UACCE_CMD_START _IO('W', 0) +#define UACCE_CMD_PUT_Q _IO('W', 1) +#define UACCE_CMD_GET_SS_DMA _IOR('W', 100, unsigned long) + +/** + * UACCE Device flags: + * + * SVA: Shared Virtual Addresses + * Support PASID + * Support device page faults (PCI PRI or SMMU Stall) + */ + +enum { + UACCE_DEV_SVA = 0x1, +}; + +#define UACCE_API_VER_NOIOMMU_SUBFIX "_noiommu" + +enum uacce_qfrt { + UACCE_QFRT_MMIO = 0, /* device mmio region */ + UACCE_QFRT_DUS = 1, /* device user share */ + UACCE_QFRT_MAX, +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/uadk/include/wd.h b/uadk/include/wd.h new file mode 100644 index 0000000..b0580ba --- /dev/null +++ b/uadk/include/wd.h @@ -0,0 +1,532 @@ +// SPDX-License-Identifier: Apache-2.0 +/* + * Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. + * Copyright 2020-2021 Linaro ltd. + */ + +#ifndef __WD_H +#define __WD_H +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "uacce.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define PATH_STR_SIZE 256 +#define MAX_ATTR_STR_SIZE 384 +#define WD_NAME_SIZE 64 +#define MAX_DEV_NAME_LEN 256 +#define LINUX_CRTDIR_SIZE 1 +#define LINUX_PRTDIR_SIZE 2 +#define WD_CTX_CNT_NUM 1024 +#define WD_IPC_KEY 0x500011 + +typedef void (*wd_log)(const char *format, ...); + +#ifndef WD_NO_LOG +#define WD_DEBUG(fmt, args...) \ + do {\ + openlog("uadk-debug", LOG_CONS | LOG_PID, LOG_LOCAL5);\ + syslog(LOG_DEBUG, fmt, ##args);\ + } while (0) + +#define WD_INFO(fmt, args...) \ + do {\ + openlog("uadk-info", LOG_CONS | LOG_PID, LOG_LOCAL5);\ + syslog(LOG_INFO, fmt, ##args);\ + } while (0) + +#define WD_ERR(fmt, args...) \ + do {\ + openlog("uadk-err", LOG_CONS | LOG_PID, LOG_LOCAL5);\ + syslog(LOG_ERR, fmt, ##args);\ + } while (0) +#else +#define OPEN_LOG(s) +#define WD_DEBUG(fmt, args...) fprintf(stderr, fmt, ##args) +#define WD_INFO(fmt, args...) fprintf(stderr, fmt, ##args) +#define WD_ERR(fmt, args...) fprintf(stderr, fmt, ##args) +#endif + +/* @h_ctx: The handle of context. */ +#define WD_DEV_ERR(h_ctx, format, args...)\ + do { \ + char *dev_name = wd_ctx_get_dev_name(h_ctx); \ + WD_ERR("%s: "format"\n", dev_name, ##args); \ + } while (0) + +#define WD_CONSOLE printf + +/* WD error code */ +#define WD_SUCCESS 0 +#define WD_STREAM_END 1 +#define WD_STREAM_START 2 +#define WD_EIO EIO +#define WD_EAGAIN EAGAIN +#define WD_ENOMEM ENOMEM +#define WD_EACCESS EACCESS +#define WD_EBUSY EBUSY +#define WD_EEXIST EEXIST +#define WD_ENODEV ENODEV +#define WD_EINVAL EINVAL +#define WD_ETIMEDOUT ETIMEDOUT +#define WD_ADDR_ERR 61 /* address error */ +#define WD_HW_EACCESS 62 /* hardware access denied, such as resetting */ +#define WD_SGL_ERR 63 /* sgl input parameter error */ +#define WD_VERIFY_ERR 64 /* verified error */ +#define WD_OUT_EPARA 66 /* output parameter error */ +#define WD_IN_EPARA 67 /* input parameter error */ +#define WD_ENOPROC 68 /* no processed */ + +#define WD_HANDLE_ERR(h) ((long long)(h)) +#define WD_IS_ERR(h) ((uintptr_t)(h) > \ + (uintptr_t)(-1000)) + +static inline void *WD_ERR_PTR(uintptr_t error) +{ + return (void *)error; +} + +enum wcrypto_type { + WD_CIPHER, + WD_DIGEST, + WD_AEAD, +}; + +struct wd_dtb { + /* data/buffer start address */ + char *data; + /* data size */ + __u32 dsize; + /* buffer size */ + __u32 bsize; +}; + +struct uacce_dev { + /* sysfs node content */ + /* flag: SVA */ + int flags; + /* HW context type */ + char api[WD_NAME_SIZE]; + /* dev supported algorithms */ + char algs[MAX_ATTR_STR_SIZE]; + unsigned long qfrs_offs[UACCE_QFRT_MAX]; + /* sysfs path with dev name */ + char dev_root[PATH_STR_SIZE]; + + /* dev path in devfs */ + char char_dev_path[MAX_DEV_NAME_LEN]; + + int numa_id; +}; + +struct uacce_dev_list { + struct uacce_dev *dev; + struct uacce_dev_list *next; +}; + +struct wd_dev_mask { + unsigned char *mask; + + int len; + unsigned int magic; +}; + +#define handle_t uintptr_t +typedef struct wd_dev_mask wd_dev_mask_t; + +#if defined(__AARCH64_CMODEL_SMALL__) && __AARCH64_CMODEL_SMALL__ +#define dsb(opt) { asm volatile("dsb " #opt : : : "memory"); } +#define rmb() dsb(ld) /* read fence */ +#define wmb() dsb(st) /* write fence */ +#define mb() dsb(sy) /* rw fence */ +#else +#define rmb() __sync_synchronize() /* read fence */ +#define wmb() __sync_synchronize() /* write fence */ +#define mb() __sync_synchronize() /* rw fence */ +#endif + +static inline uint32_t wd_ioread32(void *addr) +{ + uint32_t ret; + + ret = *((volatile uint32_t *)addr); + rmb(); + return ret; +} + +static inline uint64_t wd_ioread64(void *addr) +{ + uint64_t ret; + + ret = *((volatile uint64_t *)addr); + rmb(); + return ret; +} + +static inline void wd_iowrite32(void *addr, uint32_t value) +{ + wmb(); + *((volatile uint32_t *)addr) = value; +} + +static inline void wd_iowrite64(void *addr, uint64_t value) +{ + wmb(); + *((volatile uint64_t *)addr) = value; +} + +/** + * wd_request_ctx() - Request a communication context from a device. + * @dev: Indicate one device. + * + * Return the handle of related context or NULL otherwise. + * + * The context is communication context between user and hardware. One context + * must be got before doing any task. This function can be used among multiple + * threads. dev should be got from wd_get_accel_list() firstly. + */ +handle_t wd_request_ctx(struct uacce_dev *dev); + +/** + * wd_release_ctx() - Release a context. + * @h_ctx: The handle of context which will be released. + * + * The function is the wrapper of close fd. So the release of context maybe + * delay. + */ +void wd_release_ctx(handle_t h_ctx); + +/** + * wd_ctx_start() - Start a context. + * @h_ctx: The handle of context which will be started. + * + * Return 0 if successful or less than 0 otherwise. + * + * Context will be started after calling this function. If necessary resource + * (e.g. MMIO and DUS) already got, tasks can be received by context. + */ +int wd_ctx_start(handle_t h_ctx); + +/** + * wd_release_ctx_force() - Release a context forcely. + * @h_ctx: The handle of context which will be released. + * + * Return 0 if successful or less than 0 otherwise. + * + * Context will be stopped and related hardware will be released, which avoids + * release delay in wd_release_ctx(). After calling this function, context + * related hardware resource will be released, however, fd is still there. + * wd_release_ctx mush be used to release context finally, other APIs about + * context can not work with this context after calling wd_release_ctx_force. + */ +int wd_release_ctx_force(handle_t h_ctx); + +/** + * wd_ctx_set_priv() - Store some information in context. + * @h_ctx: The handle of context. + * @priv: The pointer of memory which stores above information. + * + * Return 0 if successful or less than 0 otherwise. + */ +int wd_ctx_set_priv(handle_t h_ctx, void *priv); + +/** + * wd_ctx_get_priv() - Get stored information in context. + * @h_ctx: The handle of context. + * + * Return pointer of memory of stored information if successful or NULL + * otherwise. + */ +void *wd_ctx_get_priv(handle_t h_ctx); + +/** + * wd_ctx_get_api() - Get api string of context. + * @h_ctx: The handle of context. + * + * Return api string or NULL otherwise. + * + * This function is a wrapper of reading /sys/class/uacce//api, which is + * used to define api version between user space and kernel driver. + */ +char *wd_ctx_get_api(handle_t h_ctx); + +/** + * wd_ctx_mmap_qfr() - Map and get the base address of one context region. + * @h_ctx: The handle of context. + * @qfrt: Name of context region, which could be got in kernel head file + * include/uapi/misc/uacce/uacce.h + * + * Return pointer of context region if successful or NULL otherwise. + * + * Normally, UACCE_QFRT_MMIO is for MMIO registers of one context, + * UACCE_QFRT_DUS is for task communication memory of one context. + */ +void *wd_ctx_mmap_qfr(handle_t h_ctx, enum uacce_qfrt qfrt); + +/** + * wd_ctx_unmap_qfr() - Unmap one context region. + * @h_ctx: The handle of context. + * @qfrt: Name of context region, which could be got in kernel head file + * include/uapi/misc/uacce/uacce.h. + */ +void wd_ctx_unmap_qfr(handle_t h_ctx, enum uacce_qfrt qfrt); + +/** + * wd_ctx_wait() - Wait task in context finished. + * @h_ctx: The handle of context. + * @ms: Timeout parameter. + * + * Return more than 0 if successful, 0 for timeout, less than 0 otherwise. + * + * This function is a wrapper of Linux poll interface. + */ +int wd_ctx_wait(handle_t h_ctx, __u16 ms); + +/** + * wd_is_sva() - Check if the system supports SVA. + * @h_ctx: The handle of context. + * + * Return 1 if SVA, 0 for no SVA, less than 0 otherwise. + */ +int wd_is_sva(handle_t h_ctx); + +/** + * wd_is_isolate() - Check if the device has been isolated. + * @dev: Indicate one device. + * + * Return 1 if isolated, 0 for not isolated, less than 0 otherwise. + */ +int wd_is_isolate(struct uacce_dev *dev); + +/** + * wd_get_accel_name() - Get device name or driver name. + * @dev_path: The path of device. e.g. /dev/hisi_zip-0. + * @no_apdx: Flag to indicate getting device name(0) or driver name(1). + * + * Return device name, e.g. hisi_zip-0; driver name, e.g. hisi_zip. + */ +char *wd_get_accel_name(char *dev_path, int no_apdx); + +/** + * wd_get_numa_id() - Get the NUMA id of one context. + * @h_ctx: The handle of context. + * + * Return NUMA id of related context. + */ +int wd_get_numa_id(handle_t h_ctx); + +/** + * wd_get_avail_ctx() - Get available context in one device. + * @dev: The uacce_dev for one device. + * + * Return number of available context in dev or less than 0 otherwise. + */ +int wd_get_avail_ctx(struct uacce_dev *dev); + +/** + * wd_get_accel_list() - Get device list for one algorithm. + * @alg_name: Algorithm name, which could be got from + * /sys/class/uacce//algorithm. + * + * Return device list in which devices support given algorithm or NULL + * otherwise. + */ +struct uacce_dev_list *wd_get_accel_list(const char *alg_name); + +/** + * wd_get_accel_dev() - Get device supporting the algorithm with + smallest numa distance to current numa node. + * @alg_name: Algorithm name, which could be got from + * /sys/class/uacce//algorithm. + * + * Return a device closest to current numa node supporting given algorithm + * and the device need to be freed after usage. + * Otherwise return NULL. + */ +struct uacce_dev *wd_get_accel_dev(const char *alg_name); + +/** + * wd_free_list_accels() - Free device list. + * @list: Device list which will be free. + */ +void wd_free_list_accels(struct uacce_dev_list *list); + +/** + * wd_ctx_set_io_cmd() - Send ioctl command to context. + * @h_ctx: The handle of context. + * @cmd: ioctl command which could be found in Linux kernel head file, + * include/uapi/misc/uacce/uacce.h, hisi_qm.h... + * @arg: Command output buffer if some information will be got from kernel or + * NULL otherwise. + * + * This function is a wrapper of ioctl. + */ +int wd_ctx_set_io_cmd(handle_t h_ctx, unsigned long cmd, void *arg); + +/** + * wd_ctx_get_region_size() - Get region offset size + * @h_ctx: The handle of context. + * @qfrt: Name of context region, which could be got in kernel head file + * include/uapi/misc/uacce/uacce.h + * Return device region size. + */ +unsigned long wd_ctx_get_region_size(handle_t h_ctx, enum uacce_qfrt qfrt); + +enum wd_page_type { + WD_HUGE_PAGE = 0, + WD_NORMAL_PAGE, +}; + +/* + * struct wd_mempool_stats - Use to dump statistics info about mempool + * @page_type: 0 huge page, 1 mmap + pin. + * @page_size: Page size. + * @pape_num: Page numbers in mempool. + * @blk_size: Memory in mempool will be divied into blocks with same size, + * this is size of each block. Currently it is 4KB fixed. + * @blk_num: Number of blocks in mempool. + * @free_blk_num: Number of free blocks in mempool. + * @blk_usage_rate: In wd_blockpool_create function, it gets memory from + * mempool by mempool blocks. As continuous blocks in mempool + * may be needed, wd_blockpool_create may fail. blk_usage_rate + * helps to show the usage rate of mempool. It will be helpful + * to show the state of memory fragmentation. e.g. 30 is 30%. + */ +struct wd_mempool_stats { + enum wd_page_type page_type; + unsigned long page_size; + unsigned long page_num; + unsigned long blk_size; + unsigned long blk_num; + unsigned long free_blk_num; + unsigned long blk_usage_rate; +}; + +/* + * struct wd_blockpool_stats - Use to dump statistics info about blkpool + * @block_size: Block size. + * @block_num: Number of blocks. + * @free_block_num: Number of free blocks. + * @block_usage_rate: Block usage rate, e.g. 30 is 30% + * @mem_waste_rate: When blkpool allocate memory from mempool, it may waste + * some memory as below figure. This is the waste rate, + * e.g. 30 is 30%. + * +--+--+--+--+ +-------------------+ + * | | | | | waste memory | | waste memory + * +--+--+--+--+ / +-------------------+ / + * / / + * +-------------+ +-----+-----+-----+-----+ + * | | | | | | | + * +-------------+ +-----+-----+-----+-----+ + */ +struct wd_blockpool_stats { + unsigned long block_size; + unsigned long block_num; + unsigned long free_block_num; + unsigned long block_usage_rate; + unsigned long mem_waste_rate; +}; + +/** + * wd_block_alloc() - Allocate block memory from blkpool. + * @blkpool: The handle of blkpool. + * + * Return addr of block memory. + */ +void *wd_block_alloc(handle_t blkpool); + +/** + * wd_block_free() - Free block memory. + * @blkpool: The handle of blkpool. + * @addr: The addr of block memory. + */ +void wd_block_free(handle_t blkpool, void *addr); + +/** + * wd_blockpool_create() - Blkpool allocate memory from mempool. + * @mempool: The handle of mempool. + * @block_size: Size of every block in blkpool. + * @block_num: Number of blocks in blkpool. + * + * Return handle of blkpool if suceessful; On error, errno is set to indicate + * the error. WD_EINVAL: An invalid value was specified for mempool、block_size + * or block_num. WD_ENOMEM: Insufficient kernel memory was available. + */ +handle_t wd_blockpool_create(handle_t mempool, size_t block_size, + size_t block_num); + +/** + * wd_blockpool_destroy() - Destory blkpool and release memory to the mempool. + * @blkpool: The handle of blkpool. + */ +void wd_blockpool_destroy(handle_t blkpool); + +/** + * wd_mempool_create() - Creat mempool. + * @size: Size of mempool. + * @node: Node of numa, the memory policy defines from which node memory is + * allocated. If system does't support numa, node will be -1. + * + * Return handle of mempool if suceessful; On error, errno is set to indicate + * the error. WD_EINVAL: An invalid value was specified for size or node. + * WD_ENOMEM: Insufficient kernel memory was available. + */ +handle_t wd_mempool_create(size_t size, int node); + +/** + * wd_mempool_destroy() - Destory mempool. + * @mempool: The handle of mempool. + */ +void wd_mempool_destroy(handle_t mempool); + +/** + * wd_mempool_stats() - Dump statistics information about mempool. + * @mempool: The handle of mempool. + * @stats: Pointer of struct wd_mempool_stats. + */ +void wd_mempool_stats(handle_t mempool, struct wd_mempool_stats *stats); + +/** + * wd_blockpool_stats() - Dump statistics information about blkpool. + * @blkpool: The handle of blkpool. + * @stats: Pointer of struct wd_blockpool_stats. + */ +void wd_blockpool_stats(handle_t blkpool, struct wd_blockpool_stats *stats); + +/** + * wd_ctx_get_dev_name() - Get the device name about task. + * @h_ctx: The handle of context. + * Return device name. + */ +char *wd_ctx_get_dev_name(handle_t h_ctx); + +/** + * wd_get_version() - Get the libwd version number and released time. + */ +void wd_get_version(void); + +/** + * wd_need_debug() - Get the debug flag from rsyslog.cnf + */ +bool wd_need_debug(void); + +/** + * wd_need_info() - Get the info flag from rsyslog.cnf + */ +bool wd_need_info(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/uadk/include/wd_aead.h b/uadk/include/wd_aead.h new file mode 100644 index 0000000..3be8e8a --- /dev/null +++ b/uadk/include/wd_aead.h @@ -0,0 +1,227 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. + * Copyright 2020-2021 Linaro ltd. + */ + +#ifndef __WD_AEAD_H +#define __WD_AEAD_H + +#include +#include "config.h" +#include "wd.h" +#include "wd_alg_common.h" +#include "wd_cipher.h" +#include "wd_digest.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * wd_aead_op_type - Algorithm type of option + */ +enum wd_aead_op_type { + WD_CIPHER_ENCRYPTION_DIGEST, + WD_CIPHER_DECRYPTION_DIGEST, + WD_DIGEST_CIPHER_ENCRYPTION, + WD_DIGEST_CIPHER_DECRYPTION, +}; + +/** + * wd_cipher_alg - Algorithm type of cipher + * statement in wd_cipher.h + * + * wd_cipher_mode - Algorithm mode of cipher + * statement in wd_cipher.h + */ + +struct wd_aead_sess_setup { + enum wd_cipher_alg calg; + enum wd_cipher_mode cmode; + enum wd_digest_type dalg; + enum wd_digest_mode dmode; + void *sched_param; +}; + +struct wd_aead_req; +typedef void *wd_alg_aead_cb_t(struct wd_aead_req *req, void *cb_param); + +/** + * struct wd_aead_req - Parameters for per aead operation. + * @ op_type: denoted by enum wd_aead_op_type + * @ src: input data pointer + * @ dst: output data pointer + * @ mac: mac data pointer + * @ iv: input iv pointer + * @ in_bytes: input data length + * @ out_bytes: output data length + * @ iv_bytes: input iv length + * @ mac_bytes: mac data buffer length + * @ assoc_bytes: input associated data length + * @ state: operation result, denoted by WD error code + * @ cb: callback function pointer + * @ cb_param: callback function paramaters + */ +struct wd_aead_req { + enum wd_aead_op_type op_type; + union { + struct wd_datalist *list_src; + void *src; + }; + union { + struct wd_datalist *list_dst; + void *dst; + }; + void *mac; + void *iv; + __u32 in_bytes; + __u32 out_bytes; + __u16 iv_bytes; + __u16 mac_bytes; + __u16 assoc_bytes; + __u16 state; + __u8 data_fmt; + wd_alg_aead_cb_t *cb; + void *cb_param; +}; + +/** + * wd_aead_init() Initialise ctx configuration and schedule. + * @ config User defined ctx configuration. + * @ sched User defined schedule. + */ +int wd_aead_init(struct wd_ctx_config *config, struct wd_sched *sched); + +/** + * wd_aead_uninit() uninitialized ctx configuration and schedule. + */ +void wd_aead_uninit(void); + +/** + * wd_aead_alloc_sess() Allocate a wd aead session + * @ setup Parameters to setup this session. + */ +handle_t wd_aead_alloc_sess(struct wd_aead_sess_setup *setup); + +/** + * wd_aead_free_sess() + * @ sess, need to be freed sess + */ +void wd_aead_free_sess(handle_t h_sess); + +/** + * wd_aead_set_ckey() Set cipher key to aead session. + * @h_sess: wd aead session. + * @key: cipher key addr. + * @key_len: cipher key length. + */ +int wd_aead_set_ckey(handle_t h_sess, const __u8 *key, __u16 key_len); + +/** + * wd_aead_set_akey() Set authenticate key to aead session. + * @h_sess: wd aead session. + * @key: authenticate key addr. + * @key_len: authenticate key length. + */ +int wd_aead_set_akey(handle_t h_sess, const __u8 *key, __u16 key_len); + +/** + * wd_do_aead_sync() synchronous aead operation + * @sess: wd aead session + * @req: operational data. + */ +int wd_do_aead_sync(handle_t h_sess, struct wd_aead_req *req); + +/** + * wd_do_aead_async() asynchronous aead operation + * @sess: wd aead session + * @req: operational data. + */ +int wd_do_aead_async(handle_t h_sess, struct wd_aead_req *req); + +/** + * wd_aead_set_authsize() Set authenticate data length to aead session. + * @h_sess: wd aead session. + * @authsize: authenticate data length. + */ +int wd_aead_set_authsize(handle_t h_sess, __u16 authsize); + +/** + * wd_aead_get_authsize() Get authenticate data length from aead session. + * @h_sess: wd aead session. + */ +int wd_aead_get_authsize(handle_t h_sess); + +/** + * wd_aead_get_maxauthsize() Get max authenticate data length from aead API. + * @h_sess: wd aead session. + */ +int wd_aead_get_maxauthsize(handle_t h_sess); + +/** + * wd_aead_poll_ctx() poll operation for asynchronous operation + * @idx: index of ctx which will be polled. + * @expt: user expected num respondences + * @count: how many respondences this poll has to get. + */ +int wd_aead_poll_ctx(__u32 idx, __u32 expt, __u32 *count); + +/** + * wd_aead_poll() Poll finished request. + * this function will call poll_policy function which is registered to wd aead + * by user. + * @expt: user expected num respondences + * @count: how many respondences this poll has to get. + */ +int wd_aead_poll(__u32 expt, __u32 *count); + +/** + * wd_aead_env_init() - Init ctx and schedule resources according to wd aead + * environment variables. + * @sched: user's custom scheduler. + * More information, please see docs/wd_environment_variable. + */ +int wd_aead_env_init(struct wd_sched *sched); + +/** + * wd_aead_env_uninit() - UnInit ctx and schedule resources set by above init. + */ +void wd_aead_env_uninit(void); + +/** + * wd_aead_ctx_num_init() - request ctx for aead. + * @node: numa node id. + * @type: operation type. + * @num: ctx number. + * @mode: 0: sync mode, 1: async mode + */ +int wd_aead_ctx_num_init(__u32 node, __u32 type, __u32 num, __u8 mode); + +/** + * wd_aead_ctx_num_uninit() - UnInit ctx and schedule resources + * set by above init. + */ +void wd_aead_ctx_num_uninit(void); + +/** + * wd_aead_get_env_param() - query the number of CTXs + * that meet input attributes. + * @node: numa node id. + * @type: operation type. + * @mode: 0: sync mode, 1: async mode + * @num: return ctx num. + * @is_enable return enable inner poll flag. + * + * If the current algorithm library does not require the type parameter, + * the type parameter is invalid. The function returns 0 to indicate that + * the value read is valid; otherwise, it returns a negative number. + */ +int wd_aead_get_env_param(__u32 node, __u32 type, __u32 mode, + __u32 *num, __u8 *is_enable); + +#ifdef __cplusplus +} +#endif + +#endif /* __WD_AEAD_H */ diff --git a/uadk/include/wd_alg_common.h b/uadk/include/wd_alg_common.h new file mode 100644 index 0000000..c455dc3 --- /dev/null +++ b/uadk/include/wd_alg_common.h @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: Apache-2.0 +/* + * Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. + * Copyright 2020-2021 Linaro ltd. + */ + +#ifndef WD_ALG_COMMON_H +#define WD_ALG_COMMON_H + +#include +#include +#include "wd.h" +#include "wd_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Required compiler attributes */ +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) + +#define BYTE_BITS_SHIFT 3 +#define BITS_TO_BYTES(bits) (((bits) + 7) >> 3) +#define BYTES_TO_BITS(bytes) ((bytes) << 3) + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#define MAX_STR_LEN 256 +#define CTX_TYPE_INVALID 9999 +#define POLL_TIME 1000 + +enum wd_ctx_mode { + CTX_MODE_SYNC = 0, + CTX_MODE_ASYNC, + CTX_MODE_MAX, +}; + +/** + * struct wd_ctx - Define one ctx and related type. + * @ctx: The ctx itself. + * @op_type: Define the operation type of this specific ctx. + * e.g. 0: compression; 1: decompression. + * @ctx_mode: Define this ctx is used for synchronization of asynchronization + * 1: synchronization; 0: asynchronization; + */ +struct wd_ctx { + handle_t ctx; + __u8 op_type; + __u8 ctx_mode; +}; + +/** + * struct wd_ctx_config - Define a ctx set and its related attributes, which + * will be used in the scope of current process. + * @ctx_num: The ctx number in below ctx array. + * @ctxs: Point to a ctx array, length is above ctx_num. + * @priv: The attributes of ctx defined by user, which is used by user + * defined scheduler. + */ +struct wd_ctx_config { + __u32 ctx_num; + struct wd_ctx *ctxs; + void *priv; +}; + +struct wd_ctx_internal { + handle_t ctx; + __u8 op_type; + __u8 ctx_mode; + pthread_spinlock_t lock; +}; + +struct wd_ctx_config_internal { + __u32 ctx_num; + struct wd_ctx_internal *ctxs; + void *priv; + int pid; + bool epoll_en; + unsigned long *msg_cnt; +}; + +/** + * struct wd_comp_sched - Define a scheduler. + * @name: Name of this scheduler. + * @sched_policy: Method for scheduler to perform scheduling + * @sched_init: inited the scheduler input parameters. + * @pick_next_ctx: Pick the proper ctx which a request will be sent to. + * config points to the ctx config; sched_ctx points to + * scheduler context; req points to the request. Return + * the proper ctx pos in wd_ctx_config. + * (fix me: modify req to request?) + * @poll_policy: Define the polling policy. config points to the ctx + * config; sched_ctx points to scheduler context; Return + * number of polled request. + */ +struct wd_sched { + const char *name; + int sched_policy; + handle_t (*sched_init)(handle_t h_sched_ctx, void *sched_param); + __u32 (*pick_next_ctx)(handle_t h_sched_ctx, + void *sched_key, + const int sched_mode); + int (*poll_policy)(handle_t h_sched_ctx, __u32 expect, __u32 *count); + handle_t h_sched_ctx; +}; + +struct wd_datalist { + void *data; + __u32 len; + struct wd_datalist *next; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/uadk/include/wd_cipher.h b/uadk/include/wd_cipher.h new file mode 100644 index 0000000..dfd6e60 --- /dev/null +++ b/uadk/include/wd_cipher.h @@ -0,0 +1,196 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. + * Copyright 2020-2021 Linaro ltd. + */ + +#ifndef __WD_CIPHER_H +#define __WD_CIPHER_H + +#include +#include "wd.h" +#include "wd_alg_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define AES_BLOCK_SIZE 16 +#define GCM_BLOCK_SIZE 12 +#define DES3_BLOCK_SIZE 8 +#define MAX_CIPHER_KEY_SIZE 64 +#define MAX_IV_SIZE AES_BLOCK_SIZE + +/** + * config ctx operation type and task mode. + * + */ +enum { + CTX_TYPE_ENCRYPT = 0, + CTX_TYPE_DECRYPT, +}; + +/** + * wd_cipher_op_type - Algorithm type of option + */ +enum wd_cipher_op_type { + WD_CIPHER_ENCRYPTION, + WD_CIPHER_DECRYPTION, +}; + +/** + * wd_cipher_type - Algorithm type of cipher + */ +enum wd_cipher_alg { + WD_CIPHER_SM4, + WD_CIPHER_AES, + WD_CIPHER_DES, + WD_CIPHER_3DES, + WD_CIPHER_ALG_TYPE_MAX, +}; + +/** + * wd_cipher_mode - Algorithm mode of cipher + */ +enum wd_cipher_mode { + WD_CIPHER_ECB, + WD_CIPHER_CBC, + WD_CIPHER_CTR, + WD_CIPHER_XTS, + WD_CIPHER_OFB, + WD_CIPHER_CFB, + WD_CIPHER_CBC_CS1, + WD_CIPHER_CBC_CS2, + WD_CIPHER_CBC_CS3, + WD_CIPHER_CCM, + WD_CIPHER_GCM, + WD_CIPHER_MODE_TYPE_MAX, +}; + +struct wd_cipher_sess_setup { + enum wd_cipher_alg alg; + enum wd_cipher_mode mode; + void *sched_param; +}; + +struct wd_cipher_req; +typedef void *wd_alg_cipher_cb_t(struct wd_cipher_req *req, void *cb_param); + +struct wd_cipher_req { + enum wd_cipher_op_type op_type; + union { + struct wd_datalist *list_src; + void *src; + }; + union { + struct wd_datalist *list_dst; + void *dst; + }; + void *iv; + __u32 in_bytes; + __u32 iv_bytes; + __u32 out_buf_bytes; + __u32 out_bytes; + __u16 state; + __u8 type; + __u8 data_fmt; + wd_alg_cipher_cb_t *cb; + void *cb_param; +}; + +/** + * wd_cipher_init() Initialise ctx configuration and schedule. + * @ config User defined ctx configuration. + * @ sched User defined schedule. + */ +int wd_cipher_init(struct wd_ctx_config *config, struct wd_sched *sched); +void wd_cipher_uninit(void); + +/** + * wd_cipher_alloc_sess() Allocate a wd cipher session + * @ setup Parameters to setup this session. + */ +handle_t wd_cipher_alloc_sess(struct wd_cipher_sess_setup *setup); + +/** + * wd_cipher_free_sess() + * @ sess, need to be freed sess + */ +void wd_cipher_free_sess(handle_t h_sess); + +/** + * wd_cipher_set_key() Set cipher key to cipher msg. + * @h_sess: wd cipher session. + * @key: cipher key addr. + * @key_len: cipher key length. + */ +int wd_cipher_set_key(handle_t h_sess, const __u8 *key, __u32 key_len); + +/** + * wd_do_cipher_sync()/ async() Syn/asynchronous cipher operation + * @sess: wd cipher session + * @req: operational data. + */ +int wd_do_cipher_sync(handle_t h_sess, struct wd_cipher_req *req); +int wd_do_cipher_async(handle_t h_sess, struct wd_cipher_req *req); +/** + * wd_cipher_poll_ctx() poll operation for asynchronous operation + * @idx: index of ctx which will be polled. + * @expt: user expected num respondences + * @count: how many respondences this poll has to get. + */ +int wd_cipher_poll_ctx(__u32 idx, __u32 expt, __u32 *count); +/** + * wd_cipher_poll() Poll finished request. + * this function will call poll_policy function which is registered to wd cipher + * by user. + */ +int wd_cipher_poll(__u32 expt, __u32 *count); +/** + * wd_cipher_env_init() - Init ctx and schedule resources according to wd cipher + * environment variables. + * + * @sched: user's custom scheduler. + * More information, please see docs/wd_environment_variable. + */ +int wd_cipher_env_init(struct wd_sched *sched); + +/** + * wd_cipher_env_uninit() - UnInit ctx and schedule resources set by above init. + */ +void wd_cipher_env_uninit(void); + +/** + * wd_cipher_ctx_num_init() - request ctx for cipher. + * @node: numa node id. + * @type: operation type. + * @num: ctx number. + * @mode: 0: sync mode, 1: async mode + */ +int wd_cipher_ctx_num_init(__u32 node, __u32 type, __u32 num, __u8 mode); + +/** + * wd_cipher_ctx_num_uninit() - UnInit ctx and schedule resources + * set by above init. + * + */ +void wd_cipher_ctx_num_uninit(void); + +/** + * wd_cipher_get_env_param() - query the number of CTXs + * that meet input attributes. + * + * @node: numa node id. + * @type: operation type. + * @mode: 0: sync mode, 1: async mode + * @num: return ctx num. + * @is_enable return enable inner poll flag. + */ +int wd_cipher_get_env_param(__u32 node, __u32 type, __u32 mode, + __u32 *num, __u8 *is_enable); + +#ifdef __cplusplus +} +#endif + +#endif /* __WD_CIPHER_H */ diff --git a/uadk/include/wd_common.h b/uadk/include/wd_common.h new file mode 100644 index 0000000..91dd066 --- /dev/null +++ b/uadk/include/wd_common.h @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: Apache-2.0 +/* + * Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. + * Copyright 2020-2021 Linaro ltd. + */ + +#ifndef __WD_COMMON_H +#define __WD_COMMON_H + +#ifdef __cplusplus +extern "C" { +#endif + +enum wd_buff_type { + WD_FLAT_BUF, + WD_SGL_BUF, +}; + +#ifdef __cplusplus +} +#endif + +#endif /* __WD_COMMON_H */ diff --git a/uadk/include/wd_comp.h b/uadk/include/wd_comp.h new file mode 100644 index 0000000..e043a83 --- /dev/null +++ b/uadk/include/wd_comp.h @@ -0,0 +1,226 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. + * Copyright 2020-2021 Linaro ltd. + */ + +#ifndef __WD_COMP_H +#define __WD_COMP_H + +#include "wd.h" +#include "wd_alg_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum wd_comp_alg_type { + WD_DEFLATE, + WD_ZLIB, + WD_GZIP, + WD_LZ77_ZSTD, + WD_COMP_ALG_MAX, +}; + +enum wd_comp_op_type { + WD_DIR_COMPRESS, /* session for compression */ + WD_DIR_DECOMPRESS, /* session for decompression */ + WD_DIR_MAX, +}; + +enum wd_comp_level { + WD_COMP_L1 = 1, /* Compression level 1 */ + WD_COMP_L2, /* Compression level 2 */ + WD_COMP_L3, /* Compression level 3 */ + WD_COMP_L4, /* Compression level 4 */ + WD_COMP_L5, /* Compression level 5 */ + WD_COMP_L6, /* Compression level 6 */ + WD_COMP_L7, /* Compression level 7 */ + WD_COMP_L8, /* Compression level 8 */ + WD_COMP_L9, /* Compression level 9 */ + WD_COMP_L10, /* Compression level 10 */ + WD_COMP_L11, /* Compression level 11 */ + WD_COMP_L12, /* Compression level 12 */ + WD_COMP_L13, /* Compression level 13 */ + WD_COMP_L14, /* Compression level 14 */ + WD_COMP_L15, /* Compression level 15 */ +}; + +enum wd_comp_winsz_type { + WD_COMP_WS_4K, /* 4k bytes window size */ + WD_COMP_WS_8K, /* 8k bytes window size */ + WD_COMP_WS_16K, /* 16k bytes window size */ + WD_COMP_WS_24K, /* 24k bytes window size */ + WD_COMP_WS_32K, /* 32k bytes window size */ +}; + +struct wd_comp_req; + +typedef void *wd_alg_comp_cb_t(struct wd_comp_req *req, void *cb_param); + +struct wd_comp_req { + union { + void *src; + struct wd_datalist *list_src; + }; + __u32 src_len; + union { + void *dst; + struct wd_datalist *list_dst; + }; + __u32 dst_len; + wd_alg_comp_cb_t *cb; + void *cb_param; + enum wd_comp_op_type op_type; /* Denoted by wd_comp_op_type */ + enum wd_buff_type data_fmt; /* Denoted by wd_buff_type */ + __u32 last; + __u32 status; + void *priv; +}; + +/** + * The output format defined by hardware and drivers should fill the format + * @literals_start:address of the literals data output by the hardware + * @sequences_start:address of the sequences data output by the hardware + * @lit_num:the size of literals + * @seq_num:the size of sequences + * @lit_length_overflow_cnt:the count of the literal length overflow + * @lit_length_overflow_pos:the position of the literal length overflow + * @freq:address of the frequency about sequences members + * @blk_type:the previous block status, 0 means an uncompressed block, + * 1 means a RLE block and 2 means a compressed block. + */ +struct wd_lz77_zstd_data { + void *literals_start; + void *sequences_start; + __u32 lit_num; + __u32 seq_num; + __u32 lit_length_overflow_cnt; + __u32 lit_length_overflow_pos; + void *freq; + __u32 blk_type; +}; + +/** + * wd_comp_init() - Initialise ctx configuration and scheduler. + * @ config: User defined ctx configuration. + * @ sched: User defined scheduler. + */ +int wd_comp_init(struct wd_ctx_config *config, struct wd_sched *sched); + +/** + * wd_comp_uninit() - Un-initialise ctx configuration and scheduler. + */ +void wd_comp_uninit(void); + +struct wd_comp_sess_setup { + enum wd_comp_alg_type alg_type; /* Denoted by enum wd_comp_alg_type */ + enum wd_comp_level comp_lv; /* Denoted by enum wd_comp_level */ + enum wd_comp_winsz_type win_sz; /* Denoted by enum wd_comp_winsz_type */ + enum wd_comp_op_type op_type; /* Denoted by enum wd_comp_op_type */ + void *sched_param; +}; + +/** + * wd_comp_alloc_sess() - Allocate a wd comp session. + * @setup: Parameters to setup this session. + */ +handle_t wd_comp_alloc_sess(struct wd_comp_sess_setup *setup); + +/** + * wd_comp_free_sess() - Free a wd comp session. + * @h_sess: The sess to be freed. + */ +void wd_comp_free_sess(handle_t h_sess); + +/** + * wd_do_comp_sync() - Send a sync compression request. + * @h_sess: The session which request will be sent to. + * @req: Request. + */ +int wd_do_comp_sync(handle_t h_sess, struct wd_comp_req *req); + +int wd_do_comp_strm(handle_t h_sess, struct wd_comp_req *req); + + +/** + * wd_do_comp_async() - Send an async compression request. + * @h_sess: The session which request will be sent to. + * @req: Request. + */ +int wd_do_comp_async(handle_t h_sess, struct wd_comp_req *req); + +/** + * wd_comp_poll_ctx() - Poll a ctx. + * @idx: The index of ctx which will be polled. + * @expt: Max number of requests to poll. If 0, polled all finished + * requests in this ctx. + * @count: Return the number of polled requests finally. + * + * This is a help function which can be used by user's poll_policy function. + * User defines polling policy in poll_policiy, when it needs to poll a + * specific ctx, this function should be used. + */ +int wd_comp_poll_ctx(__u32 idx, __u32 expt, __u32 *count); + +int wd_comp_poll(__u32 expt, __u32 *count); + +/** + * wd_do_comp_sync2() - advanced sync compression interface, can do u32 size input. + * @h_sess: The session which request will be sent to. + * @req: Request. + */ +int wd_do_comp_sync2(handle_t h_sess, struct wd_comp_req *req); + +/** + * wd_comp_env_init() - Init ctx and schedule resources according to wd comp + * environment variables. + * + * @sched: user's custom scheduler. + * More information, please see docs/wd_environment_variable. + */ +int wd_comp_env_init(struct wd_sched *sched); + +/** + * wd_comp_env_uninit() - UnInit ctx and schedule resources set by above init. + */ +void wd_comp_env_uninit(void); + +/** + * wd_comp_ctx_num_init() - request ctx for comp. + * @node: numa node id. + * @type: operation type. + * @num: ctx number. + * @mode: 0: sync mode, 1: async mode + */ +int wd_comp_ctx_num_init(__u32 node, __u32 type, __u32 num, __u8 mode); + +/** + * wd_comp_ctx_num_uninit() - UnInit ctx and schedule resources + * set by above init. + * + */ +void wd_comp_ctx_num_uninit(void); + +/** + * wd_comp_get_env_param() - query the number of CTXs + * that meet input attributes. + * + * @node: numa node id. + * @type: operation type. + * @mode: 0: sync mode, 1: async mode + * @num: return ctx num. + * @is_enable return enable inner poll flag. + * + * If the current algorithm library does not require the type parameter, + * the type parameter is invalid. The function returns 0 to indicate that + * the value read is valid; otherwise, it returns a negative number. + */ +int wd_comp_get_env_param(__u32 node, __u32 type, __u32 mode, + __u32 *num, __u8 *is_enable); + +#ifdef __cplusplus +} +#endif + +#endif /* __WD_COMP_H */ diff --git a/uadk/include/wd_dh.h b/uadk/include/wd_dh.h new file mode 100644 index 0000000..f342722 --- /dev/null +++ b/uadk/include/wd_dh.h @@ -0,0 +1,80 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. + * Copyright 2020-2021 Linaro ltd. + */ + +#ifndef __WD_DH_H +#define __WD_DH_H + +#include + +#include "wd.h" +#include "wd_alg_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define BYTE_BITS 8 +#define BYTE_BITS_SHIFT 3 +#define GET_NEGATIVE(val) (0 - (val)) + +typedef void (*wd_dh_cb_t)(void *cb_param); + +enum wd_dh_op_type { + WD_DH_INVALID, /* invalid DH operation */ + WD_DH_PHASE1, /* Phase1 DH key generate */ + WD_DH_PHASE2 /* Phase2 DH key compute */ +}; + +struct wd_dh_sess_setup { + __u16 key_bits; /* DH key bites */ + bool is_g2; /* is g2 mode or not */ + void *sched_param; +}; + +struct wd_dh_req { + void *x_p; /* x and p */ + + /* it is g, but it is PV at phase 2 */ + void *pv; + + /* phase 1&&2 output */ + void *pri; + __u16 pri_bytes; /* output bytes */ + + __u16 pbytes; /* p bytes */ + __u16 xbytes; /* x bytes */ + __u16 pvbytes; /* pv bytes */ + wd_dh_cb_t cb; + void *cb_param; + int status; /* output status */ + __u8 op_type; /* operational type */ + __u8 data_fmt; /* data format denoted by enum wd_buff_type */ +}; + +int wd_dh_get_mode(handle_t sess, __u8 *alg_mode); +__u32 wd_dh_key_bits(handle_t sess); +int wd_dh_set_g(handle_t sess, struct wd_dtb *g); +void wd_dh_get_g(handle_t sess, struct wd_dtb **g); +handle_t wd_dh_alloc_sess(struct wd_dh_sess_setup *setup); +void wd_dh_free_sess(handle_t sess); +int wd_do_dh_async(handle_t sess, struct wd_dh_req *req); +int wd_do_dh_sync(handle_t sess, struct wd_dh_req *req); +int wd_dh_poll_ctx(__u32 idx, __u32 expt, __u32 *count); +int wd_dh_poll(__u32 expt, __u32 *count); +int wd_dh_init(struct wd_ctx_config *config, struct wd_sched *sched); +void wd_dh_uninit(void); +int wd_dh_env_init(struct wd_sched *sched); +void wd_dh_env_uninit(void); +int wd_dh_ctx_num_init(__u32 node, __u32 type, __u32 num, __u8 mode); +void wd_dh_ctx_num_uninit(void); +int wd_dh_get_env_param(__u32 node, __u32 type, __u32 mode, + __u32 *num, __u8 *is_enable); + +#ifdef __cplusplus +} +#endif + +#endif /* __WD_DH_H */ diff --git a/uadk/include/wd_digest.h b/uadk/include/wd_digest.h new file mode 100644 index 0000000..eb764ce --- /dev/null +++ b/uadk/include/wd_digest.h @@ -0,0 +1,245 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. + * Copyright 2020-2021 Linaro ltd. + */ + +#ifndef __WD_DIGEST_H +#define __WD_DIGEST_H +#include + +#include "wd.h" +#include "wd_alg_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define MAX_HMAC_KEY_SIZE 128U + +/** + * wd_digest_type - Algorithm type of digest + * algorithm should be offered by struct wd_digest_arg + */ +enum wd_digest_type { + WD_DIGEST_SM3, + WD_DIGEST_MD5, + WD_DIGEST_SHA1, + WD_DIGEST_SHA256, + WD_DIGEST_SHA224, + WD_DIGEST_SHA384, + WD_DIGEST_SHA512, + WD_DIGEST_SHA512_224, + WD_DIGEST_SHA512_256, + WD_DIGEST_AES_XCBC_MAC_96, + WD_DIGEST_AES_XCBC_PRF_128, + WD_DIGEST_AES_CMAC, + WD_DIGEST_AES_GMAC, + WD_DIGEST_TYPE_MAX, +}; + +enum wd_digest_mac_len { + WD_DIGEST_SM3_LEN = 32, + WD_DIGEST_MD5_LEN = 16, + WD_DIGEST_SHA1_LEN = 20, + WD_DIGEST_SHA256_LEN = 32, + WD_DIGEST_SHA224_LEN = 28, + WD_DIGEST_SHA384_LEN = 48, + WD_DIGEST_SHA512_LEN = 64, + WD_DIGEST_SHA512_224_LEN = 28, + WD_DIGEST_SHA512_256_LEN = 32, + WD_DIGEST_AES_XCBC_MAC_96_LEN = 12, + WD_DIGEST_AES_XCBC_PRF_128_LEN = 16, + WD_DIGEST_AES_CMAC_LEN = 16, + WD_DIGEST_AES_GMAC_LEN = 16, +}; + +/* User need to input full mac len in first and middle hash */ +enum wd_digest_mac_full_len { + WD_DIGEST_SM3_FULL_LEN = 32, + WD_DIGEST_MD5_FULL_LEN = 16, + WD_DIGEST_SHA1_FULL_LEN = 20, + WD_DIGEST_SHA256_FULL_LEN = 32, + WD_DIGEST_SHA224_FULL_LEN = 32, + WD_DIGEST_SHA384_FULL_LEN = 64, + WD_DIGEST_SHA512_FULL_LEN = 64, + WD_DIGEST_SHA512_224_FULL_LEN = 64, + WD_DIGEST_SHA512_256_FULL_LEN = 64, +}; + +/** + * wd_digest_mode - Mode of digest + * Mode should be offered by struct wd_digest_arg + * @WD_DIGEST_NORMAL: Normal digest + * @WD_DIGEST_HMAC: Keyed-Hashing, e.g. HMAC + */ +enum wd_digest_mode { + WD_DIGEST_NORMAL, + WD_DIGEST_HMAC, + WD_DIGEST_MODE_MAX, +}; + +/** + * wd_digest_sess_setup - Parameters which is used to allocate a digest session + * @alg: digest algorithm type, denoted by enum wd_digest_type + * @mode: digest algorithm mode, denoted by enum wd_digest_mode + */ +struct wd_digest_sess_setup { + enum wd_digest_type alg; + enum wd_digest_mode mode; + void *sched_param; +}; + +typedef void *wd_digest_cb_t(void *cb_param); + +/** + * struct wd_digest_arg - Parameters for per digest operation + * @in: input data address + * @out: output data address + * @in_bytes: input data size + * @out_bytes: output data size + * @out_buf_bytes: actual output buffer size + * @iv: input iv data addrss for AES_GMAC + * @iv_bytes: input iv data size + * @has_next: is there next data block + * @cb: callback function for async mode + * @cb_param: pointer of callback parameter + * + * Note: If there is a alg selected in session, alg below will be ignore + * otherwise, alg here will be used. Same as mode below. + * + * fix me: for hmac, seems we need *key also? + */ +struct wd_digest_req { + union { + void *in; + struct wd_datalist *list_in; + }; + void *out; + __u32 in_bytes; + __u32 out_bytes; + __u32 out_buf_bytes; + __u8 *iv; + __u32 iv_bytes; + __u16 state; + __u16 has_next; + __u8 data_fmt; + wd_digest_cb_t *cb; + void *cb_param; +}; + +struct wd_cb_tag { + void *ctx; /* user: context or other user relatives */ + void *tag; /* to store user tag */ + int ctx_id; /* user id: context ID or other user identifier */ +}; + +/* Digest tag format */ +struct wd_digest_tag { + struct wd_cb_tag wd_tag; + __u64 long_data_len; + void *priv; +}; + +int wd_digest_init(struct wd_ctx_config *config, struct wd_sched *sched); +void wd_digest_uninit(void); + +/** + * wd_digest_alloc_sess() - Create a digest session. + * @setup: Hold the parameters which are used to allocate a digest session + * + * Return handler of allocated session. Return 0 if failing. + */ +handle_t wd_digest_alloc_sess(struct wd_digest_sess_setup *setup); + +/** + * wd_alg_digest_free_sess() - Free digest session. + * @h_sess: session handler which will be free + */ +void wd_digest_free_sess(handle_t h_sess); + +/** + * wd_do_digest_sync() - Do sync digest task. + * @h_sess: Session handler + * @req: Operation parameters. + */ +int wd_do_digest_sync(handle_t h_sess, struct wd_digest_req *req); + +/** + * wd_do_digest_async() - Do asynchronous digest task. + * @h_sess: Session handler + * @req: Operation parameters. + */ +int wd_do_digest_async(handle_t h_sess, struct wd_digest_req *req); + +/** + * wd_digest_set_key() - Set auth key to digest session. + * @h_sess: Session handler + * @key: Auth key addr + * @key_len: Auth key length + */ +int wd_digest_set_key(handle_t h_sess, const __u8 *key, __u32 key_len); + +/** + * wd_digest_poll() - Poll operation for asynchronous operation. + * @idx: index of ctx which will be polled. + * @expt: Count of polling + * @count: recv poll nums. + */ +int wd_digest_poll_ctx(__u32 idx, __u32 expt, __u32 *count); + +/** + * wd_digest_poll() - Poll operation for asynchronous operation. + * @expt: Count of polling. + * @count: recv poll nums. + */ +int wd_digest_poll(__u32 expt, __u32 *count); + +/** + * wd_digest_env_init() - Init ctx and schedule resources according to wd digest + * environment variables. + * + * @sched: user's custom scheduler. + * More information, please see docs/wd_environment_variable. + */ +int wd_digest_env_init(struct wd_sched *sched); + +/** + * wd_digest_env_uninit() - UnInit ctx and schedule resources set by above init. + */ +void wd_digest_env_uninit(void); + +/** + * wd_digest_ctx_num_init() - request ctx for digest. + * @node: numa node id. + * @type: operation type. + * @num: ctx number. + * @mode: 0: sync mode, 1: async mode + */ +int wd_digest_ctx_num_init(__u32 node, __u32 type, __u32 num, __u8 mode); + +/** + * wd_digest_ctx_num_uninit() - UnInit ctx and schedule resources + * set by above init. + * + */ +void wd_digest_ctx_num_uninit(void); + +/** + * wd_digest_get_env_param() - query the number of CTXs + * that meet input attributes. + * + * @node: numa node id. + * @type: operation type. + * @mode: 0: sync mode, 1: async mode + * @num: return ctx num. + * @is_enable return enable inner poll flag. + */ +int wd_digest_get_env_param(__u32 node, __u32 type, __u32 mode, + __u32 *num, __u8 *is_enable); + +#ifdef __cplusplus +} +#endif + +#endif /* __WD_DIGEST_H */ diff --git a/uadk/include/wd_ecc.h b/uadk/include/wd_ecc.h new file mode 100644 index 0000000..05a776d --- /dev/null +++ b/uadk/include/wd_ecc.h @@ -0,0 +1,531 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. + * Copyright 2020-2021 Linaro ltd. + */ + +#ifndef __WD_ECC_H +#define __WD_ECC_H + +#include +#include + +#include "wd.h" +#include "wd_alg_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct wd_ecc_in; +struct wd_ecc_out; +struct wd_ecc_key; + +typedef void (*wd_ecc_cb_t)(void *cb_param); +typedef int (*wd_rand)(char *out, size_t out_len, void *usr); +typedef int (*wd_hash)(const char *in, size_t in_len, + char *out, size_t out_len, void *usr); + +struct wd_ecc_point { + struct wd_dtb x; /* x affine coordinates */ + struct wd_dtb y; /* y affine coordinates */ +}; + +/* ECC operational types */ +enum wd_ecc_op_type { + WD_EC_OP_INVALID, /* invalid ecc operation */ + WD_ECXDH_GEN_KEY, /* ECDH/X448/X25519 generate pubkey */ + WD_ECXDH_COMPUTE_KEY, /* ECDH/X448/X25519 compute share key */ + WD_ECDSA_SIGN, /* ECDSA sign */ + WD_ECDSA_VERIFY, /* ECDSA verify */ + WD_SM2_SIGN, /* SM2 sign */ + WD_SM2_VERIFY, /* SM2 verify */ + WD_SM2_ENCRYPT, /* SM2 encrypt */ + WD_SM2_DECRYPT, /* SM2 decrypt */ + WD_SM2_KG, /* SM2 key generate */ + WD_EC_OP_MAX +}; + +/* ECC operational types */ +enum wd_ecc_curve_id { + WD_SECP128R1 = 0x10, /* SECG 128 bit prime field */ + WD_SECP192K1 = 0x11, /* SECG 192 bit prime field */ + WD_SECP224R1 = 0x12, /* SECG 224 bit prime field */ + WD_SECP256K1 = 0x13, /* SECG 256 bit prime field */ + WD_BRAINPOOLP320R1 = 0x14, /* RFC5639 320 bit prime field */ + WD_BRAINPOOLP384R1 = 0x15, /* RFC5639 384 bit prime field */ + WD_SECP384R1 = 0x16, /* SECG 384 bit prime field */ + WD_SECP521R1 = 0x17, /* NIST/SECG 521 bit prime field */ +}; + +/* ECC hash callback func types */ +enum wd_ecc_hash_type { + WD_HASH_SM3, + WD_HASH_SHA1, + WD_HASH_SHA224, + WD_HASH_SHA256, + WD_HASH_SHA384, + WD_HASH_SHA512, + WD_HASH_MD4, + WD_HASH_MD5, + WD_HASH_MAX +}; + +struct wd_ecc_curve { + struct wd_dtb p; /* Prime field p */ + struct wd_dtb a; /* Elliptic curve equation a parameter */ + struct wd_dtb b; /* Elliptic curve equation b parameter */ + struct wd_ecc_point g; /* Elliptic curve G point */ + struct wd_dtb n; /* Elliptic curve order */ +}; + +enum wd_ecc_curve_cfg_type { + WD_CV_CFG_ID, /* set curve param by denote curve ID */ + WD_CV_CFG_PARAM /* set curve param by denote curve param */ +}; + +struct wd_ecc_curve_cfg { + __u32 type; /* denoted by enum wd_ecc_curve_cfg_type */ + union { + enum wd_ecc_curve_id id; /* if WD_CV_CFG_ID */ + struct wd_ecc_curve *pparam; /* if WD_CV_CFG_PARAM */ + } cfg; + __u8 resv[4]; /* reserve */ +}; + +struct wd_rand_mt { + wd_rand cb; /* rand callback */ + void *usr; /* user private param */ +}; + +struct wd_hash_mt { + wd_hash cb; /* rand callback */ + void *usr; /* user private param */ + __u8 type; /* hash type, denoted by enum wd_ecc_hash_type */ + __u8 rsv[3]; /* reserve */ +}; + +/* ECC context setting up input parameters from user */ +struct wd_ecc_sess_setup { + /* + * Ec algorithm name, + * find "/sys/class/uacce/hisi_hpre-xx/algorithms" + */ + const char *alg; + __u16 key_bits; /* ECC key bits */ + struct wd_ecc_curve_cfg cv; /* curve config denoted by user */ + struct wd_rand_mt rand; /* rand method from user */ + struct wd_hash_mt hash; /* hash method from user */ + void *sched_param; +}; + +struct wd_ecc_req { + void *src; /* ecc operation input address */ + void *dst; /* ecc operation output address */ + __u32 src_bytes; /* ecc operation input bytes */ + __u32 dst_bytes; /* ecc operation output bytes */ + wd_ecc_cb_t cb; + void *cb_param; + int status; /* ecc operation status */ + __u8 data_fmt; /* data format denoted by enum wd_buff_type */ + __u8 op_type; /* ecc operation type */ +}; + +/** + * wd_ecc_get_key_bits() - Get key width. + * @sess: Session handler. + * Return key bit width, 0 otherwise. + */ +int wd_ecc_get_key_bits(handle_t sess); + +/** + * wd_ecc_get_ecc_key() - Get ecc key param handle. + * @sess: Session handler. + * Return key param handle, NULL otherwise. + */ +struct wd_ecc_key *wd_ecc_get_key(handle_t sess); + +/** + * wd_ecc_set_ecc_prikey() - Set ecc private key param. + * @ecc_key: Ecc key param handle. + * @prikey: Private key param. + * Return 0, less than 0 otherwise. + */ +int wd_ecc_set_prikey(struct wd_ecc_key *ecc_key, + struct wd_dtb *prikey); + + +/** + * wd_ecc_get_ecc_prikey() - Get ecc private key param. + * @ecc_key: Ecc key param handle. + * @prikey: Output private key param pointer. + * Return 0, less than 0 otherwise. + */ +int wd_ecc_get_prikey(struct wd_ecc_key *ecc_key, + struct wd_dtb **prikey); + +/** + * wd_ecc_set_ecc_pubkey() - Set ecc public key param. + * @ecc_key: Ecc key param handle. + * @pubkey: Public key param. + * Return 0, less than 0 otherwise. + */ +int wd_ecc_set_pubkey(struct wd_ecc_key *ecc_key, + struct wd_ecc_point *pubkey); + +/** + * wd_ecc_get_pubkey() - Get ecc public key param. + * @ecc_key: Ecc key param handle. + * @pubkey: Output public key param pointer. + * Return 0, less than 0 otherwise. + */ +int wd_ecc_get_pubkey(struct wd_ecc_key *ecc_key, + struct wd_ecc_point **pubkey); + +/** + * wd_ecc_del_in() - Delete ecc input param handle. + * @sess: Session handler. + * @in: input param handle. + */ +void wd_ecc_del_in(handle_t sess, struct wd_ecc_in *in); + +/** + * wd_ecc_del_out() - Delete ecc output param handle. + * @sess: Session handler. + * @out: output param handle. + */ +void wd_ecc_del_out(handle_t sess, struct wd_ecc_out *out); + +/** + * wd_ecc_get_prikey_params() - Get private key params. + * @key: Ecc key param handle. + * @p: curve param p pointer. + * @a: curve param a pointer. + * @b: curve param b pointer. + * @n: curve param n pointer. + * @g: curve param g pointer. + * @d: private pointer. + */ +void wd_ecc_get_prikey_params(struct wd_ecc_key *key, + struct wd_dtb **p, struct wd_dtb **a, + struct wd_dtb **b, struct wd_dtb **n, + struct wd_ecc_point **g, + struct wd_dtb **d); + +/** + * wd_ecc_get_pubkey_params() - Get public key params. + * @key: Ecc key param handle. + * @p: curve param p pointer. + * @a: curve param a pointer. + * @b: curve param b pointer. + * @n: curve param n pointer. + * @g: curve param g pointer. + * @pub: public key pointer. + */ +void wd_ecc_get_pubkey_params(struct wd_ecc_key *key, + struct wd_dtb **p, struct wd_dtb **a, + struct wd_dtb **b, struct wd_dtb **n, + struct wd_ecc_point **g, + struct wd_ecc_point **pub); + +/* APIs For ECXDH gen/comp */ + +/** + * wd_ecxdh_new_in() - Create ECXDH input params handle in compute shared key. + * @sess: Session handler. + * @in: input param used for compute shared key. + * Return input params handle, NULL otherwise. + */ +struct wd_ecc_in *wd_ecxdh_new_in(handle_t sess, struct wd_ecc_point *in); + +/** + * wd_ecxdh_new_out() - Create ECXDH output params handle. + * @sess: Session handler. + * Return output params handle, NULL otherwise. + */ +struct wd_ecc_out *wd_ecxdh_new_out(handle_t sess); + +/** + * wd_ecxdh_get_out_params() - Get ECXDH output params. + * @out: Output param handle. + * @pbk: ECXDH ouput param. + */ +void wd_ecxdh_get_out_params(struct wd_ecc_out *out, struct wd_ecc_point **pbk); + + +/* APIs For SM2 sign/verf/enc/dec/kg */ + +/** + * wd_sm2_new_sign_in() - Create sm2 sign input params handle. + * @sess: Session handler. + * @e: sign input param digest or plaintext by is_dgst param. + * @k: sign input param random. + * @id: sign input param user identity ID. + * Return input params handle, NULL otherwise. + */ +struct wd_ecc_in *wd_sm2_new_sign_in(handle_t sess, + struct wd_dtb *e, + struct wd_dtb *k, + struct wd_dtb *id, + __u8 is_dgst); + +/** + * wd_sm2_new_verf_in() - Create sm2 verification input params handle. + * @sess: Session handler. + * @e: verification input param digest or plaintext by is_dgst param. + * @r: sign input param r. + * @s: sign input param s. + * Return input params handle, NULL otherwise. + */ +struct wd_ecc_in *wd_sm2_new_verf_in(handle_t sess, + struct wd_dtb *e, + struct wd_dtb *r, + struct wd_dtb *s, + struct wd_dtb *id, + __u8 is_dgst); + +/** + * wd_sm2_new_enc_in() - Create sm2 encrypt input params handle. + * @sess: Session handler. + * @k: encrypt input param random. + * @plaintext: encrypt input param plaintext. + * Return input params handle, NULL otherwise. + */ +struct wd_ecc_in *wd_sm2_new_enc_in(handle_t sess, + struct wd_dtb *k, + struct wd_dtb *plaintext); +/** + * wd_sm2_new_dec_in() - Create sm2 decrypt input params handle. + * @sess: Session handler. + * @c1: decrypt input param C1. + * @c2: decrypt input param C2. + * @c3: decrypt input param C3. + * Return input params handle, NULL otherwise. + */ +struct wd_ecc_in *wd_sm2_new_dec_in(handle_t sess, + struct wd_ecc_point *c1, + struct wd_dtb *c2, + struct wd_dtb *c3); + +/** + * wd_sm2_new_sign_out() - Create sm2 sign output params handle. + * @sess: Session handler. + * Return output params handle, NULL otherwise. + */ +struct wd_ecc_out *wd_sm2_new_sign_out(handle_t sess); + +/** + * wd_sm2_new_enc_out() - Create sm2 encrypt output params handle. + * @sess: Session handler. + * @plaintext_len: plaintext bytes. + * Return output params handle, NULL otherwise. + */ +struct wd_ecc_out *wd_sm2_new_enc_out(handle_t sess, + __u32 plaintext_len); + +/** + * wd_sm2_new_dec_out() - Create sm2 decrypt output params handle. + * @sess: Session handler. + * @plaintext_len: plaintext bytes. + * Return output params handle, NULL otherwise. + */ +struct wd_ecc_out *wd_sm2_new_dec_out(handle_t sess, + __u32 plaintext_len); + +/** + * wd_sm2_new_kg_out() - Create sm2 key generate output params handle. + * @sess: Session handler. + * Return output params handle. + */ +struct wd_ecc_out *wd_sm2_new_kg_out(handle_t sess); + +/** + * wd_sm2_get_sign_out_params() - Get sm2 sign output params. + * @out: Output param handle. + * @r: sm2 sign ouput param r. + * @s: sm2 sign ouput param s. + */ +void wd_sm2_get_sign_out_params(struct wd_ecc_out *out, + struct wd_dtb **r, + struct wd_dtb **s); +/** + * wd_sm2_get_kg_out_params() - Get sm2 key generate output params. + * @out: output param handle. + * @privkey: output private key. + * @pubkey: output public key. + */ +void wd_sm2_get_kg_out_params(struct wd_ecc_out *out, + struct wd_dtb **privkey, + struct wd_ecc_point **pubkey); + +/** + * wd_sm2_get_enc_out_params() - Get sm2 encrypt output params. + * @out: output param handle. + * @c1: encrypt output C1. + * @c2: encrypt output C2. + * @c3: encrypt output C3. + */ +void wd_sm2_get_enc_out_params(struct wd_ecc_out *out, + struct wd_ecc_point **c1, + struct wd_dtb **c2, + struct wd_dtb **c3); + +/** + * wd_sm2_get_dec_out_params() - Get sm2 decrypt output params. + * @out: output param handle. + * @plaintext: decrypt output plaintext. + */ +void wd_sm2_get_dec_out_params(struct wd_ecc_out *out, + struct wd_dtb **plaintext); + +/* APIs For ECDSA sign/verf */ + +/** + * wd_ecdsa_new_sign_in() - Create ecdsa sign input params handle. + * @sess: Session handler. + * @dgst: sign input param digest. + * @k: sign input param random. + * Return input params handle, NULL otherwise. + */ +struct wd_ecc_in *wd_ecdsa_new_sign_in(handle_t sess, + struct wd_dtb *dgst, + struct wd_dtb *k); + +/** + * wd_ecdsa_new_verf_in() - Create ecdsa verification input params handle. + * @sess: Session handler. + * @dgst: verification input param digest. + * @r: sign input param r. + * @s: sign input param s. + * Return input params handle, NULL otherwise. + */ +struct wd_ecc_in *wd_ecdsa_new_verf_in(handle_t sess, + struct wd_dtb *dgst, + struct wd_dtb *r, + struct wd_dtb *s); + +/** + * wd_ecdsa_new_sign_out() - Create ecdsa sign output params handle. + * @sess: Session handler. + * Return output params handle, NULL otherwise. + */ +struct wd_ecc_out *wd_ecdsa_new_sign_out(handle_t sess); + +/** + * wd_ecdsa_get_sign_out_params() - Get ecdsa sign output params. + * @out: Output param handle. + * @r: sign ouput param r. + * @s: sign ouput param s. + */ +void wd_ecdsa_get_sign_out_params(struct wd_ecc_out *out, + struct wd_dtb **r, + struct wd_dtb **s); + +/** + * wd_ecc_init() - Initialise ctx configuration and scheduler. + * @ config: User defined ctx configuration. + * @ sched: User defined scheduler. + */ +int wd_ecc_init(struct wd_ctx_config *config, struct wd_sched *sched); + +/** + * wd_ecc_uninit() - Un-initialise ctx configuration and scheduler. + */ +void wd_ecc_uninit(void); + + +/** + * wd_ecc_alloc_sess() - Allocate a wd ecc session. + * @setup: Parameters to setup this session. + */ +handle_t wd_ecc_alloc_sess(struct wd_ecc_sess_setup *setup); + +/** + * wd_ecc_free_sess() - Free a wd ecc session. + * @ sess: The sess to be freed. + */ +void wd_ecc_free_sess(handle_t sess); + +/** + * wd_ecc_poll() - Poll finished request. + * + * This function will call poll_policy function which is registered to wd ecc + * by user. + */ +int wd_ecc_poll(__u32 expt, __u32 *count); + +/** + * wd_do_ecc() - Send a sync eccression request. + * @h_sess: The session which request will be sent to. + * @req: Request. + */ +int wd_do_ecc_sync(handle_t h_sess, struct wd_ecc_req *req); + +/** + * wd_do_ecc_async() - Send an async eccression request. + * @sess: The session which request will be sent to. + * @req: Request. + */ +int wd_do_ecc_async(handle_t sess, struct wd_ecc_req *req); + + +/** + * wd_ecc_poll_ctx() - Poll a ctx. + * @pos: The ctx idx which will be polled. + * @expt: Max number of requests to poll. If 0, polled all finished + * requests in this ctx. + * @count: The number of polled requests. + * Return: 0-succ others-fail. + * + * This is a help function which can be used by user's poll_policy function. + * User defines polling policy in poll_policiy, when it needs to poll a + * specific ctx, this function should be used. + */ +int wd_ecc_poll_ctx(__u32 idx, __u32 expt, __u32 *count); + +/** + * wd_ecc_env_init() - Init ctx and schedule resources according to wd ecc + * environment variables. + * + * @sched: user's custom scheduler. + * More information, please see docs/wd_environment_variable. + */ +int wd_ecc_env_init(struct wd_sched *sched); + +/** + * wd_ecc_env_uninit() - UnInit ctx and schedule resources set by above init. + */ +void wd_ecc_env_uninit(void); + +/** + * wd_ecc_ctx_num_init() - request ctx for ecc. + * @node: numa node id. + * @type: operation type. + * @num: ctx number. + * @mode: 0: sync mode, 1: async mode + */ +int wd_ecc_ctx_num_init(__u32 node, __u32 type, __u32 num, __u8 mode); + +/** + * wd_ecc_ctx_num_uninit() - UnInit ctx and schedule resources + * set by above init. + * + */ +void wd_ecc_ctx_num_uninit(void); + +/** + * wd_ecc_get_env_param() - query the number of CTXs that meet input attributes. + * @node: numa node id. + * @type: operation type. + * @mode: 0: sync mode, 1: async mode + * @num: return ctx num. + * @is_enable return enable inner poll flag. + */ +int wd_ecc_get_env_param(__u32 node, __u32 type, __u32 mode, + __u32 *num, __u8 *is_enable); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/uadk/include/wd_ecc_curve.h b/uadk/include/wd_ecc_curve.h new file mode 100644 index 0000000..20b017a --- /dev/null +++ b/uadk/include/wd_ecc_curve.h @@ -0,0 +1,353 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. + * Copyright 2020-2021 Linaro ltd. + */ + +#ifndef __WD_ECC_CURVE_H +#define __WD_ECC_CURVE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* big-endian ************************/ +#define X25519_256_PARAM {\ + /* p = (2 ^ 255 - 19) */\ + 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xed,\ + /* a = (486662 - 2) / 4 = 121665 */\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xDB, 0x41,\ + /* b : only for format, no mean */\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + /* x */\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,\ + /* y : only for format, no mean */\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + /* order : only for format, no mean */\ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ +} + +/********************* big-endian ************************/ +#define X448_448_PARAM {\ + /* p = (2 ^ 448 - 2 ^ 224 - 1) */\ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + /* a = (156326 - 2) / 4 = 39081 */\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0xA9,\ + /* b : only for format, no mean */\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + /* x */\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,\ + /* y : only for format, no mean */\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + /* order : only for format, no mean */\ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ +} + +#define SECG_P128_R1_PARAM {\ + /* p */\ + 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFF,\ + /* a */\ + 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFC,\ + /* b */\ + 0xE8, 0x75, 0x79, 0xC1, 0x10, 0x79, 0xF4, 0x3D, 0xD8, 0x24, 0x99, 0x3C,\ + 0x2C, 0xEE, 0x5E, 0xD3,\ + /* x */\ + 0x16, 0x1F, 0xF7, 0x52, 0x8B, 0x89, 0x9B, 0x2D, 0x0C, 0x28, 0x60, 0x7C,\ + 0xA5, 0x2C, 0x5B, 0x86,\ + /* y */\ + 0xcf, 0x5a, 0xc8, 0x39, 0x5b, 0xaf, 0xeb, 0x13, 0xc0, 0x2d, 0xa2, 0x92,\ + 0xdd, 0xed, 0x7a, 0x83,\ + /* order */\ + 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x75, 0xA3, 0x0D, 0x1B,\ + 0x90, 0x38, 0xA1, 0x15,\ +} + +#define SECG_P192_K1_PARAM {\ + /* p */\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xEE, 0x37,\ + /* a */\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + /* b */\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,\ + /* x */\ + 0xDB, 0x4F, 0xF1, 0x0E, 0xC0, 0x57, 0xE9, 0xAE, 0x26, 0xB0, 0x7D, 0x02,\ + 0x80, 0xB7, 0xF4, 0x34, 0x1D, 0xA5, 0xD1, 0xB1, 0xEA, 0xE0, 0x6C, 0x7D,\ + /* y */\ + 0x9b, 0x2f, 0x2f, 0x6d, 0x9c, 0x56, 0x28, 0xa7, 0x84, 0x41, 0x63, 0xd0,\ + 0x15, 0xbe, 0x86, 0x34, 0x40, 0x82, 0xaa, 0x88, 0xd9, 0x5e, 0x2f, 0x9d,\ + /* order */\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,\ + 0x26, 0xF2, 0xFC, 0x17, 0x0F, 0x69, 0x46, 0x6A, 0x74, 0xDE, 0xFD, 0x8D\ +} + +#define SECG_P224_R1_PARAM {\ + /* p */\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x01,\ + /* a */\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFE,\ + /* b */\ + 0xB4, 0x05, 0x0A, 0x85, 0x0C, 0x04, 0xB3, 0xAB, 0xF5, 0x41, 0x32, 0x56,\ + 0x50, 0x44, 0xB0, 0xB7, 0xD7, 0xBF, 0xD8, 0xBA, 0x27, 0x0B, 0x39, 0x43,\ + 0x23, 0x55, 0xFF, 0xB4,\ + /* x */\ + 0xB7, 0x0E, 0x0C, 0xBD, 0x6B, 0xB4, 0xBF, 0x7F, 0x32, 0x13, 0x90, 0xB9,\ + 0x4A, 0x03, 0xC1, 0xD3, 0x56, 0xC2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xD6,\ + 0x11, 0x5C, 0x1D, 0x21,\ + /* y */\ + 0xBD, 0x37, 0x63, 0x88, 0xB5, 0xF7, 0x23, 0xFB, 0x4C, 0x22, 0xDF, 0xE6,\ + 0xCD, 0x43, 0x75, 0xA0, 0x5A, 0x07, 0x47, 0x64, 0x44, 0xD5, 0x81, 0x99,\ + 0x85, 0x00, 0x7E, 0x34,\ + /* order */\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xFF, 0xFF, 0x16, 0xA2, 0xE0, 0xB8, 0xF0, 0x3E, 0x13, 0xDD, 0x29, 0x45, \ + 0x5C, 0x5C, 0x2A, 0x3D\ +} + +#define SECG_P256_K1_PARAM {\ + /* p */\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x2F,\ + /* a */\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + /* b */\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,\ + /* x */\ + 0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95,\ + 0xCE, 0x87, 0x0B, 0x07, 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9,\ + 0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98,\ + /* y */\ + 0x48, 0x3a, 0xda, 0x77, 0x26, 0xa3, 0xc4, 0x65, 0x5d, 0xa4, 0xfb, 0xfc,\ + 0x0e, 0x11, 0x08, 0xa8, 0xfd, 0x17, 0xb4, 0x48, 0xa6, 0x85, 0x54, 0x19,\ + 0x9c, 0x47, 0xd0, 0x8f, 0xfb, 0x10, 0xd4, 0xb8,\ + /* order */\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B,\ + 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41\ +} + +#define BRAINPOOL_P320_R1_PARAM {\ + /* p */\ + 0xD3, 0x5E, 0x47, 0x20, 0x36, 0xBC, 0x4F, 0xB7, 0xE1, 0x3C, 0x78, 0x5E,\ + 0xD2, 0x01, 0xE0, 0x65, 0xF9, 0x8F, 0xCF, 0xA6, 0xF6, 0xF4, 0x0D, 0xEF,\ + 0x4F, 0x92, 0xB9, 0xEC, 0x78, 0x93, 0xEC, 0x28, 0xFC, 0xD4, 0x12, 0xB1,\ + 0xF1, 0xB3, 0x2E, 0x27,\ + /* a */\ + 0x3E, 0xE3, 0x0B, 0x56, 0x8F, 0xBA, 0xB0, 0xF8, 0x83, 0xCC, 0xEB, 0xD4,\ + 0x6D, 0x3F, 0x3B, 0xB8, 0xA2, 0xA7, 0x35, 0x13, 0xF5, 0xEB, 0x79, 0xDA,\ + 0x66, 0x19, 0x0E, 0xB0, 0x85, 0xFF, 0xA9, 0xF4, 0x92, 0xF3, 0x75, 0xA9,\ + 0x7D, 0x86, 0x0E, 0xB4,\ + /* b */\ + 0x52, 0x08, 0x83, 0x94, 0x9D, 0xFD, 0xBC, 0x42, 0xD3, 0xAD, 0x19, 0x86,\ + 0x40, 0x68, 0x8A, 0x6F, 0xE1, 0x3F, 0x41, 0x34, 0x95, 0x54, 0xB4, 0x9A,\ + 0xCC, 0x31, 0xDC, 0xCD, 0x88, 0x45, 0x39, 0x81, 0x6F, 0x5E, 0xB4, 0xAC,\ + 0x8F, 0xB1, 0xF1, 0xA6,\ + /* x */\ + 0x43, 0xBD, 0x7E, 0x9A, 0xFB, 0x53, 0xD8, 0xB8, 0x52, 0x89, 0xBC, 0xC4,\ + 0x8E, 0xE5, 0xBF, 0xE6, 0xF2, 0x01, 0x37, 0xD1, 0x0A, 0x08, 0x7E, 0xB6,\ + 0xE7, 0x87, 0x1E, 0x2A, 0x10, 0xA5, 0x99, 0xC7, 0x10, 0xAF, 0x8D, 0x0D,\ + 0x39, 0xE2, 0x06, 0x11,\ + /* y */\ + 0x14, 0xFD, 0xD0, 0x55, 0x45, 0xEC, 0x1C, 0xC8, 0xAB, 0x40, 0x93, 0x24,\ + 0x7F, 0x77, 0x27, 0x5E, 0x07, 0x43, 0xFF, 0xED, 0x11, 0x71, 0x82, 0xEA,\ + 0xA9, 0xC7, 0x78, 0x77, 0xAA, 0xAC, 0x6A, 0xC7, 0xD3, 0x52, 0x45, 0xD1,\ + 0x69, 0x2E, 0x8E, 0xE1,\ + /* order */\ + 0xD3, 0x5E, 0x47, 0x20, 0x36, 0xBC, 0x4F, 0xB7, 0xE1, 0x3C, 0x78, 0x5E,\ + 0xD2, 0x01, 0xE0, 0x65, 0xF9, 0x8F, 0xCF, 0xA5, 0xB6, 0x8F, 0x12, 0xA3,\ + 0x2D, 0x48, 0x2E, 0xC7, 0xEE, 0x86, 0x58, 0xE9, 0x86, 0x91, 0x55, 0x5B,\ + 0x44, 0xC5, 0x93, 0x11\ +} + +#define BRAINPOOL_P384_R1_PARAM {\ + /* p */\ + 0x8C, 0xB9, 0x1E, 0x82, 0xA3, 0x38, 0x6D, 0x28, 0x0F, 0x5D, 0x6F, 0x7E,\ + 0x50, 0xE6, 0x41, 0xDF, 0x15, 0x2F, 0x71, 0x09, 0xED, 0x54, 0x56, 0xB4,\ + 0x12, 0xB1, 0xDA, 0x19, 0x7F, 0xB7, 0x11, 0x23, 0xAC, 0xD3, 0xA7, 0x29,\ + 0x90, 0x1D, 0x1A, 0x71, 0x87, 0x47, 0x00, 0x13, 0x31, 0x07, 0xEC, 0x53,\ + /* a */\ + 0x7B, 0xC3, 0x82, 0xC6, 0x3D, 0x8C, 0x15, 0x0C, 0x3C, 0x72, 0x08, 0x0A,\ + 0xCE, 0x05, 0xAF, 0xA0, 0xC2, 0xBE, 0xA2, 0x8E, 0x4F, 0xB2, 0x27, 0x87,\ + 0x13, 0x91, 0x65, 0xEF, 0xBA, 0x91, 0xF9, 0x0F, 0x8A, 0xA5, 0x81, 0x4A,\ + 0x50, 0x3A, 0xD4, 0xEB, 0x04, 0xA8, 0xC7, 0xDD, 0x22, 0xCE, 0x28, 0x26,\ + /* b */\ + 0x04, 0xA8, 0xC7, 0xDD, 0x22, 0xCE, 0x28, 0x26, 0x8B, 0x39, 0xB5, 0x54,\ + 0x16, 0xF0, 0x44, 0x7C, 0x2F, 0xB7, 0x7D, 0xE1, 0x07, 0xDC, 0xD2, 0xA6,\ + 0x2E, 0x88, 0x0E, 0xA5, 0x3E, 0xEB, 0x62, 0xD5, 0x7C, 0xB4, 0x39, 0x02,\ + 0x95, 0xDB, 0xC9, 0x94, 0x3A, 0xB7, 0x86, 0x96, 0xFA, 0x50, 0x4C, 0x11,\ + /* x */\ + 0x1D, 0x1C, 0x64, 0xF0, 0x68, 0xCF, 0x45, 0xFF, 0xA2, 0xA6, 0x3A, 0x81,\ + 0xB7, 0xC1, 0x3F, 0x6B, 0x88, 0x47, 0xA3, 0xE7, 0x7E, 0xF1, 0x4F, 0xE3,\ + 0xDB, 0x7F, 0xCA, 0xFE, 0x0C, 0xBD, 0x10, 0xE8, 0xE8, 0x26, 0xE0, 0x34,\ + 0x36, 0xD6, 0x46, 0xAA, 0xEF, 0x87, 0xB2, 0xE2, 0x47, 0xD4, 0xAF, 0x1E,\ + /* y */\ + 0x8A, 0xBE, 0x1D, 0x75, 0x20, 0xF9, 0xC2, 0xA4, 0x5C, 0xB1, 0xEB, 0x8E,\ + 0x95, 0xCF, 0xD5, 0x52, 0x62, 0xB7, 0x0B, 0x29, 0xFE, 0xEC, 0x58, 0x64,\ + 0xE1, 0x9C, 0x05, 0x4F, 0xF9, 0x91, 0x29, 0x28, 0x0E, 0x46, 0x46, 0x21,\ + 0x77, 0x91, 0x81, 0x11, 0x42, 0x82, 0x03, 0x41, 0x26, 0x3C, 0x53, 0x15,\ + /* order */\ + 0x8C, 0xB9, 0x1E, 0x82, 0xA3, 0x38, 0x6D, 0x28, 0x0F, 0x5D, 0x6F, 0x7E,\ + 0x50, 0xE6, 0x41, 0xDF, 0x15, 0x2F, 0x71, 0x09, 0xED, 0x54, 0x56, 0xB3,\ + 0x1F, 0x16, 0x6E, 0x6C, 0xAC, 0x04, 0x25, 0xA7, 0xCF, 0x3A, 0xB6, 0xAF,\ + 0x6B, 0x7F, 0xC3, 0x10, 0x3B, 0x88, 0x32, 0x02, 0xE9, 0x04, 0x65, 0x65\ +} + +#define SECG_P384_R1_PARAM {\ + /* p */\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,\ + /* a */\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFC,\ + /* b */\ + 0xB3, 0x31, 0x2F, 0xA7, 0xE2, 0x3E, 0xE7, 0xE4, 0x98, 0x8E, 0x05, 0x6B,\ + 0xE3, 0xF8, 0x2D, 0x19, 0x18, 0x1D, 0x9C, 0x6E, 0xFE, 0x81, 0x41, 0x12,\ + 0x03, 0x14, 0x08, 0x8F, 0x50, 0x13, 0x87, 0x5A, 0xC6, 0x56, 0x39, 0x8D,\ + 0x8A, 0x2E, 0xD1, 0x9D, 0x2A, 0x85, 0xC8, 0xED, 0xD3, 0xEC, 0x2A, 0xEF,\ + /* x */\ + 0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37, 0x8E, 0xB1, 0xC7, 0x1E,\ + 0xF3, 0x20, 0xAD, 0x74, 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98,\ + 0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38, 0x55, 0x02, 0xF2, 0x5D,\ + 0xBF, 0x55, 0x29, 0x6C, 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7,\ + /* y */\ + 0x36, 0x17, 0xDE, 0x4A, 0x96, 0x26, 0x2C, 0x6F, 0x5D, 0x9E, 0x98, 0xBF,\ + 0x92, 0x92, 0xDC, 0x29, 0xF8, 0xF4, 0x1D, 0xBD, 0x28, 0x9A, 0x14, 0x7C,\ + 0xE9, 0xDA, 0x31, 0x13, 0xB5, 0xF0, 0xB8, 0xC0, 0x0A, 0x60, 0xB1, 0xCE,\ + 0x1D, 0x7E, 0x81, 0x9D, 0x7A, 0x43, 0x1D, 0x7C, 0x90, 0xEA, 0x0E, 0x5F,\ + /* order */\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xC7, 0x63, 0x4D, 0x81, 0xF4, 0x37, 0x2D, 0xDF, 0x58, 0x1A, 0x0D, 0xB2,\ + 0x48, 0xB0, 0xA7, 0x7A, 0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73,\ +} + +#define SECG_P521_R1_PARAM {\ + /* p */\ + 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + /* a */\ + 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC,\ + /* b */\ + 0x00, 0x51, 0x95, 0x3E, 0xB9, 0x61, 0x8E, 0x1C, 0x9A, 0x1F, 0x92, 0x9A,\ + 0x21, 0xA0, 0xB6, 0x85, 0x40, 0xEE, 0xA2, 0xDA, 0x72, 0x5B, 0x99, 0xB3,\ + 0x15, 0xF3, 0xB8, 0xB4, 0x89, 0x91, 0x8E, 0xF1, 0x09, 0xE1, 0x56, 0x19,\ + 0x39, 0x51, 0xEC, 0x7E, 0x93, 0x7B, 0x16, 0x52, 0xC0, 0xBD, 0x3B, 0xB1,\ + 0xBF, 0x07, 0x35, 0x73, 0xDF, 0x88, 0x3D, 0x2C, 0x34, 0xF1, 0xEF, 0x45,\ + 0x1F, 0xD4, 0x6B, 0x50, 0x3F, 0x00,\ + /* x */\ + 0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD, 0x9E, 0x3E,\ + 0xCB, 0x66, 0x23, 0x95, 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F,\ + 0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, 0x3D, 0xBA, 0xA1, 0x4B,\ + 0x5E, 0x77, 0xEF, 0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF,\ + 0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, 0x42, 0x9B, 0xF9, 0x7E,\ + 0x7E, 0x31, 0xC2, 0xE5, 0xBD, 0x66,\ + /* y */\ + 0x01, 0x18, 0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b, 0xc0, 0x04, 0x5c, 0x8a,\ + 0x5f, 0xb4, 0x2c, 0x7d, 0x1b, 0xd9, 0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b,\ + 0x44, 0x68, 0x17, 0xaf, 0xbd, 0x17, 0x27, 0x3e, 0x66, 0x2c, 0x97, 0xee,\ + 0x72, 0x99, 0x5e, 0xf4, 0x26, 0x40, 0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad,\ + 0x07, 0x61, 0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72, 0xc2, 0x40, 0x88, 0xbe,\ + 0x94, 0x76, 0x9f, 0xd1, 0x66, 0x50,\ + /* order */\ + 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x51, 0x86,\ + 0x87, 0x83, 0xBF, 0x2F, 0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09,\ + 0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C, 0x47, 0xAE, 0xBB, 0x6F,\ + 0xB7, 0x1E, 0x91, 0x38, 0x64, 0x09\ +} + +#define SM2_P256_V1_PARAM {\ + /* p */\ + 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + /* a */\ + 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc,\ + /* b */\ + 0x28, 0xe9, 0xfa, 0x9e, 0x9d, 0x9f, 0x5e, 0x34, 0x4d, 0x5a, 0x9e, 0x4b,\ + 0xcf, 0x65, 0x09, 0xa7, 0xf3, 0x97, 0x89, 0xf5, 0x15, 0xab, 0x8f, 0x92,\ + 0xdd, 0xbc, 0xbd, 0x41, 0x4d, 0x94, 0x0e, 0x93,\ + /* x */\ + 0x32, 0xc4, 0xae, 0x2c, 0x1f, 0x19, 0x81, 0x19, 0x5f, 0x99, 0x04, 0x46,\ + 0x6a, 0x39, 0xc9, 0x94, 0x8f, 0xe3, 0x0b, 0xbf, 0xf2, 0x66, 0x0b, 0xe1,\ + 0x71, 0x5a, 0x45, 0x89, 0x33, 0x4c, 0x74, 0xc7,\ + /* y */\ + 0xbc, 0x37, 0x36, 0xa2, 0xf4, 0xf6, 0x77, 0x9c, 0x59, 0xbd, 0xce, 0xe3,\ + 0x6b, 0x69, 0x21, 0x53, 0xd0, 0xa9, 0x87, 0x7c, 0xc6, 0x2a, 0x47, 0x40,\ + 0x02, 0xdf, 0x32, 0xe5, 0x21, 0x39, 0xf0, 0xa0,\ + /* order */\ + 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + 0xff, 0xff, 0xff, 0xff, 0x72, 0x03, 0xdf, 0x6b, 0x21, 0xc6, 0x05, 0x2b,\ + 0x53, 0xbb, 0xf4, 0x09, 0x39, 0xd5, 0x41, 0x23,\ +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/uadk/include/wd_rsa.h b/uadk/include/wd_rsa.h new file mode 100644 index 0000000..ef7a12c --- /dev/null +++ b/uadk/include/wd_rsa.h @@ -0,0 +1,227 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. + * Copyright 2020-2021 Linaro ltd. + */ + +#ifndef __WD_RSA_H +#define __WD_RSA_H + +#include + +#include "wd.h" +#include "wd_alg_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define BYTE_BITS 8 +#define BYTE_BITS_SHIFT 3 +#define CRT_PARAMS_SZ(key_size) ((5 * (key_size)) >> 1) +#define CRT_GEN_PARAMS_SZ(key_size) ((7 * (key_size)) >> 1) +#define GEN_PARAMS_SZ(key_size) ((key_size) << 1) +#define CRT_PARAM_SZ(key_size) ((key_size) >> 1) +#define GET_NEGATIVE(val) (0 - (val)) + +typedef void (*wd_rsa_cb_t)(void *cb_param); + +struct wd_rsa_req { + void *src; /* rsa operation input address */ + void *dst; /* rsa operation output address */ + __u32 src_bytes; /* rsa operation input bytes */ + __u32 dst_bytes; /* rsa operation output bytes */ + wd_rsa_cb_t cb; + void *cb_param; + int status; /* rsa operation status */ + __u8 data_fmt; /* data format denoted by enum wd_buff_type */ + __u8 op_type; /* rsa operation type */ +}; + +struct wd_rsa_kg_in; /* rsa key generation input parameters */ +struct wd_rsa_kg_out; /* rsa key generation output parameters */ +struct wd_rsa_pubkey; /* rsa public key */ +struct wd_rsa_prikey; /* rsa private key */ + +/* RSA operational types */ +enum wd_rsa_op_type { + WD_RSA_INVALID, /* invalid rsa operation */ + WD_RSA_SIGN, /* RSA sign */ + WD_RSA_VERIFY, /* RSA verify */ + WD_RSA_GENKEY, /* RSA key generation */ +}; + +/* RSA key types */ +enum wd_rsa_key_type { + WD_RSA_INVALID_KEY, /* invalid rsa key type */ + WD_RSA_PUBKEY, /* rsa publick key type */ + WD_RSA_PRIKEY1, /* invalid rsa private common key type */ + WD_RSA_PRIKEY2, /* invalid rsa private CRT key type */ +}; + +/* RSA context setting up input parameters from user */ +struct wd_rsa_sess_setup { + __u16 key_bits; /* RSA key bits */ + bool is_crt; /* CRT mode or not */ + void *sched_param; +}; + +bool wd_rsa_is_crt(handle_t sess); +__u32 wd_rsa_get_key_bits(handle_t sess); +void wd_rsa_get_pubkey(handle_t sess, struct wd_rsa_pubkey **pubkey); +void wd_rsa_get_prikey(handle_t sess, struct wd_rsa_prikey **prikey); +int wd_rsa_set_pubkey_params(handle_t sess, struct wd_dtb *e, struct wd_dtb *n); +void wd_rsa_get_pubkey_params(struct wd_rsa_pubkey *pbk, + struct wd_dtb **e, struct wd_dtb **n); +int wd_rsa_set_prikey_params(handle_t sess, struct wd_dtb *d, struct wd_dtb *n); +void wd_rsa_get_prikey_params(struct wd_rsa_prikey *pvk, struct wd_dtb **d, + struct wd_dtb **n); +int wd_rsa_set_crt_prikey_params(handle_t sess, struct wd_dtb *dq, + struct wd_dtb *dp, + struct wd_dtb *qinv, + struct wd_dtb *q, + struct wd_dtb *p); +void wd_rsa_get_crt_prikey_params(struct wd_rsa_prikey *pvk, + struct wd_dtb **dq, struct wd_dtb **dp, + struct wd_dtb **qinv, struct wd_dtb **q, + struct wd_dtb **p); + +/* APIs For RSA key generate */ +struct wd_rsa_kg_in *wd_rsa_new_kg_in(handle_t sess, struct wd_dtb *e, + struct wd_dtb *p, struct wd_dtb *q); +void wd_rsa_del_kg_in(handle_t sess, struct wd_rsa_kg_in *ki); +void wd_rsa_get_kg_in_params(struct wd_rsa_kg_in *kin, struct wd_dtb *e, + struct wd_dtb *q, struct wd_dtb *p); + +struct wd_rsa_kg_out *wd_rsa_new_kg_out(handle_t sess); +void wd_rsa_del_kg_out(handle_t sess, struct wd_rsa_kg_out *kout); +void wd_rsa_get_kg_out_params(struct wd_rsa_kg_out *kout, + struct wd_dtb *d, + struct wd_dtb *n); +void wd_rsa_get_kg_out_crt_params(struct wd_rsa_kg_out *kout, + struct wd_dtb *qinv, + struct wd_dtb *dq, struct wd_dtb *dp); + +int wd_rsa_kg_in_data(struct wd_rsa_kg_in *ki, char **data); +int wd_rsa_kg_out_data(struct wd_rsa_kg_out *ko, char **data); +void wd_rsa_set_kg_out_crt_psz(struct wd_rsa_kg_out *kout, + size_t qinv_sz, + size_t dq_sz, + size_t dp_sz); +void wd_rsa_set_kg_out_psz(struct wd_rsa_kg_out *kout, + size_t d_sz, + size_t n_sz); + +/** + * wd_rsa_init() - Initialise ctx configuration and scheduler. + * @ config: User defined ctx configuration. + * @ sched: User defined scheduler. + */ +int wd_rsa_init(struct wd_ctx_config *config, struct wd_sched *sched); + +/** + * wd_rsa_uninit() - Un-initialise ctx configuration and scheduler. + */ +void wd_rsa_uninit(void); + + +/** + * wd_rsa_alloc_sess() - Allocate a wd rsa session. + * @setup: Parameters to setup this session. + */ +handle_t wd_rsa_alloc_sess(struct wd_rsa_sess_setup *setup); + +/** + * wd_rsa_free_sess() - Free a wd rsa session. + * @ sess: The sess to be freed. + */ +void wd_rsa_free_sess(handle_t sess); + +int wd_do_rsa_async(handle_t sess, struct wd_rsa_req *req); + +int wd_rsa_poll(__u32 expt, __u32 *count); + +/** + * wd_do_rsa() - Send a sync rsaression request. + * @h_sess: The session which request will be sent to. + * @req: Request. + */ +int wd_do_rsa_sync(handle_t h_sess, struct wd_rsa_req *req); + +/** + * wd_do_rsa_async() - Send an async rsaression request. + * @sess: The session which request will be sent to. + * @req: Request. + */ +int wd_do_rsa_async(handle_t sess, struct wd_rsa_req *req); + +/** + * wd_rsa_poll() - Poll finished request. + * + * This function will call poll_policy function which is registered to wd rsa + * by user. + +__u32 wd_rsa_poll(void); +*/ + + +/** + * wd_rsa_poll_ctx() - Poll a ctx. + * @pos: The ctx idx which will be polled. + * @expt: Max number of requests to poll. If 0, polled all finished + * requests in this ctx. + * @count: The number of polled requests. + * Return: 0-succ others-fail. + * + * This is a help function which can be used by user's poll_policy function. + * User defines polling policy in poll_policiy, when it needs to poll a + * specific ctx, this function should be used. + */ +int wd_rsa_poll_ctx(__u32 idx, __u32 expt, __u32 *count); + +/** + * wd_rsa_env_init() - Init ctx and schedule resources according to wd rsa + * environment variables. + * + * @sched: user's custom scheduler. + * More information, please see docs/wd_environment_variable. + */ +int wd_rsa_env_init(struct wd_sched *sched); + +/** + * wd_rsa_env_uninit() - UnInit ctx and schedule resources set by above init. + */ +void wd_rsa_env_uninit(void); + +/** + * wd_rsa_ctx_num_init() - request ctx for rsa. + * @node: numa node id. + * @type: operation type. + * @num: ctx number. + * @mode: 0: sync mode, 1: async mode + */ +int wd_rsa_ctx_num_init(__u32 node, __u32 type, __u32 num, __u8 mode); + +/** + * wd_rsa_ctx_num_uninit() - UnInit ctx and schedule resources + * set by above init. + * + */ +void wd_rsa_ctx_num_uninit(void); + +/** + * wd_rsa_get_env_param() - query the number of CTXs that meet input attributes. + * @node: numa node id. + * @type: operation type. + * @mode: 0: sync mode, 1: async mode + * @num: return ctx num. + * @is_enable return enable inner poll flag. + */ +int wd_rsa_get_env_param(__u32 node, __u32 type, __u32 mode, + __u32 *num, __u8 *is_enable); + +#ifdef __cplusplus +} +#endif + +#endif /* __WD_RSA_H */ diff --git a/uadk/include/wd_sched.h b/uadk/include/wd_sched.h new file mode 100644 index 0000000..2ae6103 --- /dev/null +++ b/uadk/include/wd_sched.h @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: Apache-2.0 +/* + * Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. + * Copyright 2020-2021 Linaro ltd. + */ + +#ifndef SCHED_SAMPLE_h +#define SCHED_SAMPLE_h +#include "wd_alg_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define INVALID_POS 0xFFFFFFFF + +/* The global policy type */ +enum sched_policy_type { + /* requests will be sent to ctxs one by one */ + SCHED_POLICY_RR = 0, + SCHED_POLICY_BUTT +}; + +struct sched_params { + int numa_id; + __u8 type; + __u8 mode; + __u32 begin; + __u32 end; +}; + +typedef int (*user_poll_func)(__u32 pos, __u32 expect, __u32 *count); + +/* + * wd_sched_rr_instance - Instante the schedule min region. + * @sched: The schedule instance + * @param: input schedule parameters + * + * The shedule indexed mode is NUMA -> MODE -> TYPE -> [BEGIN : END], + * then select one index from begin to end. + */ +int wd_sched_rr_instance(const struct wd_sched *sched, + struct sched_params *param); + +/** + * wd_sched_rr_alloc - Allocate a schedule instance. + * @sched_type: Reference sched_policy_type. + * @type_num: The service type num of user's service. For example, the zip + * include comp and decomp, type nume is two. + * @numa_num: The number of numa that the user needs. + * @func: The ctx poll function of user underlying operating. + * + */ +struct wd_sched *wd_sched_rr_alloc(__u8 sched_type, __u8 type_num, + __u16 numa_num, user_poll_func func); + +/** + * wd_sched_rr_release - Release schedule memory. + * @sched: The schedule which will be released. + */ +void wd_sched_rr_release(struct wd_sched *sched); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/uadk/include/wd_util.h b/uadk/include/wd_util.h new file mode 100644 index 0000000..83ac5f8 --- /dev/null +++ b/uadk/include/wd_util.h @@ -0,0 +1,380 @@ +// SPDX-License-Identifier: Apache-2.0 +/* + * Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. + * Copyright 2020-2021 Linaro ltd. + */ + +#ifndef __WD_UTIL_H +#define __WD_UTIL_H + +#include +#include +#include +#include +#include "wd_alg_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define FOREACH_NUMA(i, config, config_numa) \ + for ((i) = 0, (config_numa) = (config)->config_per_numa; \ + (i) < (config)->numa_num; (config_numa)++, (i)++) + +struct wd_async_msg_pool { + struct msg_pool *pools; + __u32 pool_num; +}; + +struct wd_ctx_range { + __u32 begin; + __u32 end; + __u32 size; +}; + +struct wd_env_config_per_numa { + /* Config begin */ + unsigned long node; + unsigned long sync_ctx_num; + unsigned long async_ctx_num; + /* + * Define which polling thread to poll each async ctx, polling thread + * number stars from 0. + * + * async_ctx_poll: 0, 0, 0, 1, 1, means polling thread 0 polls async + * ctx 0, 1, 2, polling thread 1 polls async ctx 3, 4. + */ + unsigned long *async_ctx_poll; + + /* + * +---------+-----------------+---------------+ + * | | sync | async | + * +---------+-----------------+---------------+ + * | op_type | begine end | begin end | + * | | | | + * ... + */ + __u8 op_type_num; + struct wd_ctx_range **ctx_table; + + /* Resource begin */ + struct uacce_dev *dev; + int dev_num; + /* This can be made statically currently */ + unsigned long async_poll_num; + void *async_task_queue_array; +}; + +struct wd_env_config { + struct wd_env_config_per_numa *config_per_numa; + /* Let's make it as a gobal config, not per numa */ + bool enable_internal_poll; + + /* resource config */ + struct wd_sched *sched; + bool internal_sched; + struct wd_ctx_config *ctx_config; + const struct wd_config_variable *table; + __u32 table_size; + __u16 numa_num; + __u8 op_type_num; +}; + +struct wd_config_variable { + const char *name; + char *def_val; + int (*parse_fn)(struct wd_env_config *, const char *); +}; + +struct wd_alg_ops { + char *alg_name; + __u8 op_type_num; + int (*alg_init)(struct wd_ctx_config *, struct wd_sched *); + void (*alg_uninit)(void); + int (*alg_poll_ctx)(__u32, __u32, __u32 *); +}; + +struct wd_ctx_attr { + __u32 node; + __u32 type; + __u32 num; + __u8 mode; +}; + +struct wd_msg_handle { + int (*send)(handle_t sess, void *msg); + int (*recv)(handle_t sess, void *msg); +}; + +/* + * wd_init_ctx_config() - Init internal ctx configuration. + * @in: ctx configuration in global setting. + * @cfg: ctx configuration input by user. + * + * Return 0 if successful or less than 0 otherwise. + */ +int wd_init_ctx_config(struct wd_ctx_config_internal *in, + struct wd_ctx_config *cfg); + +/* + * wd_init_sched() - Init internal scheduler configuration. + * @in: Scheduler configuration in global setting. + * @from: Scheduler configuration input by user. + * + * Return 0 if successful or less than 0 otherwise. + */ +int wd_init_sched(struct wd_sched *in, struct wd_sched *from); + +/* + * wd_clear_sched() - Clear internal scheduler configuration. + * @in: Scheduler configuration in global setting. + */ +void wd_clear_sched(struct wd_sched *in); + +/* + * wd_clear_ctx_config() - Clear internal ctx configuration. + * @in: ctx configuration in global setting. + */ +void wd_clear_ctx_config(struct wd_ctx_config_internal *in); + +/* + * wd_memset_zero() - memset the data to zero. + * @data: the data memory addr. + * @size: the data length. + */ +void wd_memset_zero(void *data, __u32 size); + +/* + * wd_init_async_request_pool() - Init message pools. + * @pool: Pointer of message pool. + * @pool_num: Message pool number. + * @msg_num: Message entry number in one pool. + * @msg_size: Size of each message entry. + * + * Return 0 if successful or less than 0 otherwise. + * + * pool + * pools + * +-------+-------+----+-------+ -+- + * | msg_0 | msg_1 |... | n - 1 | | + * +-------+-------+----+-------+ + * ... pool_num + * +-------+-------+----+-------+ + * | msg_0 | msg_1 |... | n - 1 | | + * +-------+-------+----+-------+ -+- + * |<------- msg_num ---------->| + */ +int wd_init_async_request_pool(struct wd_async_msg_pool *pool, __u32 pool_num, + __u32 msg_num, __u32 msg_size); + +/* + * wd_uninit_async_request_pool() - Uninit message pools. + * @pool: Pool which will be uninit. + */ +void wd_uninit_async_request_pool(struct wd_async_msg_pool *pool); + +/* + * wd_get_msg_from_pool() - Get a free message from pool. + * @pool: Pointer of global pools. + * @ctx_idx: Index of pool. Should be 0 ~ (pool_num - 1). + * @msg: Put pointer of got message into *msg. + * + * Return tag of got message. This tag can be used to put a message and + * find a message in wd_put_msg_to_pool() and wd_find_msg_in_pool(). Returned + * tag will be in 1 ~ msg_num indicating msg_0 ~ msg_n-1; tag value 0 will NOT + * be used to avoid possible error; -WD_EBUSY will return if related message pool + * is full. + */ +int wd_get_msg_from_pool(struct wd_async_msg_pool *pool, int ctx_idx, + void **msg); + +/* + * wd_put_msg_to_pool() - Put a message to pool. + * @pool: Pointer of global pools. + * @ctx_idx: Index of pool. Should be 0 ~ (pool_num - 1). + * @tag: Tag of put message. + */ +void wd_put_msg_to_pool(struct wd_async_msg_pool *pool, int ctx_idx, + __u32 tag); + +/* + * wd_find_msg_in_pool() - Find a message in pool. + * @pool: Pointer of global pools. + * @ctx_idx: Index of pool. Should be 0 ~ (pool_num - 1). + * @tag: Tag of expected message. + * + * Return pointer of message whose tag is input tag. + */ +void *wd_find_msg_in_pool(struct wd_async_msg_pool *pool, int ctx_idx, + __u32 tag); + +/* + * wd_check_datalist() - Check the data list length + * @head: Data list's head pointer. + * @size: The size which is expected. + * + * Return 0 if the datalist is not less than expected size. + */ +int wd_check_datalist(struct wd_datalist *head, __u32 size); + + +/* + * wd_parse_ctx_num() - Parse wd ctx type environment variable and store it. + * @config: Pointer of wd_env_config which is used to store environment + * variable information. + * @s: Related environment variable string. + * + * More information, please see docs/wd_environment_variable. + */ +int wd_parse_ctx_num(struct wd_env_config *config, const char *s); + +/* + * wd_parse_async_poll_en() - Parse async polling thread related environment + * variable and store it. + * @config: Pointer of wd_env_config which is used to store environment + * variable information. + * @s: Related environment variable string. + * + * More information, please see docs/wd_environment_variable. + */ +int wd_parse_async_poll_en(struct wd_env_config *config, const char *s); + +/* + * wd_parse_async_poll_num() - Parse async polling thread related environment + * variable and store it. + * @config: Pointer of wd_env_config which is used to store environment + * variable information. + * @s: Related environment variable string. + * + * More information, please see docs/wd_environment_variable. + */ +int wd_parse_async_poll_num(struct wd_env_config *config, const char *s); + +/* + * wd_alg_env_init() - Init wd algorithm environment variable configurations. + * This is a help function which can be used by specific + * wd algorithm APIs. + * @env_config: Pointer of wd_env_config which is used to store environment + * variable information. + * @table: Table which is used to define specific environment variable、its + * default value and related parsing operations. + * @ops: Define functions which will be used by specific wd algorithm + * environment init. + * @table_size: Size of above table. + */ +int wd_alg_env_init(struct wd_env_config *env_config, + const struct wd_config_variable *table, + const struct wd_alg_ops *ops, + __u32 table_size, + struct wd_ctx_attr *ctx_attr); + +/* + * wd_alg_env_uninit() - uninit specific wd algorithm environment configuration. + * @config: Pointer of wd_env_config which is used to store environment + * variable information. + * @ops: Define functions which will be used by specific wd algorithm + * environment init. + */ +void wd_alg_env_uninit(struct wd_env_config *env_config, + const struct wd_alg_ops *ops); + +/* + * wd_add_task_to_async_queue() - Add an async request to its related async + * task queue. + * @config: Pointer of wd_env_config which is used to store environment + * variable information. + * @idx: Index of ctx in config. + */ +int wd_add_task_to_async_queue(struct wd_env_config *config, __u32 idx); + +/* + * dump_env_info() - dump wd algorithm ctx info. + * @config: Pointer of wd_env_config which is used to store environment + * variable information. + */ +void dump_env_info(struct wd_env_config *config); + +/** + * wd_alg_get_env_param() - get specific ctx number. + * @config: Pointer of wd_env_config which is used to store environment + * variable information. + * @attr: ctx attributes. + * @num: save ctx number. + * @is_enable: save enable inner poll flag. + */ +int wd_alg_get_env_param(struct wd_env_config *env_config, + struct wd_ctx_attr attr, + __u32 *num, __u8 *is_enable); + +/** + * wd_set_ctx_attr() - set node type and mode for ctx + * @ctx_attr: ctx attributes pointer. + * @node: numa id. + * @type: operation type. + * @mode: synchronous or asynchronous mode. + * @num: ctx number. + */ +int wd_set_ctx_attr(struct wd_ctx_attr *ctx_attr, + __u32 node, __u32 type, __u8 mode, __u32 num); + +/** + * wd_check_ctx() - check ctx mode and index + * @config: ctx config pointer. + * @mode: synchronous or asynchronous mode. + * @idx: ctx index. + */ +int wd_check_ctx(struct wd_ctx_config_internal *config, __u8 mode, __u32 idx); + +/** + * wd_set_epoll_en() - set epoll enable flag from environment variable value. + * @var_name: Environment variable name string. + * @epoll_en: epoll enable flag. + * + * Return 0 if the value is 0 or 1, otherwise return -WD_EINVAL. + */ +int wd_set_epoll_en(const char *var_name, bool *epoll_en); + +/** + * wd_handle_msg_sync() - recv msg from hardware + * @msg_handle: callback of msg handle ops. + * @ctx: the handle of context. + * @msg: the msg of task. + * @balance: estimated number of receiving msg. + * @epoll_en: whether to enable epoll. + * + * Return 0 if successful or less than 0 otherwise. + */ +int wd_handle_msg_sync(struct wd_msg_handle *msg_handle, handle_t ctx, + void *msg, __u64 *balance, bool epoll_en); + +/** + * wd_init_check() - Check input parameters for wd__init. + * @config: Ctx configuration input by user. + * @sched: Scheduler configuration input by user. + * + * Return 0 if successful or less than 0 otherwise. + */ +int wd_init_param_check(struct wd_ctx_config *config, struct wd_sched *sched); + +/** + * wd_dfx_msg_cnt() - Message counter interface for ctx + * @msg: Shared memory addr. + * @numSize: Number of elements. + * @index: Indicates the CTX index. + */ +static inline void wd_dfx_msg_cnt(unsigned long *msg, __u32 numsize, __u32 idx) +{ + bool ret; + + ret = wd_need_info(); + if (idx > numsize || !ret) + return; + + msg[idx]++; +} + +#ifdef __cplusplus +} +#endif + +#endif /* __WD_UTIL_H */ diff --git a/uadk/lib/libwd.pc.in b/uadk/lib/libwd.pc.in new file mode 100644 index 0000000..ac4fa56 --- /dev/null +++ b/uadk/lib/libwd.pc.in @@ -0,0 +1,20 @@ +# Process this file with autoconf to produce a pkg-config metadata file. + +# Copyright (C) 2004-2012 Free Software Foundation, Inc. + +# Copying and distribution of this file, with or without modification, +# are permitted in any medium without royalty provided the copyright +# notice and this notice are preserved. This file is offered as-is, +# without any warranty. + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: UADK_libwd +Description: UADK Helper library +Version: @VERSION@ +Libs: -L${libdir} -lwd +Cflags: -I${includedir} +Libs.Private: -lnuma diff --git a/uadk/lib/libwd_comp.pc.in b/uadk/lib/libwd_comp.pc.in new file mode 100644 index 0000000..9f934ce --- /dev/null +++ b/uadk/lib/libwd_comp.pc.in @@ -0,0 +1,21 @@ +# Process this file with autoconf to produce a pkg-config metadata file. + +# Copyright (C) 2004-2012 Free Software Foundation, Inc. + +# Copying and distribution of this file, with or without modification, +# are permitted in any medium without royalty provided the copyright +# notice and this notice are preserved. This file is offered as-is, +# without any warranty. + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: UADK_libwd_comp +Description: UADK Compress Algorithm library +Version: @VERSION@ +Libs: -L${libdir} -lwd_comp +Requires.private: libwd +Cflags: -I${includedir} +Libs.Private: -ldl diff --git a/uadk/lib/libwd_crypto.pc.in b/uadk/lib/libwd_crypto.pc.in new file mode 100644 index 0000000..bb45f71 --- /dev/null +++ b/uadk/lib/libwd_crypto.pc.in @@ -0,0 +1,21 @@ +# Process this file with autoconf to produce a pkg-config metadata file. + +# Copyright (C) 2004-2012 Free Software Foundation, Inc. + +# Copying and distribution of this file, with or without modification, +# are permitted in any medium without royalty provided the copyright +# notice and this notice are preserved. This file is offered as-is, +# without any warranty. + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: UADK_libwd_crypto +Description: UADK Crypto Algorithm library +Version: @VERSION@ +Libs: -L${libdir} -lwd_crypto +Requires.private: libwd +Cflags: -I${includedir} +Libs.Private: -ldl -lnuma diff --git a/uadk/sample/Makefile.am b/uadk/sample/Makefile.am new file mode 100644 index 0000000..eb8d71b --- /dev/null +++ b/uadk/sample/Makefile.am @@ -0,0 +1,16 @@ +ACLOCAL_AMFLAGS = -I m4 -I./include +AM_CFLAGS=-Wall -fno-strict-aliasing -I$(top_srcdir) -I$(top_srcdir)/include + +bin_PROGRAMS=uadk_comp + +uadk_comp_SOURCES=uadk_comp.c + +if WD_STATIC_DRV +AM_CFLAGS+=-Bstatic +uadk_comp_LDADD=../.libs/libwd.a \ + ../.libs/libwd_comp.a \ + ../.libs/libhisi_zip.a -lpthread -lnuma +else +uadk_comp_LDADD=-L../.libs -l:libwd.so.2 -l:libwd_comp.so.2 -lpthread -lnuma +endif +uadk_comp_LDFLAGS=-Wl,-rpath,'/usr/local/lib' diff --git a/uadk/sample/uadk_comp.c b/uadk/sample/uadk_comp.c new file mode 100644 index 0000000..908c7bc --- /dev/null +++ b/uadk/sample/uadk_comp.c @@ -0,0 +1,505 @@ +#include +#include +#include +#include +#include + +#include "wd_alg_common.h" +#include "wd_comp.h" +#include "wd_sched.h" + +#define SCHED_RR_NAME "sched_rr" + +#define CTX_SET_NUM 1 +#define CTX_SET_SIZE 4 +#define MAX_ALG_LEN 32 +#define MAX_THREAD 1024 + +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +struct request_config { + char algname[MAX_ALG_LEN]; + enum wd_comp_alg_type alg; + enum wd_comp_level complv; + enum wd_comp_op_type optype; + enum wd_comp_winsz_type winsize; + enum wd_ctx_mode request_mode; + enum wd_buff_type buftype; + struct wd_ctx_config ctx; + struct wd_sched *sched; + struct uacce_dev_list *list; +}; + +struct request_data { + handle_t h_sess; + struct wd_comp_req req; +}; + +struct acc_alg_item { + char *name; + int alg; +}; + +static struct request_config config = { + .complv = WD_COMP_L8, + .optype = WD_DIR_COMPRESS, + .winsize = WD_COMP_WS_8K, + .request_mode = CTX_MODE_SYNC, + .buftype = WD_FLAT_BUF, +}; + +static struct request_data data; + +static struct acc_alg_item alg_options[] = { + {"zlib", WD_ZLIB}, + {"gzip", WD_GZIP}, + {"deflate", WD_DEFLATE}, + {"lz77_zstd", WD_LZ77_ZSTD}, + {"", WD_COMP_ALG_MAX} +}; + +static void cowfail(char *s) +{ + fprintf(stderr, "" + "__________________________________\n\n" + "%s" + "\n----------------------------------\n" + "\t \\ ^__^\n" + "\t \\ (oo)\\_______\n" + "\t (__)\\ )\\\\\n" + "\t ||----w |\n" + "\t || ||\n" + "\n", s); +} + +static struct uacce_dev_list* get_dev_list(char *alg_name) +{ + struct uacce_dev_list *list, *p, *head = NULL, *prev = NULL; + int ctx_set_num = CTX_SET_NUM; + int max_ctx_num; + int i; + + for (i = 0; i < ARRAY_SIZE(alg_options); i++) + if (!strcmp(alg_name, alg_options[i].name)) + config.alg = alg_options[i].alg; + + list = wd_get_accel_list(alg_name); + if (!list) + return NULL; + + p = list; + /* Find one device matching the requested contexts. */ + while (p) { + max_ctx_num = wd_get_avail_ctx(p->dev); + /* + * Check whether there's enough contexts. + * There may be multiple taskes running together. + * The number of multiple taskes is specified in children. + */ + if (max_ctx_num < ctx_set_num * CTX_SET_SIZE) { + if (!head) + head = p; + prev = p; + p = p->next; + } else + break; + } + + if (!p) { + fprintf(stderr, "%s request too much contexts: %d.\n", + __func__, ctx_set_num); + goto out; + } + + /* Adjust p to the head of list if p is in the middle. */ + if (p && (p != list)) { + prev->next = p->next; + p->next = head; + return p; + } + + return list; + +out: + wd_free_list_accels(list); + return NULL; +} + +static int lib_poll_func(__u32 pos, __u32 expect, __u32 *count) +{ + int ret; + + ret = wd_comp_poll_ctx(pos, expect, count); + if (ret < 0) + return ret; + + return 0; +} + +static struct wd_sched *uadk_comp_sched_init(void) +{ + int ctx_set_num = CTX_SET_NUM; + struct sched_params param; + struct wd_sched *sched; + int i, j, ret; + + sched = wd_sched_rr_alloc(SCHED_POLICY_RR, 2, 2, lib_poll_func); + if (!sched) { + printf("%s fail to alloc sched.\n", __func__); + return NULL; + } + sched->name = SCHED_RR_NAME; + + /* + * All contexts for 2 modes & 2 types. + * The test only uses one kind of contexts at the same time. + */ + for (i = 0; i < CTX_SET_SIZE; i++) { + for (j = ctx_set_num * i; j < ctx_set_num * (i + 1); j++) { + param.mode = i / 2; + param.type = i % 2; + param.numa_id = 0; + param.begin = ctx_set_num * i; + param.end = ctx_set_num * (i + 1) - 1; + ret = wd_sched_rr_instance(sched, ¶m); + if (ret < 0) { + fprintf(stderr, "%s fail to fill sched region.\n", + __func__); + goto out_free_sched; + } + } + } + + return sched; + +out_free_sched: + wd_sched_rr_release(sched); + + return NULL; +} + +static int uadk_comp_ctx_init(void) +{ + struct wd_ctx_config *ctx = &config.ctx; + int ctx_set_num = CTX_SET_NUM; + struct wd_sched *sched; + int i, j, ret; + + memset(ctx, 0, sizeof(struct wd_ctx_config)); + ctx->ctx_num = ctx_set_num * CTX_SET_SIZE; + ctx->ctxs = calloc(ctx_set_num * CTX_SET_SIZE, sizeof(struct wd_ctx)); + if (!ctx->ctxs) { + fprintf(stderr, "%s fail to allocate contexts.\n", __func__); + return -WD_ENOMEM; + } + + for (i = 0; i < CTX_SET_SIZE; i++) { + for (j = ctx_set_num * i; j < ctx_set_num * (i + 1); j++) { + ctx->ctxs[j].ctx = wd_request_ctx(config.list->dev); + if (!ctx->ctxs[j].ctx) { + fprintf(stderr, "%s fail to request context #%d.\n", + __func__, i); + ret = -WD_EINVAL; + goto out_free_ctx; + } + ctx->ctxs[j].ctx_mode = i / 2; + ctx->ctxs[j].op_type = i % 2; + } + } + + sched = uadk_comp_sched_init(); + if (!sched) { + ret = -WD_EINVAL; + goto out_free_ctx; + } + + config.sched = sched; + + ret = wd_comp_init(ctx, sched); + if (ret) { + fprintf(stderr, "%s fail to init comp.\n", __func__); + goto out_free_sched; + } + + return 0; + +out_free_sched: + wd_sched_rr_release(sched); + +out_free_ctx: + for (i = 0; i < ctx->ctx_num; i++) + if (ctx->ctxs[i].ctx) + wd_release_ctx(ctx->ctxs[i].ctx); + free(ctx->ctxs); + + return ret; +} + +static void uadk_comp_ctx_uninit(void) +{ + struct wd_ctx_config *ctx = &config.ctx; + int i; + + wd_comp_uninit(); + + for (i = 0; i < ctx->ctx_num; i++) + wd_release_ctx(ctx->ctxs[i].ctx); + + wd_free_list_accels(config.list); + wd_sched_rr_release(config.sched); +} + +static int uadk_comp_sess_init(void) +{ + struct wd_comp_sess_setup setup = {0}; + struct sched_params param = {0}; + handle_t h_sess; + int ret = 0; + + setup.alg_type = config.alg; + setup.op_type = config.optype; + setup.comp_lv = config.complv; + setup.win_sz = config.winsize; + param.type = config.optype; + setup.sched_param = ¶m; + + h_sess = wd_comp_alloc_sess(&setup); + if (!h_sess) { + fprintf(stderr, "%s fail to alloc comp sess.\n", __func__); + ret = -WD_EINVAL; + goto out_free_sess; + } + data.h_sess = h_sess; + + return 0; + +out_free_sess: + wd_comp_free_sess(data.h_sess); + + return ret; +} + +static void uadk_comp_sess_uninit(void) +{ + wd_comp_free_sess(data.h_sess); +} + +static int uadk_req_buf_init(struct wd_comp_req *req, FILE *source) +{ + int src_len = req->src_len; + int dst_len = req->dst_len; + void *src, *dst; + int ret; + + src = malloc(src_len); + if (!src) { + fprintf(stderr, "%s fail to alloc src.\n", __func__); + return -WD_ENOMEM; + } + + dst = malloc(dst_len); + if (!dst) { + fprintf(stderr, "%s fail to alloc dst.\n", __func__); + ret = -WD_ENOMEM; + goto out_free_src; + } + + ret = fread(src, 1, src_len, source); + if (ret != src_len) { + fprintf(stderr, "%s fail to read stdin.\n", __func__); + ret = -WD_ENOMEM; + goto out_free_dst; + } + + req->src = src; + req->dst = dst; + + return 0; + +out_free_dst: + free(dst); + +out_free_src: + free(src); + + return ret; +} + +static void uadk_req_buf_uninit(void) +{ + free(data.req.src); + free(data.req.dst); +} + +static int uadk_comp_request_init(FILE *source) +{ + struct wd_comp_req *req; + struct stat fs; + int fd, ret; + + fd = fileno(source); + ret = fstat(fd, &fs); + if (ret < 0) { + fprintf(stderr, "%s fstat error.\n", __func__); + return ret; + } + + req = &data.req; + req->op_type = config.optype; + req->data_fmt = WD_FLAT_BUF; + req->src_len = fs.st_size; + req->dst_len = fs.st_size * 4; + + return uadk_req_buf_init(req, source); +} + +static void uadk_comp_request_uninit(void) +{ + uadk_req_buf_uninit(); +} + +static int uadk_do_comp(void) +{ + int ret; + + ret = wd_do_comp_sync2(data.h_sess, &data.req); + if (ret < 0) + fprintf(stderr, "%s fail to do comp sync(ret = %d).\n", __func__, ret); + + return ret; +} + +static int uadk_comp_write_file(FILE *dest) +{ + int size; + + size = fwrite(data.req.dst, 1, data.req.dst_len, dest); + if (size < 0) + return size; + + return 0; +} + +static int operation(FILE *source, FILE *dest) +{ + int ret; + + ret = uadk_comp_ctx_init(); + if (ret) { + fprintf(stderr, "%s fail to init ctx!\n", __func__); + return ret; + } + + ret = uadk_comp_sess_init(); + if (ret) { + fprintf(stderr, "%s fail to init sess!\n", __func__); + goto out_ctx_uninit; + } + + ret = uadk_comp_request_init(source); + if (ret) { + fprintf(stderr, "%s fail to init request!\n", __func__); + goto out_sess_uninit; + } + + ret = uadk_do_comp(); + if (ret) { + fprintf(stderr, "%s fail to do request!\n", __func__); + goto out_sess_uninit; + } + + ret = uadk_comp_write_file(dest); + if (ret) + fprintf(stderr, "%s fail to write result!\n", __func__); + + uadk_comp_request_uninit(); + +out_sess_uninit: + uadk_comp_sess_uninit(); + +out_ctx_uninit: + uadk_comp_ctx_uninit(); + + return ret; +} + +static void print_help(void) +{ + fprintf(stderr, "" + "uadk_comp - a tool used to do compress/decompress\n\n" + "Arguments:\n" + "\t[--alg]: " + "The name of the algorithm (can find under .../uacce//algorithms)\n" + "\t[--optype]: " + "Use 0/1 stand for compression/decompression.\n" + "\t[--winsize]: " + "The window size for compression(8K as default).\n" + "\t[--complv]: " + "The compression level(8 as default).\n" + "\t[--help] " + "Print Help (this message) and exit\n" + ""); +} + +int main(int argc, char *argv[]) +{ + int option_index = 0; + int help = 0; + int ret, c; + + static struct option long_options[] = { + {"help", no_argument, 0, 0}, + {"alg", required_argument, 0, 1}, + {"complv", required_argument, 0, 2}, + {"optype", required_argument, 0, 3}, + {"winsize", required_argument, 0, 4}, + {0, 0, 0, 0} + }; + + while (!help) { + c = getopt_long(argc, argv, "", long_options, &option_index); + if (c == -1) + break; + + switch (c) { + case 0: + help = 1; + break; + case 1: + config.list = get_dev_list(optarg); + if (!config.list) { + cowfail("Can't find your algorithm!\n"); + help = 1; + } else { + strcpy(config.algname, optarg); + } + break; + case 2: + config.complv = strtol(optarg, NULL, 0); + break; + case 3: + config.optype = strtol(optarg, NULL, 0); + break; + case 4: + config.winsize = strtol(optarg, NULL, 0); + break; + default: + help = 1; + cowfail("bad input test parameter!\n"); + break; + } + } + + if (help) { + print_help(); + exit(-1); + } + + ret = operation(stdin, stdout); + if (ret) + cowfail("So sad for we do something wrong!\n"); + + return ret; +} diff --git a/uadk/test/Makefile.am b/uadk/test/Makefile.am new file mode 100644 index 0000000..81e2d2c --- /dev/null +++ b/uadk/test/Makefile.am @@ -0,0 +1,24 @@ +AM_CFLAGS=-Wall -O0 -Werror -fno-strict-aliasing -I$(top_srcdir)/include -I$(top_srcdir) -lpthread + +bin_PROGRAMS=wd_mempool_test +wd_mempool_test_SOURCES=wd_mempool_test.c + +if WD_STATIC_DRV +AM_CFLAGS+=-Bstatic +wd_mempool_test_LDADD=../.libs/libwd.a ../.libs/libwd_crypto.a \ + ../.libs/libhisi_sec.a -lnuma +else +wd_mempool_test_LDADD=-L../.libs -l:libwd.so.2 -l:libwd_crypto.so.2 -lnuma +endif +wd_mempool_test_LDFLAGS=-Wl,-rpath,'/usr/local/lib' + +SUBDIRS=. hisi_sec_test + +if HAVE_CRYPTO +SUBDIRS += hisi_hpre_test + +if HAVE_ZLIB +SUBDIRS += hisi_zip_test +endif + +endif diff --git a/uadk/test/hisi_hpre_test/Makefile.am b/uadk/test/hisi_hpre_test/Makefile.am new file mode 100644 index 0000000..ce96e2f --- /dev/null +++ b/uadk/test/hisi_hpre_test/Makefile.am @@ -0,0 +1,15 @@ +AM_CFLAGS=-Wall -fno-strict-aliasing -I$(top_srcdir)/include -pthread + +bin_PROGRAMS=test_hisi_hpre + +test_hisi_hpre_SOURCES=test_hisi_hpre.c test_hisi_hpre.h + +if WD_STATIC_DRV +test_hisi_hpre_LDADD=../../.libs/libwd.a ../../.libs/libwd_crypto.a \ + ../../.libs/libhisi_hpre.a -ldl -lnuma +else +test_hisi_hpre_LDADD=-L../../.libs -l:libwd.so.2 -l:libwd_crypto.so.2 \ + -lnuma +endif +test_hisi_hpre_LDFLAGS=-Wl,-rpath,'/usr/local/lib' +test_hisi_hpre_LDADD+= $(libcrypto_LIBS) diff --git a/uadk/test/hisi_hpre_test/hpre_test_sample.h b/uadk/test/hisi_hpre_test/hpre_test_sample.h new file mode 100644 index 0000000..921ae49 --- /dev/null +++ b/uadk/test/hisi_hpre_test/hpre_test_sample.h @@ -0,0 +1,1555 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +#ifndef __HPRE_TEST_SAMPLE_H +#define __HPRE_TEST_SAMPLE_H + +#ifndef WITH_OPENSSL_DIR +static unsigned char rsa_e_1024[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, +}; + +static unsigned char rsa_p_1024[] = { + 0xf6, 0x49, 0xf2, 0xec, 0x89, 0xc8, 0xc2, 0x9b, 0x38, 0xd8, 0x74, 0x9b, 0x77, 0xed, 0x96, 0xc7, + 0x6d, 0xed, 0x15, 0x51, 0x2d, 0xfe, 0x67, 0x10, 0xa5, 0xdf, 0xd0, 0x59, 0x79, 0x75, 0x00, 0x60, + 0x3d, 0xd0, 0xf6, 0xe4, 0xda, 0x16, 0x5a, 0x24, 0x14, 0x01, 0xfa, 0x19, 0x07, 0x75, 0x21, 0x70, + 0x88, 0x40, 0xd9, 0x2f, 0xec, 0x83, 0x9e, 0x5f, 0xaa, 0xc0, 0xa3, 0x70, 0x18, 0xf5, 0x78, 0xdf, +}; + +static unsigned char rsa_q_1024[] = { + 0xcf, 0x53, 0x52, 0x09, 0x0d, 0xd7, 0x84, 0xdb, 0xa4, 0x4c, 0x79, 0x74, 0x0d, 0x94, 0xa0, 0x19, + 0x94, 0x33, 0xbf, 0x39, 0xe5, 0xef, 0xf5, 0xe9, 0x6c, 0xef, 0xd0, 0x9a, 0x4c, 0x00, 0x14, 0x68, + 0x66, 0xa7, 0x80, 0x32, 0x14, 0x84, 0xc9, 0x6f, 0x9a, 0x7d, 0x43, 0x0e, 0x9f, 0x85, 0x27, 0x6c, + 0x65, 0x50, 0x9b, 0x88, 0x54, 0x22, 0x72, 0x95, 0x90, 0x26, 0xc4, 0xa8, 0x19, 0x1c, 0x47, 0x03, +}; + +static unsigned char rsa_dp_1024[] = { + 0xd0, 0xb6, 0x66, 0x28, 0xd1, 0xb2, 0xd2, 0x48, 0x1c, 0x6a, 0x42, 0x97, 0x25, 0x90, 0xb0, 0x40, + 0x1d, 0x05, 0xd7, 0x14, 0xce, 0x77, 0x52, 0xfc, 0x26, 0xb5, 0x7e, 0xa8, 0xf4, 0x66, 0x94, 0x84, + 0xfa, 0x9d, 0xc5, 0x3c, 0xb7, 0x1c, 0x4e, 0x13, 0x58, 0xe9, 0x3b, 0xfa, 0x4d, 0xf9, 0x92, 0xf6, + 0xfc, 0x60, 0x88, 0x2d, 0x36, 0xaf, 0x6b, 0x5d, 0x03, 0x24, 0xf0, 0xdc, 0x24, 0x2a, 0x91, 0xdd, +}; + +static unsigned char rsa_dq_1024[] = { + 0x09, 0x4a, 0x89, 0x9d, 0xa0, 0x42, 0x2d, 0x51, 0x0e, 0x8e, 0xe2, 0xce, 0x81, 0xa1, 0x4c, 0x7f, + 0x78, 0xf5, 0xcc, 0xb7, 0x12, 0x87, 0xeb, 0x74, 0x57, 0x8e, 0x73, 0xc1, 0xc6, 0x70, 0x26, 0x79, + 0xfb, 0x47, 0xbc, 0x66, 0x02, 0x27, 0x65, 0x43, 0x9c, 0x1f, 0xca, 0xf6, 0x87, 0xcd, 0x96, 0xd3, + 0xb3, 0xc2, 0xa6, 0x05, 0xb9, 0x07, 0x86, 0x2d, 0x0f, 0xb5, 0xbd, 0x10, 0x6f, 0x77, 0xa5, 0xf3, +}; + +static unsigned char rsa_qinv_1024[] = { + 0x59, 0xf3, 0xaf, 0x75, 0xde, 0xdd, 0xcc, 0xc7, 0x62, 0xd7, 0xed, 0x4e, 0x81, 0x18, 0xca, 0x42, + 0xab, 0x36, 0x3b, 0x83, 0x5c, 0xd0, 0x55, 0x3f, 0x37, 0x3a, 0xa9, 0x64, 0x25, 0x65, 0x05, 0xde, + 0x87, 0xca, 0x54, 0xdb, 0x24, 0xdc, 0xe8, 0xf7, 0x4a, 0xfe, 0x2c, 0x59, 0xbf, 0x3d, 0x45, 0x43, + 0x91, 0x9e, 0x6b, 0x9c, 0xf6, 0xce, 0xb2, 0xf8, 0xc5, 0x2e, 0xef, 0x85, 0x58, 0xed, 0x4a, 0x0e, +}; + +static unsigned char rsa_d_1024[] = { + 0x13, 0xbe, 0x3a, 0x33, 0xf3, 0xad, 0x6f, 0xc7, 0x3a, 0x8c, 0x77, 0xe3, 0x73, 0xb8, 0x13, 0xf0, + 0x66, 0x50, 0xd7, 0x04, 0xe5, 0xeb, 0x11, 0x31, 0x97, 0x9b, 0xac, 0xd5, 0x72, 0x9f, 0xe4, 0xeb, + 0xd7, 0x27, 0x9b, 0x2d, 0xef, 0xca, 0xa3, 0x7c, 0xe7, 0x2f, 0x5e, 0xd7, 0xe9, 0x85, 0xbd, 0x88, + 0xce, 0xb6, 0x32, 0xe2, 0xf3, 0xe4, 0x28, 0x0f, 0xc7, 0x8e, 0xa5, 0xbb, 0xc4, 0xd4, 0xe8, 0xd9, + 0x23, 0x81, 0x4c, 0x71, 0x37, 0xc9, 0x78, 0xe2, 0xd8, 0x54, 0x01, 0x05, 0xb9, 0x5e, 0x48, 0xab, + 0x65, 0x76, 0x63, 0xe3, 0x90, 0xaf, 0x25, 0x00, 0xde, 0xe3, 0xb7, 0x6f, 0x91, 0xa1, 0x5e, 0x7a, + 0x84, 0xbf, 0x62, 0x08, 0x63, 0xe7, 0x0a, 0x23, 0x42, 0x50, 0xc8, 0x33, 0x29, 0xb9, 0x27, 0x27, + 0xe6, 0x34, 0x73, 0x69, 0x08, 0x76, 0xaf, 0x65, 0x1e, 0x3b, 0x51, 0xa5, 0x16, 0xad, 0x20, 0xe5, +}; + +static unsigned char rsa_n_1024[] = { + 0xc7, 0x75, 0xf4, 0x53, 0x6b, 0xd4, 0x69, 0x28, 0x39, 0xeb, 0xa7, 0x70, 0xcf, 0x8f, 0x47, 0x54, + 0x57, 0xf9, 0x43, 0xd3, 0xd6, 0x7b, 0xa4, 0xc9, 0x4b, 0xb3, 0x9d, 0xb3, 0x7f, 0x8f, 0x46, 0x31, + 0xf6, 0xbe, 0x62, 0xa4, 0x0c, 0x7e, 0x41, 0x41, 0x2e, 0x4d, 0x31, 0x1a, 0x92, 0xca, 0x69, 0x27, + 0x0a, 0x06, 0x23, 0xf5, 0x0f, 0x50, 0xf0, 0x17, 0xfa, 0x92, 0x25, 0x1c, 0xb6, 0x59, 0x2c, 0xcc, + 0xc9, 0x4d, 0x3c, 0x38, 0x04, 0xbb, 0x05, 0xc5, 0x20, 0xe5, 0xaf, 0x06, 0xd0, 0xc4, 0x14, 0x9c, + 0xa9, 0xa4, 0x7e, 0x97, 0x04, 0xb9, 0xe7, 0x60, 0x47, 0xa2, 0xed, 0xea, 0xda, 0xec, 0x4e, 0x0a, + 0x7a, 0x01, 0x00, 0x19, 0x19, 0x99, 0x49, 0x28, 0x70, 0x07, 0x21, 0xd8, 0x0d, 0x1f, 0x2d, 0xa2, + 0x9d, 0x78, 0x94, 0x26, 0xdd, 0x26, 0x65, 0x66, 0xf3, 0x04, 0xc3, 0x3b, 0x5e, 0xca, 0x43, 0x9d, +}; + +static unsigned char rsa_e_2048[] = { + +}; + +static unsigned char rsa_p_2048[] = { + +}; + +static unsigned char rsa_q_2048[] = { + +}; + +static unsigned char rsa_dp_2048[] = { + +}; + +static unsigned char rsa_dq_2048[] = { + +}; + +static unsigned char rsa_qinv_2048[] = { + +}; + +static unsigned char rsa_d_2048[] = { + +}; + +static unsigned char rsa_n_2048[] = { + +}; + +static unsigned char rsa_e_3072[] = { + +}; + +static unsigned char rsa_p_3072[] = { + +}; + +static unsigned char rsa_q_3072[] = { + +}; + +static unsigned char rsa_dp_3072[] = { + +}; + +static unsigned char rsa_dq_3072[] = { + +}; + +static unsigned char rsa_qinv_3072[] = { + +}; + +static unsigned char rsa_d_3072[] = { + +}; + +static unsigned char rsa_n_3072[] = { + +}; + +static unsigned char rsa_e_4096[] = { + +}; + +static unsigned char rsa_p_4096[] = { + +}; + +static unsigned char rsa_q_4096[] = { + +}; + +static unsigned char rsa_dp_4096[] = { + +}; + +static unsigned char rsa_dq_4096[] = { + +}; + +static unsigned char rsa_qinv_4096[] = { + +}; + +static unsigned char rsa_d_4096[] = { + +}; + +static unsigned char rsa_n_4096[] = { + +}; +#endif + +static char dh_g_5[] = {0x05}; +static char dh_g_2[] = {0x02}; + +static char dh_p_768[] = { + 0xdd, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x01, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7 +}; + +static char dh_xa_768[] = { + 0xe0, 0x80, 0x86, 0x24, 0xe2, 0x20, 0x35, 0x97, 0xda, 0x0e, 0x68, 0x39, 0x01, 0xdd, 0x01, 0x87, + 0xa2, 0x47, 0xd2, 0x0d, 0xee, 0xfe, 0xdc, 0x5a, 0x37, 0x23, 0xeb, 0x3d, 0xe8, 0x1e, 0x39, 0x2d, + 0xbf, 0xa6, 0xe9, 0x17, 0x48, 0xe2, 0xea, 0xef, 0x1d, 0x2f, 0xe2, 0xaf, 0x3c, 0xbc, 0xae, 0xa7, + 0x42, 0x9b, 0xa5, 0x7d, 0x47, 0x8a, 0x20, 0xc5, 0xae, 0xa1, 0xe4, 0xe8, 0x1c, 0x05, 0xc0, 0x0a, + 0x05, 0xdc, 0x01, 0x74, 0xde, 0xad, 0xad, 0x07, 0xec, 0x6e, 0x6a, 0xc7, 0xee, 0x0f, 0xb8, 0xbe, + 0xaa, 0x46, 0x61, 0x8c, 0x12, 0x5a, 0xaf, 0x05, 0xff, 0x1b, 0x35, 0x6b, 0xe2, 0x3d, 0x48, 0x4f +}; + +#if 0 +static char dh_xb_768[] = { + 0x8b, 0xd9, 0xf8, 0x14, 0xe6, 0x42, 0x95, 0xbd, 0x9a, 0x96, 0xbe, 0xf4, 0x7d, 0x26, 0x5d, 0xa1, + 0x81, 0x9b, 0x1c, 0xec, 0xfe, 0xce, 0x9, 0x1d, 0xb7, 0x7a, 0xba, 0xca, 0x7f, 0x54, 0xee, 0x36, + 0x54, 0x65, 0x4a, 0xd0, 0x5c, 0x84, 0x8c, 0x3e, 0x1b, 0xfe, 0x91, 0x6f, 0x95, 0xb5, 0x76, 0xbf, + 0x61, 0x2a, 0x7, 0x23, 0x86, 0xb9, 0xe0, 0x19, 0x29, 0xcf, 0xea, 0x3a, 0x1, 0xbf, 0xee, 0x1b, + 0x5e, 0x3c, 0x4, 0xff, 0x1d, 0xcf, 0xa6, 0x56, 0xb3, 0x22, 0xbb, 0x45, 0x4b, 0x7f, 0x83, 0x87, + 0xef, 0x21, 0x5, 0xf7, 0x38, 0x1f, 0x6, 0x4d, 0x71, 0x0b, 0xe3, 0xe1, 0xb7, 0x7e, 0xae, 0x18 +}; +#endif + +static char dh_except_a_pubkey_768[] = { + 0xba, 0xe7, 0x3, 0x5b, 0xe4, 0x70, 0x8b, 0xe0, 0xe1, 0x92, 0x13, 0x86, 0x74, 0x4, 0xdc, 0x6a, + 0x0a, 0x2a, 0x20, 0xec, 0x6d, 0xbf, 0xf0, 0x46, 0xf7, 0x9, 0x2, 0xdb, 0x2f, 0x70, 0x11, 0xdd, + 0xb0, 0x13, 0xa2, 0xc1, 0x58, 0x74, 0x29, 0x19, 0x8d, 0x4a, 0x94, 0x80, 0x0b, 0xd7, 0x25, 0x85, + 0x10, 0x35, 0x97, 0x48, 0x6e, 0x70, 0x28, 0xae, 0x58, 0x97, 0x7d, 0xf2, 0x19, 0x27, 0x13, 0xab, + 0x47, 0x9b, 0x54, 0xdf, 0xc3, 0x5b, 0x5f, 0x5e, 0xb4, 0x64, 0x47, 0xce, 0x40, 0x3b, 0x0c, 0x4a, + 0x62, 0x52, 0xba, 0xc7, 0xf0, 0x36, 0x87, 0x9c, 0x79, 0x9a, 0x83, 0x11, 0x61, 0x0c, 0x1b, 0x6b +}; + +static char dh_except_b_pubkey_768[] = { + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x1, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7 +}; + +static char dh_share_key_768[] = { + 0x55, 0x9, 0x6b, 0x9c, 0xc6, 0x37, 0xa9, 0x9b, 0xdf, 0x67, 0x73, 0x7b, 0x46, 0xf9, 0x63, 0x47, + 0xcb, 0xa0, 0x57, 0x2a, 0xed, 0x97, 0x2f, 0xfe, 0x92, 0xf2, 0x20, 0x2c, 0x7e, 0xee, 0x7d, 0x11, + 0x78, 0xe6, 0xb9, 0x9, 0xd1, 0x94, 0xce, 0xd1, 0x5b, 0xf4, 0x44, 0xa9, 0xcb, 0x26, 0x2, 0x36, + 0x57, 0x2c, 0xa2, 0xbe, 0x37, 0xde, 0x86, 0x46, 0x20, 0x27, 0x9d, 0xa0, 0x2f, 0x4, 0xc1, 0xcd, + 0xff, 0x81, 0xe5, 0xe6, 0x2c, 0x9e, 0x39, 0x82, 0x31, 0x54, 0x33, 0xf8, 0xe7, 0xa0, 0xe5, 0x96, + 0xa4, 0x40, 0xc4, 0x44, 0xfe, 0x93, 0x66, 0xe2, 0xda, 0xaa, 0xb8, 0xfb, 0x2f, 0x3b, 0x8c, 0xce, +}; + +static char dh_p_1024[] = { + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x07, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x03, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x01, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7 +}; + +static char dh_xa_1024[] = { + 0x0f, 0x2a, 0x77, 0x25, 0x4b, 0xb3, 0xd3, 0x2d, 0xfd, 0x94, 0x8b, 0x53, 0x02, 0x21, 0x40, 0xd7, + 0x36, 0x76, 0xf3, 0xc8, 0xc0, 0x36, 0x3d, 0x23, 0xc9, 0xbd, 0x92, 0x51, 0xf2, 0x4b, 0x83, 0x15, + 0xe0, 0x80, 0x86, 0x24, 0xe2, 0x20, 0x35, 0x97, 0xda, 0x0e, 0x68, 0x39, 0x01, 0xdd, 0x01, 0x87, + 0xa2, 0x47, 0xd2, 0x0d, 0xee, 0xfe, 0xdc, 0x5a, 0x37, 0x23, 0xeb, 0x3d, 0xe8, 0x1e, 0x39, 0x2d, + 0xbf, 0xa6, 0xe9, 0x17, 0x48, 0xe2, 0xea, 0xef, 0x1d, 0x2f, 0xe2, 0xaf, 0x3c, 0xbc, 0xae, 0xa7, + 0x42, 0x9b, 0xa5, 0x7d, 0x47, 0x8a, 0x20, 0xc5, 0xae, 0xa1, 0xe4, 0xe8, 0x1c, 0x05, 0xc0, 0x0a, + 0x05, 0xdc, 0x01, 0x74, 0xde, 0xad, 0xad, 0x07, 0xec, 0x6e, 0x6a, 0xc7, 0xee, 0x0f, 0xb8, 0xbe, + 0xaa, 0x46, 0x61, 0x8c, 0x12, 0x5a, 0xaf, 0x05, 0xff, 0x1b, 0x35, 0x6b, 0xe2, 0x3d, 0x48, 0x4f +}; + +#if 0 +static char dh_xb_1024[] = { + 0x5e, 0x21, 0x0a, 0x9e, 0x3, 0xdd, 0x3f, 0xcc, 0x38, 0xf6, 0xa9, 0xa6, 0xf8, 0xfd, 0x15, 0x7d, + 0x67, 0x4e, 0x14, 0xae, 0x4d, 0xe2, 0x1f, 0x78, 0x77, 0xfb, 0x83, 0x5f, 0x48, 0xa8, 0xc8, 0x21, + 0x8b, 0xd9, 0xf8, 0x14, 0xe6, 0x42, 0x95, 0xbd, 0x9a, 0x96, 0xbe, 0xf4, 0x7d, 0x26, 0x5d, 0xa1, + 0x81, 0x9b, 0x1c, 0xec, 0xfe, 0xce, 0x9, 0x1d, 0xb7, 0x7a, 0xba, 0xca, 0x7f, 0x54, 0xee, 0x36, + 0x54, 0x65, 0x4a, 0xd0, 0x5c, 0x84, 0x8c, 0x3e, 0x1b, 0xfe, 0x91, 0x6f, 0x95, 0xb5, 0x76, 0xbf, + 0x61, 0x2a, 0x7, 0x23, 0x86, 0xb9, 0xe0, 0x19, 0x29, 0xcf, 0xea, 0x3a, 0x1, 0xbf, 0xee, 0x1b, + 0x5e, 0x3c, 0x4, 0xff, 0x1d, 0xcf, 0xa6, 0x56, 0xb3, 0x22, 0xbb, 0x45, 0x4b, 0x7f, 0x83, 0x87, + 0xef, 0x21, 0x5, 0xf7, 0x38, 0x1f, 0x6, 0x4d, 0x71, 0x0b, 0xe3, 0xe1, 0xb7, 0x7e, 0xae, 0x18 +}; +#endif + +static char dh_except_a_pubkey_1024[] = { + 0x5d, 0xa6, 0x7, 0x56, 0x93, 0x89, 0xe5, 0x0f, 0x2a, 0xb5, 0x67, 0x3a, 0xcf, 0xc3, 0x82, 0x83, + 0xf6, 0x88, 0x52, 0x0b, 0xfc, 0x6a, 0x5b, 0x1a, 0x57, 0x87, 0x86, 0xef, 0xda, 0x47, 0xdb, 0x4d, + 0xba, 0xe7, 0x3, 0x5b, 0xe4, 0x70, 0x8b, 0xe0, 0xe1, 0x92, 0x13, 0x86, 0x74, 0x4, 0xdc, 0x6a, + 0x0a, 0x2a, 0x20, 0xec, 0x6d, 0xbf, 0xf0, 0x46, 0xf7, 0x9, 0x2, 0xdb, 0x2f, 0x70, 0x11, 0xdd, + 0xb0, 0x13, 0xa2, 0xc1, 0x58, 0x74, 0x29, 0x19, 0x8d, 0x4a, 0x94, 0x80, 0x0b, 0xd7, 0x25, 0x85, + 0x10, 0x35, 0x97, 0x48, 0x6e, 0x70, 0x28, 0xae, 0x58, 0x97, 0x7d, 0xf2, 0x19, 0x27, 0x13, 0xab, + 0x47, 0x9b, 0x54, 0xdf, 0xc3, 0x5b, 0x5f, 0x5e, 0xb4, 0x64, 0x47, 0xce, 0x40, 0x3b, 0x0c, 0x4a, + 0x62, 0x52, 0xba, 0xc7, 0xf0, 0x36, 0x87, 0x9c, 0x79, 0x9a, 0x83, 0x11, 0x61, 0x0c, 0x1b, 0x6b +}; + +static char dh_except_b_pubkey_1024[] = { + 0x4a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x7, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x3, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x1, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7 +}; + +static char dh_share_key_1024[] = { + 0xcc, 0x48, 0x97, 0xe4, 0x21, 0x65, 0xa6, 0x55, 0xb8, 0xf3, 0xb2, 0x7b, 0x91, 0xd7, 0xca, 0xb9, + 0x17, 0x58, 0x31, 0x71, 0xc0, 0xc9, 0x69, 0x1e, 0xf0, 0x9e, 0x3f, 0xe2, 0x37, 0x4, 0x2d, 0xa8, + 0x55, 0x9, 0x6b, 0x9c, 0xc6, 0x37, 0xa9, 0x9b, 0xdf, 0x67, 0x73, 0x7b, 0x46, 0xf9, 0x63, 0x47, + 0xcb, 0xa0, 0x57, 0x2a, 0xed, 0x97, 0x2f, 0xfe, 0x92, 0xf2, 0x20, 0x2c, 0x7e, 0xee, 0x7d, 0x11, + 0x78, 0xe6, 0xb9, 0x9, 0xd1, 0x94, 0xce, 0xd1, 0x5b, 0xf4, 0x44, 0xa9, 0xcb, 0x26, 0x2, 0x36, + 0x57, 0x2c, 0xa2, 0xbe, 0x37, 0xde, 0x86, 0x46, 0x20, 0x27, 0x9d, 0xa0, 0x2f, 0x4, 0xc1, 0xcd, + 0xff, 0x81, 0xe5, 0xe6, 0x2c, 0x9e, 0x39, 0x82, 0x31, 0x54, 0x33, 0xf8, 0xe7, 0xa0, 0xe5, 0x96, + 0xa4, 0x40, 0xc4, 0x44, 0xfe, 0x93, 0x66, 0xe2, 0xda, 0xaa, 0xb8, 0xfb, 0x2f, 0x3b, 0x8c, 0xce, +}; + +static char dh_p_1536[] = { + 0xe3,0x7d,0xa7,0x4a,0xcc,0xef,0xce,0xa6,0xde,0x1d,0x3d,0xc5,0x2b,0xaa,0x6b,0x83, + 0xec,0x87,0x60,0xcd,0xc6,0xe4,0x16,0x0d,0xe7,0xb9,0x20,0x0e,0x10,0x50,0x35,0x22, + 0xd6,0xdb,0xbf,0x6,0xcc,0x7b,0x8e,0xe1,0x68,0x38,0x76,0x5f,0x0a,0x68,0xa8,0xfd, + 0x3f,0x40,0x51,0x46,0x45,0x64,0x53,0x22,0xcf,0x8,0xe2,0xef,0xd2,0x6f,0x28,0x84, + 0x14,0xb3,0xa6,0x24,0x49,0x6f,0x49,0x6c,0x0a,0x13,0xb6,0x78,0x4f,0xa4,0xd0,0xc4, + 0x20,0x6c,0x7,0x4c,0x6b,0xf7,0x8c,0x72,0x16,0x6c,0x99,0xd2,0x44,0x9e,0x63,0x5, + 0xfc,0x3a,0xa9,0x33,0x16,0x0b,0xc4,0x1a,0xf0,0xc7,0x25,0xcd,0xc6,0x3a,0x8e,0x66, + 0xa2,0xeb,0x70,0xb9,0x59,0xd9,0xb7,0xdd,0x68,0x45,0x26,0x20,0xfa,0x58,0x6f,0xd6, + 0x3f,0xd8,0xf2,0x52,0xd5,0x3a,0x16,0x7,0xdd,0xb4,0x63,0x0c,0xfe,0x8,0x67,0xd0, + 0x9f,0x8a,0xe0,0xe9,0x25,0xa0,0x0e,0x5,0x8e,0xe5,0x56,0xa6,0xc3,0x5b,0x0b,0xb5, + 0x41,0x33,0xd0,0xdb,0x89,0xbd,0x3b,0xaf,0x33,0x7e,0xae,0xff,0x20,0xef,0xa9,0x3c, + 0xd7,0xb5,0x45,0x61,0x50,0x76,0x60,0x89,0x6a,0xbb,0x9c,0x3e,0xcb,0xcb,0xdb,0x0b, +}; + +static char dh_xa_1536[] = { + 0x56,0x68,0x23,0x22,0x49,0x24,0xf2,0x21,0xee,0x5f,0x12,0x46,0xe2,0xea,0x69,0x93, + 0x0,0xf5,0x10,0x1d,0x4d,0x96,0x7b,0xa4,0x9d,0xab,0xbe,0xdf,0x8e,0xcc,0xa5,0x0e, + 0x84,0x12,0x4e,0x77,0xc0,0x46,0x6b,0x51,0x11,0x46,0x4f,0x73,0x1e,0x1c,0x1c,0xd1, + 0x3,0xea,0x0e,0x11,0xdb,0xa3,0xa6,0x14,0xdb,0xdc,0x3e,0xc5,0x7f,0x7d,0x7a,0x69, + 0xa1,0x38,0x70,0x95,0xa5,0x2d,0x47,0xa3,0x0f,0xcf,0xf9,0x7c,0x2,0x4e,0x52,0x4c, + 0xd6,0x5b,0x9e,0xf3,0x7f,0x64,0x70,0x13,0x59,0x8e,0x44,0x31,0x92,0x1b,0xb4,0xaa, + 0xf9,0x64,0xfd,0xb7,0x3c,0x81,0xc0,0xf9,0x66,0x5d,0xff,0x9,0x3e,0x26,0xaf,0x1a, + 0xc0,0xd2,0xd9,0x7c,0x0e,0x6f,0x81,0x12,0x82,0x90,0x1b,0x37,0xb7,0x1a,0x7e,0x36, + 0x79,0x15,0xb1,0xe1,0xd5,0x2d,0x72,0xd4,0x47,0xf7,0x30,0x3c,0x17,0xe1,0x76,0x15, + 0xbc,0x17,0xdc,0x9d,0xd9,0xfc,0xfd,0xb6,0xe6,0xbd,0x8e,0x47,0x8d,0xbb,0xa8,0x8a, + 0xe7,0xe7,0x57,0xf2,0xd8,0x80,0x4c,0xdd,0xe7,0xaf,0x29,0xee,0x40,0x4e,0x2,0xad, + 0xec,0xb3,0x18,0x8e,0x4b,0x2d,0xd2,0x28,0x4e,0x58,0x85,0x29,0xe3,0x93,0x1b,0xa7, +}; + +#if 0 +static char dh_xb_1536[] = { + 0x5c, 0xdf, 0x3, 0x2f, 0x18, 0xac, 0xbc, 0xeb, 0x95, 0xa2, 0x33, 0x70, 0x39, 0x13, 0x92, 0x7e, + 0x91, 0x19, 0x89, 0xd4, 0x0, 0xd1, 0xc5, 0x7e, 0x32, 0xb7, 0x4a, 0xd2, 0xff, 0x11, 0x7a, 0x9b, + 0x2, 0x84, 0xd0, 0x8e, 0x19, 0x91, 0x34, 0xc2, 0x5, 0xff, 0xe4, 0xf4, 0xd8, 0xcf, 0xc8, 0xa0, + 0xeb, 0x19, 0xb9, 0x69, 0x60, 0xcd, 0xa8, 0xda, 0x33, 0xbc, 0xa7, 0x80, 0x0, 0x92, 0x27, 0xe0, + 0xe7, 0x34, 0x77, 0x1f, 0xfd, 0x56, 0x0, 0x0c, 0x57, 0x0, 0x6d, 0x47, 0xe4, 0x32, 0xd7, 0x22, + 0x64, 0xa5, 0x33, 0x65, 0x33, 0x3e, 0x7c, 0x4e, 0x9d, 0xa6, 0xb7, 0x8b, 0xd7, 0xaa, 0x72, 0xe5, + 0x9d, 0xd5, 0xb4, 0x25, 0xcb, 0x30, 0x2, 0xfc, 0xb5, 0xae, 0xb3, 0x88, 0x67, 0x55, 0x0a, 0x7e, + 0x9d, 0xe8, 0x32, 0xfb, 0x50, 0x79, 0x4e, 0x9b, 0x21, 0x92, 0x25, 0x3, 0xa0, 0x15, 0x52, 0x3d, + 0x5e, 0x21, 0x0a, 0x9e, 0x3, 0xdd, 0x3f, 0xcc, 0x38, 0xf6, 0xa9, 0xa6, 0xf8, 0xfd, 0x15, 0x7d, + 0x67, 0x4e, 0x14, 0xae, 0x4d, 0xe2, 0x1f, 0x78, 0x77, 0xfb, 0x83, 0x5f, 0x48, 0xa8, 0xc8, 0x21, + 0x8b, 0xd9, 0xf8, 0x14, 0xe6, 0x42, 0x95, 0xbd, 0x9a, 0x96, 0xbe, 0xf4, 0x7d, 0x26, 0x5d, 0xa1, + 0x81, 0x9b, 0x1c, 0xec, 0xfe, 0xce, 0x9, 0x1d, 0xb7, 0x7a, 0xba, 0xca, 0x7f, 0x54, 0xee, 0x36, +}; +#endif + +static char dh_except_a_pubkey_1536[] = { + 0x97,0x1e,0x6d,0xf7,0xb1,0x2f,0xa7,0x82,0x9e,0x99,0x22,0xfb,0xf3,0x4e,0x2a,0x73, + 0xcc,0xd9,0x2b,0x10,0x1,0xfb,0xac,0xf1,0x81,0xfe,0x78,0x3d,0x23,0xb0,0xcf,0x5c, + 0x95,0x69,0x36,0xc0,0x99,0x6a,0xd2,0x9c,0xf0,0x85,0x8d,0xda,0x5d,0xba,0x8e,0x0f, + 0xa3,0xce,0xbe,0x9b,0xe8,0x3b,0xad,0x71,0xfd,0xfd,0x53,0x25,0xee,0x61,0x26,0x15, + 0x0a,0x46,0x9e,0xce,0x85,0xb1,0x5c,0xf1,0xa0,0x8f,0xe7,0x89,0xe3,0x4f,0x7c,0xea, + 0x18,0xd3,0xa9,0x44,0xce,0x35,0x9,0x86,0x80,0x8c,0x30,0x1,0xbc,0x6d,0xf6,0x6a, + 0x3a,0xa6,0xad,0xbe,0xfa,0x73,0x6b,0xb0,0x35,0x8c,0x63,0x80,0xb6,0x58,0x51,0x6e, + 0x4c,0x5d,0x4a,0xe9,0xa9,0x72,0x6,0x9f,0xa2,0x3e,0x64,0xaf,0x70,0x63,0xee,0x2a, + 0x5d,0x73,0xf3,0xdc,0xa3,0x32,0x0f,0x8,0x48,0xcf,0x13,0x80,0x0d,0xdb,0x91,0xdf, + 0x87,0x99,0xa4,0x8a,0x50,0xe9,0x75,0x43,0xfb,0x56,0xd7,0x89,0xc3,0x10,0x7e,0xd0, + 0xb7,0x46,0xd8,0x41,0x91,0xdf,0xb1,0x91,0x8e,0xc1,0x58,0xd7,0x7c,0x33,0x1e,0xb3, + 0xa3,0xda,0xcb,0xf5,0x0,0x76,0xe4,0xee,0x20,0xd6,0x9d,0x8a,0x28,0xa4,0xdb,0xf9, +}; + +static char dh_except_b_pubkey_1536[] = { + 0x44, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x9, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x4, 0xe8, 0x9a, 0xd2, 0x0, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x0, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x5, + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x7, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x3, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, +}; + +static char dh_share_key_1536[] = { + 0xaf, 0xd4, 0xf6, 0x45, 0x63, 0x21, 0x8d, 0x98, 0xc4, 0xab, 0x18, 0xd7, 0x2b, 0x3c, 0x1d, 0xde, + 0xe7, 0x1f, 0xe1, 0xc5, 0x79, 0x57, 0x60, 0x20, 0xfa, 0x99, 0xbd, 0x7b, 0xa2, 0x94, 0x0b, 0xa3, + 0xb4, 0xb3, 0x33, 0x4a, 0x2f, 0xd0, 0x17, 0x7, 0x2e, 0x70, 0x19, 0x84, 0x1f, 0x8e, 0xe9, 0x61, + 0xe5, 0x52, 0x3, 0x96, 0xea, 0xd8, 0xb6, 0x3, 0x9f, 0xc4, 0x3e, 0x23, 0x77, 0x17, 0x54, 0xfb, + 0x13, 0xf0, 0x3e, 0x9a, 0x27, 0x5d, 0x12, 0x99, 0x58, 0x8d, 0x41, 0x46, 0xd9, 0xc9, 0x29, 0xbd, + 0x40, 0xd1, 0x4f, 0xef, 0x63, 0x7b, 0x54, 0xe6, 0x59, 0x6d, 0xe2, 0x30, 0xe8, 0x2c, 0x2f, 0xf9, + 0x66, 0xa2, 0x12, 0xf5, 0x58, 0x61, 0xac, 0x43, 0xec, 0x7e, 0xf9, 0x2e, 0x27, 0x70, 0x35, 0x75, + 0xb4, 0x10, 0x29, 0xac, 0x0a, 0xab, 0x59, 0xb6, 0x68, 0x4c, 0x16, 0xaf, 0xf0, 0x4f, 0x21, 0xcd, + 0xcc, 0x48, 0x97, 0xe4, 0x21, 0x65, 0xa6, 0x55, 0xb8, 0xf3, 0xb2, 0x7b, 0x91, 0xd7, 0xca, 0xb9, + 0x17, 0x58, 0x31, 0x71, 0xc0, 0xc9, 0x69, 0x1e, 0xf0, 0x9e, 0x3f, 0xe2, 0x37, 0x4, 0x2d, 0xa8, + 0x55, 0x9, 0x6b, 0x9c, 0xc6, 0x37, 0xa9, 0x9b, 0xdf, 0x67, 0x73, 0x7b, 0x46, 0xf9, 0x63, 0x47, + 0xcb, 0xa0, 0x57, 0x2a, 0xed, 0x97, 0x2f, 0xfe, 0x92, 0xf2, 0x20, 0x2c, 0x7e, 0xee, 0x7d, 0x11, +}; + +static char dh_p_2048[] = { + 0xce, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x09, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x04, 0xe8, 0x9a, 0xd2, 0x00, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x00, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x05, + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x07, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x03, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x01, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7 +}; + +static char dh_xa_2048[] = { + 0x6b, 0x1f, 0xc4, 0x85, 0x98, 0xc3, 0x01, 0xda, 0x39, 0xf0, 0x1b, 0x76, 0x5d, 0x81, 0x1d, 0x1f, + 0xc9, 0x93, 0x95, 0xc1, 0xf8, 0xd1, 0x67, 0x2c, 0xd4, 0x0a, 0x67, 0xf0, 0x40, 0x86, 0x82, 0x7f, + 0x8f, 0x9d, 0x79, 0x04, 0xee, 0x4a, 0x54, 0xc9, 0x9c, 0x7f, 0xda, 0x15, 0x13, 0xc6, 0x95, 0xfb, + 0xfc, 0x7b, 0xe7, 0xd8, 0xde, 0x2a, 0xd8, 0xfd, 0xff, 0xdb, 0xa4, 0x7f, 0x4b, 0x37, 0x5d, 0x42, + 0xb6, 0x46, 0x4c, 0xbc, 0x34, 0x23, 0x99, 0x74, 0xf8, 0x80, 0x1b, 0xc1, 0x97, 0x34, 0xdf, 0x23, + 0x15, 0xa2, 0x8b, 0xec, 0xf3, 0x3e, 0x20, 0x93, 0x63, 0x88, 0x17, 0x70, 0x75, 0xbb, 0x9d, 0xb8, + 0x32, 0xb0, 0xae, 0xb5, 0x24, 0x6a, 0x86, 0xf6, 0xc1, 0x60, 0x41, 0xc4, 0xf4, 0x95, 0x6e, 0x10, + 0x2f, 0xd8, 0x58, 0x56, 0x42, 0x82, 0x71, 0x85, 0x19, 0xde, 0x91, 0xf0, 0x2f, 0x30, 0x0c, 0x63, + 0x0f, 0x2a, 0x77, 0x25, 0x4b, 0xb3, 0xd3, 0x2d, 0xfd, 0x94, 0x8b, 0x53, 0x02, 0x21, 0x40, 0xd7, + 0x36, 0x76, 0xf3, 0xc8, 0xc0, 0x36, 0x3d, 0x23, 0xc9, 0xbd, 0x92, 0x51, 0xf2, 0x4b, 0x83, 0x15, + 0xe0, 0x80, 0x86, 0x24, 0xe2, 0x20, 0x35, 0x97, 0xda, 0x0e, 0x68, 0x39, 0x01, 0xdd, 0x01, 0x87, + 0xa2, 0x47, 0xd2, 0x0d, 0xee, 0xfe, 0xdc, 0x5a, 0x37, 0x23, 0xeb, 0x3d, 0xe8, 0x1e, 0x39, 0x2d, + 0xbf, 0xa6, 0xe9, 0x17, 0x48, 0xe2, 0xea, 0xef, 0x1d, 0x2f, 0xe2, 0xaf, 0x3c, 0xbc, 0xae, 0xa7, + 0x42, 0x9b, 0xa5, 0x7d, 0x47, 0x8a, 0x20, 0xc5, 0xae, 0xa1, 0xe4, 0xe8, 0x1c, 0x05, 0xc0, 0x0a, + 0x05, 0xdc, 0x01, 0x74, 0xde, 0xad, 0xad, 0x07, 0xec, 0x6e, 0x6a, 0xc7, 0xee, 0x0f, 0xb8, 0xbe, + 0xaa, 0x46, 0x61, 0x8c, 0x12, 0x5a, 0xaf, 0x05, 0xff, 0x1b, 0x35, 0x6b, 0xe2, 0x3d, 0x48, 0x4f +}; + +#if 0 +static char dh_xb_2048[] = { + 0x5c, 0xdf, 0x3, 0x2f, 0x18, 0xac, 0xbc, 0xeb, 0x95, 0xa2, 0x33, 0x70, 0x39, 0x13, 0x92, 0x7e, + 0x91, 0x19, 0x89, 0xd4, 0x0, 0xd1, 0xc5, 0x7e, 0x32, 0xb7, 0x4a, 0xd2, 0xff, 0x11, 0x7a, 0x9b, + 0x2, 0x84, 0xd0, 0x8e, 0x19, 0x91, 0x34, 0xc2, 0x5, 0xff, 0xe4, 0xf4, 0xd8, 0xcf, 0xc8, 0xa0, + 0xeb, 0x19, 0xb9, 0x69, 0x60, 0xcd, 0xa8, 0xda, 0x33, 0xbc, 0xa7, 0x80, 0x0, 0x92, 0x27, 0xe0, + 0xe7, 0x34, 0x77, 0x1f, 0xfd, 0x56, 0x0, 0x0c, 0x57, 0x0, 0x6d, 0x47, 0xe4, 0x32, 0xd7, 0x22, + 0x64, 0xa5, 0x33, 0x65, 0x33, 0x3e, 0x7c, 0x4e, 0x9d, 0xa6, 0xb7, 0x8b, 0xd7, 0xaa, 0x72, 0xe5, + 0x9d, 0xd5, 0xb4, 0x25, 0xcb, 0x30, 0x2, 0xfc, 0xb5, 0xae, 0xb3, 0x88, 0x67, 0x55, 0x0a, 0x7e, + 0x9d, 0xe8, 0x32, 0xfb, 0x50, 0x79, 0x4e, 0x9b, 0x21, 0x92, 0x25, 0x3, 0xa0, 0x15, 0x52, 0x3d, + 0x5e, 0x21, 0x0a, 0x9e, 0x3, 0xdd, 0x3f, 0xcc, 0x38, 0xf6, 0xa9, 0xa6, 0xf8, 0xfd, 0x15, 0x7d, + 0x67, 0x4e, 0x14, 0xae, 0x4d, 0xe2, 0x1f, 0x78, 0x77, 0xfb, 0x83, 0x5f, 0x48, 0xa8, 0xc8, 0x21, + 0x8b, 0xd9, 0xf8, 0x14, 0xe6, 0x42, 0x95, 0xbd, 0x9a, 0x96, 0xbe, 0xf4, 0x7d, 0x26, 0x5d, 0xa1, + 0x81, 0x9b, 0x1c, 0xec, 0xfe, 0xce, 0x9, 0x1d, 0xb7, 0x7a, 0xba, 0xca, 0x7f, 0x54, 0xee, 0x36, + 0x54, 0x65, 0x4a, 0xd0, 0x5c, 0x84, 0x8c, 0x3e, 0x1b, 0xfe, 0x91, 0x6f, 0x95, 0xb5, 0x76, 0xbf, + 0x61, 0x2a, 0x7, 0x23, 0x86, 0xb9, 0xe0, 0x19, 0x29, 0xcf, 0xea, 0x3a, 0x1, 0xbf, 0xee, 0x1b, + 0x5e, 0x3c, 0x4, 0xff, 0x1d, 0xcf, 0xa6, 0x56, 0xb3, 0x22, 0xbb, 0x45, 0x4b, 0x7f, 0x83, 0x87, + 0xef, 0x21, 0x5, 0xf7, 0x38, 0x1f, 0x6, 0x4d, 0x71, 0x0b, 0xe3, 0xe1, 0xb7, 0x7e, 0xae, 0x18 +}; +#endif + +static char dh_except_a_pubkey_2048[] = { + 0xa5, 0x24, 0x63, 0x20, 0xb2, 0x56, 0x9a, 0x94, 0x97, 0xf7, 0x88, 0x41, 0x35, 0xeb, 0x52, 0x37, + 0xa4, 0xf2, 0x74, 0x1b, 0x38, 0xe4, 0x4c, 0x8b, 0x4b, 0xd2, 0xa5, 0xad, 0xb8, 0x2f, 0x7b, 0x5a, + 0xfd, 0xbc, 0x9c, 0xe0, 0xea, 0x9e, 0x82, 0x3, 0x62, 0xe2, 0xdc, 0x6c, 0x56, 0x9, 0x2, 0x28, + 0xb8, 0x2d, 0xb8, 0x46, 0xaf, 0x3a, 0xf4, 0x51, 0xf7, 0x4d, 0xc4, 0xd9, 0xa9, 0x1d, 0x67, 0x9d, + 0x2b, 0x18, 0x56, 0x86, 0x2a, 0x3, 0x19, 0xe9, 0x6, 0xeb, 0x4a, 0x6f, 0x2a, 0x40, 0x28, 0xbb, + 0x3e, 0x87, 0xc1, 0xce, 0x39, 0x6e, 0x3b, 0x1f, 0xb0, 0x9, 0x33, 0x67, 0x19, 0x0e, 0x1a, 0xb2, + 0xb3, 0x7d, 0xd3, 0xe6, 0x33, 0xf4, 0x7c, 0x82, 0x73, 0x7b, 0xb6, 0x16, 0x55, 0xff, 0x76, 0xaf, + 0x7f, 0xc2, 0x42, 0x51, 0xa9, 0xad, 0x1e, 0x72, 0xc9, 0x63, 0xab, 0x41, 0x5a, 0x26, 0x32, 0x39, + 0x5d, 0xa6, 0x7, 0x56, 0x93, 0x89, 0xe5, 0x0f, 0x2a, 0xb5, 0x67, 0x3a, 0xcf, 0xc3, 0x82, 0x83, + 0xf6, 0x88, 0x52, 0x0b, 0xfc, 0x6a, 0x5b, 0x1a, 0x57, 0x87, 0x86, 0xef, 0xda, 0x47, 0xdb, 0x4d, + 0xba, 0xe7, 0x3, 0x5b, 0xe4, 0x70, 0x8b, 0xe0, 0xe1, 0x92, 0x13, 0x86, 0x74, 0x4, 0xdc, 0x6a, + 0x0a, 0x2a, 0x20, 0xec, 0x6d, 0xbf, 0xf0, 0x46, 0xf7, 0x9, 0x2, 0xdb, 0x2f, 0x70, 0x11, 0xdd, + 0xb0, 0x13, 0xa2, 0xc1, 0x58, 0x74, 0x29, 0x19, 0x8d, 0x4a, 0x94, 0x80, 0x0b, 0xd7, 0x25, 0x85, + 0x10, 0x35, 0x97, 0x48, 0x6e, 0x70, 0x28, 0xae, 0x58, 0x97, 0x7d, 0xf2, 0x19, 0x27, 0x13, 0xab, + 0x47, 0x9b, 0x54, 0xdf, 0xc3, 0x5b, 0x5f, 0x5e, 0xb4, 0x64, 0x47, 0xce, 0x40, 0x3b, 0x0c, 0x4a, + 0x62, 0x52, 0xba, 0xc7, 0xf0, 0x36, 0x87, 0x9c, 0x79, 0x9a, 0x83, 0x11, 0x61, 0x0c, 0x1b, 0x6b +}; + +static char dh_except_b_pubkey_2048[] = { + 0x44, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x9, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x4, 0xe8, 0x9a, 0xd2, 0x0, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x0, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x5, + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x7, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x3, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x1, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7 +}; + +static char dh_share_key_2048[] = { + 0xaf, 0xd4, 0xf6, 0x45, 0x63, 0x21, 0x8d, 0x98, 0xc4, 0xab, 0x18, 0xd7, 0x2b, 0x3c, 0x1d, 0xde, + 0xe7, 0x1f, 0xe1, 0xc5, 0x79, 0x57, 0x60, 0x20, 0xfa, 0x99, 0xbd, 0x7b, 0xa2, 0x94, 0x0b, 0xa3, + 0xb4, 0xb3, 0x33, 0x4a, 0x2f, 0xd0, 0x17, 0x7, 0x2e, 0x70, 0x19, 0x84, 0x1f, 0x8e, 0xe9, 0x61, + 0xe5, 0x52, 0x3, 0x96, 0xea, 0xd8, 0xb6, 0x3, 0x9f, 0xc4, 0x3e, 0x23, 0x77, 0x17, 0x54, 0xfb, + 0x13, 0xf0, 0x3e, 0x9a, 0x27, 0x5d, 0x12, 0x99, 0x58, 0x8d, 0x41, 0x46, 0xd9, 0xc9, 0x29, 0xbd, + 0x40, 0xd1, 0x4f, 0xef, 0x63, 0x7b, 0x54, 0xe6, 0x59, 0x6d, 0xe2, 0x30, 0xe8, 0x2c, 0x2f, 0xf9, + 0x66, 0xa2, 0x12, 0xf5, 0x58, 0x61, 0xac, 0x43, 0xec, 0x7e, 0xf9, 0x2e, 0x27, 0x70, 0x35, 0x75, + 0xb4, 0x10, 0x29, 0xac, 0x0a, 0xab, 0x59, 0xb6, 0x68, 0x4c, 0x16, 0xaf, 0xf0, 0x4f, 0x21, 0xcd, + 0xcc, 0x48, 0x97, 0xe4, 0x21, 0x65, 0xa6, 0x55, 0xb8, 0xf3, 0xb2, 0x7b, 0x91, 0xd7, 0xca, 0xb9, + 0x17, 0x58, 0x31, 0x71, 0xc0, 0xc9, 0x69, 0x1e, 0xf0, 0x9e, 0x3f, 0xe2, 0x37, 0x4, 0x2d, 0xa8, + 0x55, 0x9, 0x6b, 0x9c, 0xc6, 0x37, 0xa9, 0x9b, 0xdf, 0x67, 0x73, 0x7b, 0x46, 0xf9, 0x63, 0x47, + 0xcb, 0xa0, 0x57, 0x2a, 0xed, 0x97, 0x2f, 0xfe, 0x92, 0xf2, 0x20, 0x2c, 0x7e, 0xee, 0x7d, 0x11, + 0x78, 0xe6, 0xb9, 0x9, 0xd1, 0x94, 0xce, 0xd1, 0x5b, 0xf4, 0x44, 0xa9, 0xcb, 0x26, 0x2, 0x36, + 0x57, 0x2c, 0xa2, 0xbe, 0x37, 0xde, 0x86, 0x46, 0x20, 0x27, 0x9d, 0xa0, 0x2f, 0x4, 0xc1, 0xcd, + 0xff, 0x81, 0xe5, 0xe6, 0x2c, 0x9e, 0x39, 0x82, 0x31, 0x54, 0x33, 0xf8, 0xe7, 0xa0, 0xe5, 0x96, + 0xa4, 0x40, 0xc4, 0x44, 0xfe, 0x93, 0x66, 0xe2, 0xda, 0xaa, 0xb8, 0xfb, 0x2f, 0x3b, 0x8c, 0xce, +}; + +static char dh_p_3072[] = { + 0xce, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x09, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x04, 0xe8, 0x9a, 0xd2, 0x00, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x00, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x05, + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x07, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x03, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x01, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7, + 0xce, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x09, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x04, 0xe8, 0x9a, 0xd2, 0x00, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x00, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x05, +}; + +static char dh_xa_3072[] = { + 0x6b, 0x1f, 0xc4, 0x85, 0x98, 0xc3, 0x01, 0xda, 0x39, 0xf0, 0x1b, 0x76, 0x5d, 0x81, 0x1d, 0x1f, + 0xc9, 0x93, 0x95, 0xc1, 0xf8, 0xd1, 0x67, 0x2c, 0xd4, 0x0a, 0x67, 0xf0, 0x40, 0x86, 0x82, 0x7f, + 0x8f, 0x9d, 0x79, 0x04, 0xee, 0x4a, 0x54, 0xc9, 0x9c, 0x7f, 0xda, 0x15, 0x13, 0xc6, 0x95, 0xfb, + 0xfc, 0x7b, 0xe7, 0xd8, 0xde, 0x2a, 0xd8, 0xfd, 0xff, 0xdb, 0xa4, 0x7f, 0x4b, 0x37, 0x5d, 0x42, + 0xb6, 0x46, 0x4c, 0xbc, 0x34, 0x23, 0x99, 0x74, 0xf8, 0x80, 0x1b, 0xc1, 0x97, 0x34, 0xdf, 0x23, + 0x15, 0xa2, 0x8b, 0xec, 0xf3, 0x3e, 0x20, 0x93, 0x63, 0x88, 0x17, 0x70, 0x75, 0xbb, 0x9d, 0xb8, + 0x32, 0xb0, 0xae, 0xb5, 0x24, 0x6a, 0x86, 0xf6, 0xc1, 0x60, 0x41, 0xc4, 0xf4, 0x95, 0x6e, 0x10, + 0x2f, 0xd8, 0x58, 0x56, 0x42, 0x82, 0x71, 0x85, 0x19, 0xde, 0x91, 0xf0, 0x2f, 0x30, 0x0c, 0x63, + 0x0f, 0x2a, 0x77, 0x25, 0x4b, 0xb3, 0xd3, 0x2d, 0xfd, 0x94, 0x8b, 0x53, 0x02, 0x21, 0x40, 0xd7, + 0x36, 0x76, 0xf3, 0xc8, 0xc0, 0x36, 0x3d, 0x23, 0xc9, 0xbd, 0x92, 0x51, 0xf2, 0x4b, 0x83, 0x15, + 0xe0, 0x80, 0x86, 0x24, 0xe2, 0x20, 0x35, 0x97, 0xda, 0x0e, 0x68, 0x39, 0x01, 0xdd, 0x01, 0x87, + 0xa2, 0x47, 0xd2, 0x0d, 0xee, 0xfe, 0xdc, 0x5a, 0x37, 0x23, 0xeb, 0x3d, 0xe8, 0x1e, 0x39, 0x2d, + 0xbf, 0xa6, 0xe9, 0x17, 0x48, 0xe2, 0xea, 0xef, 0x1d, 0x2f, 0xe2, 0xaf, 0x3c, 0xbc, 0xae, 0xa7, + 0x42, 0x9b, 0xa5, 0x7d, 0x47, 0x8a, 0x20, 0xc5, 0xae, 0xa1, 0xe4, 0xe8, 0x1c, 0x05, 0xc0, 0x0a, + 0x05, 0xdc, 0x01, 0x74, 0xde, 0xad, 0xad, 0x07, 0xec, 0x6e, 0x6a, 0xc7, 0xee, 0x0f, 0xb8, 0xbe, + 0xaa, 0x46, 0x61, 0x8c, 0x12, 0x5a, 0xaf, 0x05, 0xff, 0x1b, 0x35, 0x6b, 0xe2, 0x3d, 0x48, 0x4f, + 0x6b, 0x1f, 0xc4, 0x85, 0x98, 0xc3, 0x01, 0xda, 0x39, 0xf0, 0x1b, 0x76, 0x5d, 0x81, 0x1d, 0x1f, + 0xc9, 0x93, 0x95, 0xc1, 0xf8, 0xd1, 0x67, 0x2c, 0xd4, 0x0a, 0x67, 0xf0, 0x40, 0x86, 0x82, 0x7f, + 0x8f, 0x9d, 0x79, 0x04, 0xee, 0x4a, 0x54, 0xc9, 0x9c, 0x7f, 0xda, 0x15, 0x13, 0xc6, 0x95, 0xfb, + 0xfc, 0x7b, 0xe7, 0xd8, 0xde, 0x2a, 0xd8, 0xfd, 0xff, 0xdb, 0xa4, 0x7f, 0x4b, 0x37, 0x5d, 0x42, + 0xb6, 0x46, 0x4c, 0xbc, 0x34, 0x23, 0x99, 0x74, 0xf8, 0x80, 0x1b, 0xc1, 0x97, 0x34, 0xdf, 0x23, + 0x15, 0xa2, 0x8b, 0xec, 0xf3, 0x3e, 0x20, 0x93, 0x63, 0x88, 0x17, 0x70, 0x75, 0xbb, 0x9d, 0xb8, + 0x32, 0xb0, 0xae, 0xb5, 0x24, 0x6a, 0x86, 0xf6, 0xc1, 0x60, 0x41, 0xc4, 0xf4, 0x95, 0x6e, 0x10, + 0x2f, 0xd8, 0x58, 0x56, 0x42, 0x82, 0x71, 0x85, 0x19, 0xde, 0x91, 0xf0, 0x2f, 0x30, 0x0c, 0x63, +}; + +#if 0 +static char dh_xb_3072[] = { + 0x5c, 0xdf, 0x3, 0x2f, 0x18, 0xac, 0xbc, 0xeb, 0x95, 0xa2, 0x33, 0x70, 0x39, 0x13, 0x92, 0x7e, + 0x91, 0x19, 0x89, 0xd4, 0x0, 0xd1, 0xc5, 0x7e, 0x32, 0xb7, 0x4a, 0xd2, 0xff, 0x11, 0x7a, 0x9b, + 0x2, 0x84, 0xd0, 0x8e, 0x19, 0x91, 0x34, 0xc2, 0x5, 0xff, 0xe4, 0xf4, 0xd8, 0xcf, 0xc8, 0xa0, + 0xeb, 0x19, 0xb9, 0x69, 0x60, 0xcd, 0xa8, 0xda, 0x33, 0xbc, 0xa7, 0x80, 0x0, 0x92, 0x27, 0xe0, + 0xe7, 0x34, 0x77, 0x1f, 0xfd, 0x56, 0x0, 0x0c, 0x57, 0x0, 0x6d, 0x47, 0xe4, 0x32, 0xd7, 0x22, + 0x64, 0xa5, 0x33, 0x65, 0x33, 0x3e, 0x7c, 0x4e, 0x9d, 0xa6, 0xb7, 0x8b, 0xd7, 0xaa, 0x72, 0xe5, + 0x9d, 0xd5, 0xb4, 0x25, 0xcb, 0x30, 0x2, 0xfc, 0xb5, 0xae, 0xb3, 0x88, 0x67, 0x55, 0x0a, 0x7e, + 0x9d, 0xe8, 0x32, 0xfb, 0x50, 0x79, 0x4e, 0x9b, 0x21, 0x92, 0x25, 0x3, 0xa0, 0x15, 0x52, 0x3d, + 0x5e, 0x21, 0x0a, 0x9e, 0x3, 0xdd, 0x3f, 0xcc, 0x38, 0xf6, 0xa9, 0xa6, 0xf8, 0xfd, 0x15, 0x7d, + 0x67, 0x4e, 0x14, 0xae, 0x4d, 0xe2, 0x1f, 0x78, 0x77, 0xfb, 0x83, 0x5f, 0x48, 0xa8, 0xc8, 0x21, + 0x8b, 0xd9, 0xf8, 0x14, 0xe6, 0x42, 0x95, 0xbd, 0x9a, 0x96, 0xbe, 0xf4, 0x7d, 0x26, 0x5d, 0xa1, + 0x81, 0x9b, 0x1c, 0xec, 0xfe, 0xce, 0x9, 0x1d, 0xb7, 0x7a, 0xba, 0xca, 0x7f, 0x54, 0xee, 0x36, + 0x54, 0x65, 0x4a, 0xd0, 0x5c, 0x84, 0x8c, 0x3e, 0x1b, 0xfe, 0x91, 0x6f, 0x95, 0xb5, 0x76, 0xbf, + 0x61, 0x2a, 0x7, 0x23, 0x86, 0xb9, 0xe0, 0x19, 0x29, 0xcf, 0xea, 0x3a, 0x1, 0xbf, 0xee, 0x1b, + 0x5e, 0x3c, 0x4, 0xff, 0x1d, 0xcf, 0xa6, 0x56, 0xb3, 0x22, 0xbb, 0x45, 0x4b, 0x7f, 0x83, 0x87, + 0xef, 0x21, 0x5, 0xf7, 0x38, 0x1f, 0x6, 0x4d, 0x71, 0x0b, 0xe3, 0xe1, 0xb7, 0x7e, 0xae, 0x18, + 0x5c, 0xdf, 0x3, 0x2f, 0x18, 0xac, 0xbc, 0xeb, 0x95, 0xa2, 0x33, 0x70, 0x39, 0x13, 0x92, 0x7e, + 0x91, 0x19, 0x89, 0xd4, 0x0, 0xd1, 0xc5, 0x7e, 0x32, 0xb7, 0x4a, 0xd2, 0xff, 0x11, 0x7a, 0x9b, + 0x2, 0x84, 0xd0, 0x8e, 0x19, 0x91, 0x34, 0xc2, 0x5, 0xff, 0xe4, 0xf4, 0xd8, 0xcf, 0xc8, 0xa0, + 0xeb, 0x19, 0xb9, 0x69, 0x60, 0xcd, 0xa8, 0xda, 0x33, 0xbc, 0xa7, 0x80, 0x0, 0x92, 0x27, 0xe0, + 0xe7, 0x34, 0x77, 0x1f, 0xfd, 0x56, 0x0, 0x0c, 0x57, 0x0, 0x6d, 0x47, 0xe4, 0x32, 0xd7, 0x22, + 0x64, 0xa5, 0x33, 0x65, 0x33, 0x3e, 0x7c, 0x4e, 0x9d, 0xa6, 0xb7, 0x8b, 0xd7, 0xaa, 0x72, 0xe5, + 0x9d, 0xd5, 0xb4, 0x25, 0xcb, 0x30, 0x2, 0xfc, 0xb5, 0xae, 0xb3, 0x88, 0x67, 0x55, 0x0a, 0x7e, + 0x9d, 0xe8, 0x32, 0xfb, 0x50, 0x79, 0x4e, 0x9b, 0x21, 0x92, 0x25, 0x3, 0xa0, 0x15, 0x52, 0x3d, +}; +#endif + +static char dh_except_a_pubkey_3072[] = { + 0xa5, 0x24, 0x63, 0x20, 0xb2, 0x56, 0x9a, 0x94, 0x97, 0xf7, 0x88, 0x41, 0x35, 0xeb, 0x52, 0x37, + 0xa4, 0xf2, 0x74, 0x1b, 0x38, 0xe4, 0x4c, 0x8b, 0x4b, 0xd2, 0xa5, 0xad, 0xb8, 0x2f, 0x7b, 0x5a, + 0xfd, 0xbc, 0x9c, 0xe0, 0xea, 0x9e, 0x82, 0x3, 0x62, 0xe2, 0xdc, 0x6c, 0x56, 0x9, 0x2, 0x28, + 0xb8, 0x2d, 0xb8, 0x46, 0xaf, 0x3a, 0xf4, 0x51, 0xf7, 0x4d, 0xc4, 0xd9, 0xa9, 0x1d, 0x67, 0x9d, + 0x2b, 0x18, 0x56, 0x86, 0x2a, 0x3, 0x19, 0xe9, 0x6, 0xeb, 0x4a, 0x6f, 0x2a, 0x40, 0x28, 0xbb, + 0x3e, 0x87, 0xc1, 0xce, 0x39, 0x6e, 0x3b, 0x1f, 0xb0, 0x9, 0x33, 0x67, 0x19, 0x0e, 0x1a, 0xb2, + 0xb3, 0x7d, 0xd3, 0xe6, 0x33, 0xf4, 0x7c, 0x82, 0x73, 0x7b, 0xb6, 0x16, 0x55, 0xff, 0x76, 0xaf, + 0x7f, 0xc2, 0x42, 0x51, 0xa9, 0xad, 0x1e, 0x72, 0xc9, 0x63, 0xab, 0x41, 0x5a, 0x26, 0x32, 0x39, + 0x5d, 0xa6, 0x7, 0x56, 0x93, 0x89, 0xe5, 0x0f, 0x2a, 0xb5, 0x67, 0x3a, 0xcf, 0xc3, 0x82, 0x83, + 0xf6, 0x88, 0x52, 0x0b, 0xfc, 0x6a, 0x5b, 0x1a, 0x57, 0x87, 0x86, 0xef, 0xda, 0x47, 0xdb, 0x4d, + 0xba, 0xe7, 0x3, 0x5b, 0xe4, 0x70, 0x8b, 0xe0, 0xe1, 0x92, 0x13, 0x86, 0x74, 0x4, 0xdc, 0x6a, + 0x0a, 0x2a, 0x20, 0xec, 0x6d, 0xbf, 0xf0, 0x46, 0xf7, 0x9, 0x2, 0xdb, 0x2f, 0x70, 0x11, 0xdd, + 0xb0, 0x13, 0xa2, 0xc1, 0x58, 0x74, 0x29, 0x19, 0x8d, 0x4a, 0x94, 0x80, 0x0b, 0xd7, 0x25, 0x85, + 0x10, 0x35, 0x97, 0x48, 0x6e, 0x70, 0x28, 0xae, 0x58, 0x97, 0x7d, 0xf2, 0x19, 0x27, 0x13, 0xab, + 0x47, 0x9b, 0x54, 0xdf, 0xc3, 0x5b, 0x5f, 0x5e, 0xb4, 0x64, 0x47, 0xce, 0x40, 0x3b, 0x0c, 0x4a, + 0x62, 0x52, 0xba, 0xc7, 0xf0, 0x36, 0x87, 0x9c, 0x79, 0x9a, 0x83, 0x11, 0x61, 0x0c, 0x1b, 0x6b, + 0xa5, 0x24, 0x63, 0x20, 0xb2, 0x56, 0x9a, 0x94, 0x97, 0xf7, 0x88, 0x41, 0x35, 0xeb, 0x52, 0x37, + 0xa4, 0xf2, 0x74, 0x1b, 0x38, 0xe4, 0x4c, 0x8b, 0x4b, 0xd2, 0xa5, 0xad, 0xb8, 0x2f, 0x7b, 0x5a, + 0xfd, 0xbc, 0x9c, 0xe0, 0xea, 0x9e, 0x82, 0x3, 0x62, 0xe2, 0xdc, 0x6c, 0x56, 0x9, 0x2, 0x28, + 0xb8, 0x2d, 0xb8, 0x46, 0xaf, 0x3a, 0xf4, 0x51, 0xf7, 0x4d, 0xc4, 0xd9, 0xa9, 0x1d, 0x67, 0x9d, + 0x2b, 0x18, 0x56, 0x86, 0x2a, 0x3, 0x19, 0xe9, 0x6, 0xeb, 0x4a, 0x6f, 0x2a, 0x40, 0x28, 0xbb, + 0x3e, 0x87, 0xc1, 0xce, 0x39, 0x6e, 0x3b, 0x1f, 0xb0, 0x9, 0x33, 0x67, 0x19, 0x0e, 0x1a, 0xb2, + 0xb3, 0x7d, 0xd3, 0xe6, 0x33, 0xf4, 0x7c, 0x82, 0x73, 0x7b, 0xb6, 0x16, 0x55, 0xff, 0x76, 0xaf, + 0x7f, 0xc2, 0x42, 0x51, 0xa9, 0xad, 0x1e, 0x72, 0xc9, 0x63, 0xab, 0x41, 0x5a, 0x26, 0x32, 0x39, +}; + +static char dh_except_b_pubkey_3072[] = { + 0x44, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x9, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x4, 0xe8, 0x9a, 0xd2, 0x0, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x0, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x5, + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x7, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x3, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x1, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7, + 0x44, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x9, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x4, 0xe8, 0x9a, 0xd2, 0x0, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x0, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x5, +}; + +static char dh_share_key_3072[] = { + 0xaf, 0xd4, 0xf6, 0x45, 0x63, 0x21, 0x8d, 0x98, 0xc4, 0xab, 0x18, 0xd7, 0x2b, 0x3c, 0x1d, 0xde, + 0xe7, 0x1f, 0xe1, 0xc5, 0x79, 0x57, 0x60, 0x20, 0xfa, 0x99, 0xbd, 0x7b, 0xa2, 0x94, 0x0b, 0xa3, + 0xb4, 0xb3, 0x33, 0x4a, 0x2f, 0xd0, 0x17, 0x7, 0x2e, 0x70, 0x19, 0x84, 0x1f, 0x8e, 0xe9, 0x61, + 0xe5, 0x52, 0x3, 0x96, 0xea, 0xd8, 0xb6, 0x3, 0x9f, 0xc4, 0x3e, 0x23, 0x77, 0x17, 0x54, 0xfb, + 0x13, 0xf0, 0x3e, 0x9a, 0x27, 0x5d, 0x12, 0x99, 0x58, 0x8d, 0x41, 0x46, 0xd9, 0xc9, 0x29, 0xbd, + 0x40, 0xd1, 0x4f, 0xef, 0x63, 0x7b, 0x54, 0xe6, 0x59, 0x6d, 0xe2, 0x30, 0xe8, 0x2c, 0x2f, 0xf9, + 0x66, 0xa2, 0x12, 0xf5, 0x58, 0x61, 0xac, 0x43, 0xec, 0x7e, 0xf9, 0x2e, 0x27, 0x70, 0x35, 0x75, + 0xb4, 0x10, 0x29, 0xac, 0x0a, 0xab, 0x59, 0xb6, 0x68, 0x4c, 0x16, 0xaf, 0xf0, 0x4f, 0x21, 0xcd, + 0xcc, 0x48, 0x97, 0xe4, 0x21, 0x65, 0xa6, 0x55, 0xb8, 0xf3, 0xb2, 0x7b, 0x91, 0xd7, 0xca, 0xb9, + 0x17, 0x58, 0x31, 0x71, 0xc0, 0xc9, 0x69, 0x1e, 0xf0, 0x9e, 0x3f, 0xe2, 0x37, 0x4, 0x2d, 0xa8, + 0x55, 0x9, 0x6b, 0x9c, 0xc6, 0x37, 0xa9, 0x9b, 0xdf, 0x67, 0x73, 0x7b, 0x46, 0xf9, 0x63, 0x47, + 0xcb, 0xa0, 0x57, 0x2a, 0xed, 0x97, 0x2f, 0xfe, 0x92, 0xf2, 0x20, 0x2c, 0x7e, 0xee, 0x7d, 0x11, + 0x78, 0xe6, 0xb9, 0x9, 0xd1, 0x94, 0xce, 0xd1, 0x5b, 0xf4, 0x44, 0xa9, 0xcb, 0x26, 0x2, 0x36, + 0x57, 0x2c, 0xa2, 0xbe, 0x37, 0xde, 0x86, 0x46, 0x20, 0x27, 0x9d, 0xa0, 0x2f, 0x4, 0xc1, 0xcd, + 0xff, 0x81, 0xe5, 0xe6, 0x2c, 0x9e, 0x39, 0x82, 0x31, 0x54, 0x33, 0xf8, 0xe7, 0xa0, 0xe5, 0x96, + 0xa4, 0x40, 0xc4, 0x44, 0xfe, 0x93, 0x66, 0xe2, 0xda, 0xaa, 0xb8, 0xfb, 0x2f, 0x3b, 0x8c, 0xce, + 0xaf, 0xd4, 0xf6, 0x45, 0x63, 0x21, 0x8d, 0x98, 0xc4, 0xab, 0x18, 0xd7, 0x2b, 0x3c, 0x1d, 0xde, + 0xe7, 0x1f, 0xe1, 0xc5, 0x79, 0x57, 0x60, 0x20, 0xfa, 0x99, 0xbd, 0x7b, 0xa2, 0x94, 0x0b, 0xa3, + 0xb4, 0xb3, 0x33, 0x4a, 0x2f, 0xd0, 0x17, 0x7, 0x2e, 0x70, 0x19, 0x84, 0x1f, 0x8e, 0xe9, 0x61, + 0xe5, 0x52, 0x3, 0x96, 0xea, 0xd8, 0xb6, 0x3, 0x9f, 0xc4, 0x3e, 0x23, 0x77, 0x17, 0x54, 0xfb, + 0x13, 0xf0, 0x3e, 0x9a, 0x27, 0x5d, 0x12, 0x99, 0x58, 0x8d, 0x41, 0x46, 0xd9, 0xc9, 0x29, 0xbd, + 0x40, 0xd1, 0x4f, 0xef, 0x63, 0x7b, 0x54, 0xe6, 0x59, 0x6d, 0xe2, 0x30, 0xe8, 0x2c, 0x2f, 0xf9, + 0x66, 0xa2, 0x12, 0xf5, 0x58, 0x61, 0xac, 0x43, 0xec, 0x7e, 0xf9, 0x2e, 0x27, 0x70, 0x35, 0x75, + 0xb4, 0x10, 0x29, 0xac, 0x0a, 0xab, 0x59, 0xb6, 0x68, 0x4c, 0x16, 0xaf, 0xf0, 0x4f, 0x21, 0xcd, +}; + +static char dh_p_4096[] = { + 0xce, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x09, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x04, 0xe8, 0x9a, 0xd2, 0x00, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x00, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x05, + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x07, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x03, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x01, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7, + 0xce, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x09, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x04, 0xe8, 0x9a, 0xd2, 0x00, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x00, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x05, + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x07, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x03, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x01, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7 +}; + +static char dh_xa_4096[] = { + 0x6b, 0x1f, 0xc4, 0x85, 0x98, 0xc3, 0x01, 0xda, 0x39, 0xf0, 0x1b, 0x76, 0x5d, 0x81, 0x1d, 0x1f, + 0xc9, 0x93, 0x95, 0xc1, 0xf8, 0xd1, 0x67, 0x2c, 0xd4, 0x0a, 0x67, 0xf0, 0x40, 0x86, 0x82, 0x7f, + 0x8f, 0x9d, 0x79, 0x04, 0xee, 0x4a, 0x54, 0xc9, 0x9c, 0x7f, 0xda, 0x15, 0x13, 0xc6, 0x95, 0xfb, + 0xfc, 0x7b, 0xe7, 0xd8, 0xde, 0x2a, 0xd8, 0xfd, 0xff, 0xdb, 0xa4, 0x7f, 0x4b, 0x37, 0x5d, 0x42, + 0xb6, 0x46, 0x4c, 0xbc, 0x34, 0x23, 0x99, 0x74, 0xf8, 0x80, 0x1b, 0xc1, 0x97, 0x34, 0xdf, 0x23, + 0x15, 0xa2, 0x8b, 0xec, 0xf3, 0x3e, 0x20, 0x93, 0x63, 0x88, 0x17, 0x70, 0x75, 0xbb, 0x9d, 0xb8, + 0x32, 0xb0, 0xae, 0xb5, 0x24, 0x6a, 0x86, 0xf6, 0xc1, 0x60, 0x41, 0xc4, 0xf4, 0x95, 0x6e, 0x10, + 0x2f, 0xd8, 0x58, 0x56, 0x42, 0x82, 0x71, 0x85, 0x19, 0xde, 0x91, 0xf0, 0x2f, 0x30, 0x0c, 0x63, + 0x0f, 0x2a, 0x77, 0x25, 0x4b, 0xb3, 0xd3, 0x2d, 0xfd, 0x94, 0x8b, 0x53, 0x02, 0x21, 0x40, 0xd7, + 0x36, 0x76, 0xf3, 0xc8, 0xc0, 0x36, 0x3d, 0x23, 0xc9, 0xbd, 0x92, 0x51, 0xf2, 0x4b, 0x83, 0x15, + 0xe0, 0x80, 0x86, 0x24, 0xe2, 0x20, 0x35, 0x97, 0xda, 0x0e, 0x68, 0x39, 0x01, 0xdd, 0x01, 0x87, + 0xa2, 0x47, 0xd2, 0x0d, 0xee, 0xfe, 0xdc, 0x5a, 0x37, 0x23, 0xeb, 0x3d, 0xe8, 0x1e, 0x39, 0x2d, + 0xbf, 0xa6, 0xe9, 0x17, 0x48, 0xe2, 0xea, 0xef, 0x1d, 0x2f, 0xe2, 0xaf, 0x3c, 0xbc, 0xae, 0xa7, + 0x42, 0x9b, 0xa5, 0x7d, 0x47, 0x8a, 0x20, 0xc5, 0xae, 0xa1, 0xe4, 0xe8, 0x1c, 0x05, 0xc0, 0x0a, + 0x05, 0xdc, 0x01, 0x74, 0xde, 0xad, 0xad, 0x07, 0xec, 0x6e, 0x6a, 0xc7, 0xee, 0x0f, 0xb8, 0xbe, + 0xaa, 0x46, 0x61, 0x8c, 0x12, 0x5a, 0xaf, 0x05, 0xff, 0x1b, 0x35, 0x6b, 0xe2, 0x3d, 0x48, 0x4f, + 0x6b, 0x1f, 0xc4, 0x85, 0x98, 0xc3, 0x01, 0xda, 0x39, 0xf0, 0x1b, 0x76, 0x5d, 0x81, 0x1d, 0x1f, + 0xc9, 0x93, 0x95, 0xc1, 0xf8, 0xd1, 0x67, 0x2c, 0xd4, 0x0a, 0x67, 0xf0, 0x40, 0x86, 0x82, 0x7f, + 0x8f, 0x9d, 0x79, 0x04, 0xee, 0x4a, 0x54, 0xc9, 0x9c, 0x7f, 0xda, 0x15, 0x13, 0xc6, 0x95, 0xfb, + 0xfc, 0x7b, 0xe7, 0xd8, 0xde, 0x2a, 0xd8, 0xfd, 0xff, 0xdb, 0xa4, 0x7f, 0x4b, 0x37, 0x5d, 0x42, + 0xb6, 0x46, 0x4c, 0xbc, 0x34, 0x23, 0x99, 0x74, 0xf8, 0x80, 0x1b, 0xc1, 0x97, 0x34, 0xdf, 0x23, + 0x15, 0xa2, 0x8b, 0xec, 0xf3, 0x3e, 0x20, 0x93, 0x63, 0x88, 0x17, 0x70, 0x75, 0xbb, 0x9d, 0xb8, + 0x32, 0xb0, 0xae, 0xb5, 0x24, 0x6a, 0x86, 0xf6, 0xc1, 0x60, 0x41, 0xc4, 0xf4, 0x95, 0x6e, 0x10, + 0x2f, 0xd8, 0x58, 0x56, 0x42, 0x82, 0x71, 0x85, 0x19, 0xde, 0x91, 0xf0, 0x2f, 0x30, 0x0c, 0x63, + 0x0f, 0x2a, 0x77, 0x25, 0x4b, 0xb3, 0xd3, 0x2d, 0xfd, 0x94, 0x8b, 0x53, 0x02, 0x21, 0x40, 0xd7, + 0x36, 0x76, 0xf3, 0xc8, 0xc0, 0x36, 0x3d, 0x23, 0xc9, 0xbd, 0x92, 0x51, 0xf2, 0x4b, 0x83, 0x15, + 0xe0, 0x80, 0x86, 0x24, 0xe2, 0x20, 0x35, 0x97, 0xda, 0x0e, 0x68, 0x39, 0x01, 0xdd, 0x01, 0x87, + 0xa2, 0x47, 0xd2, 0x0d, 0xee, 0xfe, 0xdc, 0x5a, 0x37, 0x23, 0xeb, 0x3d, 0xe8, 0x1e, 0x39, 0x2d, + 0xbf, 0xa6, 0xe9, 0x17, 0x48, 0xe2, 0xea, 0xef, 0x1d, 0x2f, 0xe2, 0xaf, 0x3c, 0xbc, 0xae, 0xa7, + 0x42, 0x9b, 0xa5, 0x7d, 0x47, 0x8a, 0x20, 0xc5, 0xae, 0xa1, 0xe4, 0xe8, 0x1c, 0x05, 0xc0, 0x0a, + 0x05, 0xdc, 0x01, 0x74, 0xde, 0xad, 0xad, 0x07, 0xec, 0x6e, 0x6a, 0xc7, 0xee, 0x0f, 0xb8, 0xbe, + 0xaa, 0x46, 0x61, 0x8c, 0x12, 0x5a, 0xaf, 0x05, 0xff, 0x1b, 0x35, 0x6b, 0xe2, 0x3d, 0x48, 0x4f +}; + +#if 0 +static char dh_xb_4096[] = { + 0x5c, 0xdf, 0x3, 0x2f, 0x18, 0xac, 0xbc, 0xeb, 0x95, 0xa2, 0x33, 0x70, 0x39, 0x13, 0x92, 0x7e, + 0x91, 0x19, 0x89, 0xd4, 0x0, 0xd1, 0xc5, 0x7e, 0x32, 0xb7, 0x4a, 0xd2, 0xff, 0x11, 0x7a, 0x9b, + 0x2, 0x84, 0xd0, 0x8e, 0x19, 0x91, 0x34, 0xc2, 0x5, 0xff, 0xe4, 0xf4, 0xd8, 0xcf, 0xc8, 0xa0, + 0xeb, 0x19, 0xb9, 0x69, 0x60, 0xcd, 0xa8, 0xda, 0x33, 0xbc, 0xa7, 0x80, 0x0, 0x92, 0x27, 0xe0, + 0xe7, 0x34, 0x77, 0x1f, 0xfd, 0x56, 0x0, 0x0c, 0x57, 0x0, 0x6d, 0x47, 0xe4, 0x32, 0xd7, 0x22, + 0x64, 0xa5, 0x33, 0x65, 0x33, 0x3e, 0x7c, 0x4e, 0x9d, 0xa6, 0xb7, 0x8b, 0xd7, 0xaa, 0x72, 0xe5, + 0x9d, 0xd5, 0xb4, 0x25, 0xcb, 0x30, 0x2, 0xfc, 0xb5, 0xae, 0xb3, 0x88, 0x67, 0x55, 0x0a, 0x7e, + 0x9d, 0xe8, 0x32, 0xfb, 0x50, 0x79, 0x4e, 0x9b, 0x21, 0x92, 0x25, 0x3, 0xa0, 0x15, 0x52, 0x3d, + 0x5e, 0x21, 0x0a, 0x9e, 0x3, 0xdd, 0x3f, 0xcc, 0x38, 0xf6, 0xa9, 0xa6, 0xf8, 0xfd, 0x15, 0x7d, + 0x67, 0x4e, 0x14, 0xae, 0x4d, 0xe2, 0x1f, 0x78, 0x77, 0xfb, 0x83, 0x5f, 0x48, 0xa8, 0xc8, 0x21, + 0x8b, 0xd9, 0xf8, 0x14, 0xe6, 0x42, 0x95, 0xbd, 0x9a, 0x96, 0xbe, 0xf4, 0x7d, 0x26, 0x5d, 0xa1, + 0x81, 0x9b, 0x1c, 0xec, 0xfe, 0xce, 0x9, 0x1d, 0xb7, 0x7a, 0xba, 0xca, 0x7f, 0x54, 0xee, 0x36, + 0x54, 0x65, 0x4a, 0xd0, 0x5c, 0x84, 0x8c, 0x3e, 0x1b, 0xfe, 0x91, 0x6f, 0x95, 0xb5, 0x76, 0xbf, + 0x61, 0x2a, 0x7, 0x23, 0x86, 0xb9, 0xe0, 0x19, 0x29, 0xcf, 0xea, 0x3a, 0x1, 0xbf, 0xee, 0x1b, + 0x5e, 0x3c, 0x4, 0xff, 0x1d, 0xcf, 0xa6, 0x56, 0xb3, 0x22, 0xbb, 0x45, 0x4b, 0x7f, 0x83, 0x87, + 0xef, 0x21, 0x5, 0xf7, 0x38, 0x1f, 0x6, 0x4d, 0x71, 0x0b, 0xe3, 0xe1, 0xb7, 0x7e, 0xae, 0x18, + 0x5c, 0xdf, 0x3, 0x2f, 0x18, 0xac, 0xbc, 0xeb, 0x95, 0xa2, 0x33, 0x70, 0x39, 0x13, 0x92, 0x7e, + 0x91, 0x19, 0x89, 0xd4, 0x0, 0xd1, 0xc5, 0x7e, 0x32, 0xb7, 0x4a, 0xd2, 0xff, 0x11, 0x7a, 0x9b, + 0x2, 0x84, 0xd0, 0x8e, 0x19, 0x91, 0x34, 0xc2, 0x5, 0xff, 0xe4, 0xf4, 0xd8, 0xcf, 0xc8, 0xa0, + 0xeb, 0x19, 0xb9, 0x69, 0x60, 0xcd, 0xa8, 0xda, 0x33, 0xbc, 0xa7, 0x80, 0x0, 0x92, 0x27, 0xe0, + 0xe7, 0x34, 0x77, 0x1f, 0xfd, 0x56, 0x0, 0x0c, 0x57, 0x0, 0x6d, 0x47, 0xe4, 0x32, 0xd7, 0x22, + 0x64, 0xa5, 0x33, 0x65, 0x33, 0x3e, 0x7c, 0x4e, 0x9d, 0xa6, 0xb7, 0x8b, 0xd7, 0xaa, 0x72, 0xe5, + 0x9d, 0xd5, 0xb4, 0x25, 0xcb, 0x30, 0x2, 0xfc, 0xb5, 0xae, 0xb3, 0x88, 0x67, 0x55, 0x0a, 0x7e, + 0x9d, 0xe8, 0x32, 0xfb, 0x50, 0x79, 0x4e, 0x9b, 0x21, 0x92, 0x25, 0x3, 0xa0, 0x15, 0x52, 0x3d, + 0x5e, 0x21, 0x0a, 0x9e, 0x3, 0xdd, 0x3f, 0xcc, 0x38, 0xf6, 0xa9, 0xa6, 0xf8, 0xfd, 0x15, 0x7d, + 0x67, 0x4e, 0x14, 0xae, 0x4d, 0xe2, 0x1f, 0x78, 0x77, 0xfb, 0x83, 0x5f, 0x48, 0xa8, 0xc8, 0x21, + 0x8b, 0xd9, 0xf8, 0x14, 0xe6, 0x42, 0x95, 0xbd, 0x9a, 0x96, 0xbe, 0xf4, 0x7d, 0x26, 0x5d, 0xa1, + 0x81, 0x9b, 0x1c, 0xec, 0xfe, 0xce, 0x9, 0x1d, 0xb7, 0x7a, 0xba, 0xca, 0x7f, 0x54, 0xee, 0x36, + 0x54, 0x65, 0x4a, 0xd0, 0x5c, 0x84, 0x8c, 0x3e, 0x1b, 0xfe, 0x91, 0x6f, 0x95, 0xb5, 0x76, 0xbf, + 0x61, 0x2a, 0x7, 0x23, 0x86, 0xb9, 0xe0, 0x19, 0x29, 0xcf, 0xea, 0x3a, 0x1, 0xbf, 0xee, 0x1b, + 0x5e, 0x3c, 0x4, 0xff, 0x1d, 0xcf, 0xa6, 0x56, 0xb3, 0x22, 0xbb, 0x45, 0x4b, 0x7f, 0x83, 0x87, + 0xef, 0x21, 0x5, 0xf7, 0x38, 0x1f, 0x6, 0x4d, 0x71, 0x0b, 0xe3, 0xe1, 0xb7, 0x7e, 0xae, 0x18 +}; +#endif + +static char dh_except_a_pubkey_4096[] = { + 0xa5, 0x24, 0x63, 0x20, 0xb2, 0x56, 0x9a, 0x94, 0x97, 0xf7, 0x88, 0x41, 0x35, 0xeb, 0x52, 0x37, + 0xa4, 0xf2, 0x74, 0x1b, 0x38, 0xe4, 0x4c, 0x8b, 0x4b, 0xd2, 0xa5, 0xad, 0xb8, 0x2f, 0x7b, 0x5a, + 0xfd, 0xbc, 0x9c, 0xe0, 0xea, 0x9e, 0x82, 0x3, 0x62, 0xe2, 0xdc, 0x6c, 0x56, 0x9, 0x2, 0x28, + 0xb8, 0x2d, 0xb8, 0x46, 0xaf, 0x3a, 0xf4, 0x51, 0xf7, 0x4d, 0xc4, 0xd9, 0xa9, 0x1d, 0x67, 0x9d, + 0x2b, 0x18, 0x56, 0x86, 0x2a, 0x3, 0x19, 0xe9, 0x6, 0xeb, 0x4a, 0x6f, 0x2a, 0x40, 0x28, 0xbb, + 0x3e, 0x87, 0xc1, 0xce, 0x39, 0x6e, 0x3b, 0x1f, 0xb0, 0x9, 0x33, 0x67, 0x19, 0x0e, 0x1a, 0xb2, + 0xb3, 0x7d, 0xd3, 0xe6, 0x33, 0xf4, 0x7c, 0x82, 0x73, 0x7b, 0xb6, 0x16, 0x55, 0xff, 0x76, 0xaf, + 0x7f, 0xc2, 0x42, 0x51, 0xa9, 0xad, 0x1e, 0x72, 0xc9, 0x63, 0xab, 0x41, 0x5a, 0x26, 0x32, 0x39, + 0x5d, 0xa6, 0x7, 0x56, 0x93, 0x89, 0xe5, 0x0f, 0x2a, 0xb5, 0x67, 0x3a, 0xcf, 0xc3, 0x82, 0x83, + 0xf6, 0x88, 0x52, 0x0b, 0xfc, 0x6a, 0x5b, 0x1a, 0x57, 0x87, 0x86, 0xef, 0xda, 0x47, 0xdb, 0x4d, + 0xba, 0xe7, 0x3, 0x5b, 0xe4, 0x70, 0x8b, 0xe0, 0xe1, 0x92, 0x13, 0x86, 0x74, 0x4, 0xdc, 0x6a, + 0x0a, 0x2a, 0x20, 0xec, 0x6d, 0xbf, 0xf0, 0x46, 0xf7, 0x9, 0x2, 0xdb, 0x2f, 0x70, 0x11, 0xdd, + 0xb0, 0x13, 0xa2, 0xc1, 0x58, 0x74, 0x29, 0x19, 0x8d, 0x4a, 0x94, 0x80, 0x0b, 0xd7, 0x25, 0x85, + 0x10, 0x35, 0x97, 0x48, 0x6e, 0x70, 0x28, 0xae, 0x58, 0x97, 0x7d, 0xf2, 0x19, 0x27, 0x13, 0xab, + 0x47, 0x9b, 0x54, 0xdf, 0xc3, 0x5b, 0x5f, 0x5e, 0xb4, 0x64, 0x47, 0xce, 0x40, 0x3b, 0x0c, 0x4a, + 0x62, 0x52, 0xba, 0xc7, 0xf0, 0x36, 0x87, 0x9c, 0x79, 0x9a, 0x83, 0x11, 0x61, 0x0c, 0x1b, 0x6b, + 0xa5, 0x24, 0x63, 0x20, 0xb2, 0x56, 0x9a, 0x94, 0x97, 0xf7, 0x88, 0x41, 0x35, 0xeb, 0x52, 0x37, + 0xa4, 0xf2, 0x74, 0x1b, 0x38, 0xe4, 0x4c, 0x8b, 0x4b, 0xd2, 0xa5, 0xad, 0xb8, 0x2f, 0x7b, 0x5a, + 0xfd, 0xbc, 0x9c, 0xe0, 0xea, 0x9e, 0x82, 0x3, 0x62, 0xe2, 0xdc, 0x6c, 0x56, 0x9, 0x2, 0x28, + 0xb8, 0x2d, 0xb8, 0x46, 0xaf, 0x3a, 0xf4, 0x51, 0xf7, 0x4d, 0xc4, 0xd9, 0xa9, 0x1d, 0x67, 0x9d, + 0x2b, 0x18, 0x56, 0x86, 0x2a, 0x3, 0x19, 0xe9, 0x6, 0xeb, 0x4a, 0x6f, 0x2a, 0x40, 0x28, 0xbb, + 0x3e, 0x87, 0xc1, 0xce, 0x39, 0x6e, 0x3b, 0x1f, 0xb0, 0x9, 0x33, 0x67, 0x19, 0x0e, 0x1a, 0xb2, + 0xb3, 0x7d, 0xd3, 0xe6, 0x33, 0xf4, 0x7c, 0x82, 0x73, 0x7b, 0xb6, 0x16, 0x55, 0xff, 0x76, 0xaf, + 0x7f, 0xc2, 0x42, 0x51, 0xa9, 0xad, 0x1e, 0x72, 0xc9, 0x63, 0xab, 0x41, 0x5a, 0x26, 0x32, 0x39, + 0x5d, 0xa6, 0x7, 0x56, 0x93, 0x89, 0xe5, 0x0f, 0x2a, 0xb5, 0x67, 0x3a, 0xcf, 0xc3, 0x82, 0x83, + 0xf6, 0x88, 0x52, 0x0b, 0xfc, 0x6a, 0x5b, 0x1a, 0x57, 0x87, 0x86, 0xef, 0xda, 0x47, 0xdb, 0x4d, + 0xba, 0xe7, 0x3, 0x5b, 0xe4, 0x70, 0x8b, 0xe0, 0xe1, 0x92, 0x13, 0x86, 0x74, 0x4, 0xdc, 0x6a, + 0x0a, 0x2a, 0x20, 0xec, 0x6d, 0xbf, 0xf0, 0x46, 0xf7, 0x9, 0x2, 0xdb, 0x2f, 0x70, 0x11, 0xdd, + 0xb0, 0x13, 0xa2, 0xc1, 0x58, 0x74, 0x29, 0x19, 0x8d, 0x4a, 0x94, 0x80, 0x0b, 0xd7, 0x25, 0x85, + 0x10, 0x35, 0x97, 0x48, 0x6e, 0x70, 0x28, 0xae, 0x58, 0x97, 0x7d, 0xf2, 0x19, 0x27, 0x13, 0xab, + 0x47, 0x9b, 0x54, 0xdf, 0xc3, 0x5b, 0x5f, 0x5e, 0xb4, 0x64, 0x47, 0xce, 0x40, 0x3b, 0x0c, 0x4a, + 0x62, 0x52, 0xba, 0xc7, 0xf0, 0x36, 0x87, 0x9c, 0x79, 0x9a, 0x83, 0x11, 0x61, 0x0c, 0x1b, 0x6b +}; + +static char dh_except_b_pubkey_4096[] = { + 0x44, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x9, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x4, 0xe8, 0x9a, 0xd2, 0x0, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x0, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x5, + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x7, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x3, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x1, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7, + 0x44, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x9, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x4, 0xe8, 0x9a, 0xd2, 0x0, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x0, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x5, + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x7, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x3, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x1, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7 +}; + +static char dh_share_key_4096[] = { + 0xaf, 0xd4, 0xf6, 0x45, 0x63, 0x21, 0x8d, 0x98, 0xc4, 0xab, 0x18, 0xd7, 0x2b, 0x3c, 0x1d, 0xde, + 0xe7, 0x1f, 0xe1, 0xc5, 0x79, 0x57, 0x60, 0x20, 0xfa, 0x99, 0xbd, 0x7b, 0xa2, 0x94, 0x0b, 0xa3, + 0xb4, 0xb3, 0x33, 0x4a, 0x2f, 0xd0, 0x17, 0x7, 0x2e, 0x70, 0x19, 0x84, 0x1f, 0x8e, 0xe9, 0x61, + 0xe5, 0x52, 0x3, 0x96, 0xea, 0xd8, 0xb6, 0x3, 0x9f, 0xc4, 0x3e, 0x23, 0x77, 0x17, 0x54, 0xfb, + 0x13, 0xf0, 0x3e, 0x9a, 0x27, 0x5d, 0x12, 0x99, 0x58, 0x8d, 0x41, 0x46, 0xd9, 0xc9, 0x29, 0xbd, + 0x40, 0xd1, 0x4f, 0xef, 0x63, 0x7b, 0x54, 0xe6, 0x59, 0x6d, 0xe2, 0x30, 0xe8, 0x2c, 0x2f, 0xf9, + 0x66, 0xa2, 0x12, 0xf5, 0x58, 0x61, 0xac, 0x43, 0xec, 0x7e, 0xf9, 0x2e, 0x27, 0x70, 0x35, 0x75, + 0xb4, 0x10, 0x29, 0xac, 0x0a, 0xab, 0x59, 0xb6, 0x68, 0x4c, 0x16, 0xaf, 0xf0, 0x4f, 0x21, 0xcd, + 0xcc, 0x48, 0x97, 0xe4, 0x21, 0x65, 0xa6, 0x55, 0xb8, 0xf3, 0xb2, 0x7b, 0x91, 0xd7, 0xca, 0xb9, + 0x17, 0x58, 0x31, 0x71, 0xc0, 0xc9, 0x69, 0x1e, 0xf0, 0x9e, 0x3f, 0xe2, 0x37, 0x4, 0x2d, 0xa8, + 0x55, 0x9, 0x6b, 0x9c, 0xc6, 0x37, 0xa9, 0x9b, 0xdf, 0x67, 0x73, 0x7b, 0x46, 0xf9, 0x63, 0x47, + 0xcb, 0xa0, 0x57, 0x2a, 0xed, 0x97, 0x2f, 0xfe, 0x92, 0xf2, 0x20, 0x2c, 0x7e, 0xee, 0x7d, 0x11, + 0x78, 0xe6, 0xb9, 0x9, 0xd1, 0x94, 0xce, 0xd1, 0x5b, 0xf4, 0x44, 0xa9, 0xcb, 0x26, 0x2, 0x36, + 0x57, 0x2c, 0xa2, 0xbe, 0x37, 0xde, 0x86, 0x46, 0x20, 0x27, 0x9d, 0xa0, 0x2f, 0x4, 0xc1, 0xcd, + 0xff, 0x81, 0xe5, 0xe6, 0x2c, 0x9e, 0x39, 0x82, 0x31, 0x54, 0x33, 0xf8, 0xe7, 0xa0, 0xe5, 0x96, + 0xa4, 0x40, 0xc4, 0x44, 0xfe, 0x93, 0x66, 0xe2, 0xda, 0xaa, 0xb8, 0xfb, 0x2f, 0x3b, 0x8c, 0xce, + 0xaf, 0xd4, 0xf6, 0x45, 0x63, 0x21, 0x8d, 0x98, 0xc4, 0xab, 0x18, 0xd7, 0x2b, 0x3c, 0x1d, 0xde, + 0xe7, 0x1f, 0xe1, 0xc5, 0x79, 0x57, 0x60, 0x20, 0xfa, 0x99, 0xbd, 0x7b, 0xa2, 0x94, 0x0b, 0xa3, + 0xb4, 0xb3, 0x33, 0x4a, 0x2f, 0xd0, 0x17, 0x7, 0x2e, 0x70, 0x19, 0x84, 0x1f, 0x8e, 0xe9, 0x61, + 0xe5, 0x52, 0x3, 0x96, 0xea, 0xd8, 0xb6, 0x3, 0x9f, 0xc4, 0x3e, 0x23, 0x77, 0x17, 0x54, 0xfb, + 0x13, 0xf0, 0x3e, 0x9a, 0x27, 0x5d, 0x12, 0x99, 0x58, 0x8d, 0x41, 0x46, 0xd9, 0xc9, 0x29, 0xbd, + 0x40, 0xd1, 0x4f, 0xef, 0x63, 0x7b, 0x54, 0xe6, 0x59, 0x6d, 0xe2, 0x30, 0xe8, 0x2c, 0x2f, 0xf9, + 0x66, 0xa2, 0x12, 0xf5, 0x58, 0x61, 0xac, 0x43, 0xec, 0x7e, 0xf9, 0x2e, 0x27, 0x70, 0x35, 0x75, + 0xb4, 0x10, 0x29, 0xac, 0x0a, 0xab, 0x59, 0xb6, 0x68, 0x4c, 0x16, 0xaf, 0xf0, 0x4f, 0x21, 0xcd, + 0xcc, 0x48, 0x97, 0xe4, 0x21, 0x65, 0xa6, 0x55, 0xb8, 0xf3, 0xb2, 0x7b, 0x91, 0xd7, 0xca, 0xb9, + 0x17, 0x58, 0x31, 0x71, 0xc0, 0xc9, 0x69, 0x1e, 0xf0, 0x9e, 0x3f, 0xe2, 0x37, 0x4, 0x2d, 0xa8, + 0x55, 0x9, 0x6b, 0x9c, 0xc6, 0x37, 0xa9, 0x9b, 0xdf, 0x67, 0x73, 0x7b, 0x46, 0xf9, 0x63, 0x47, + 0xcb, 0xa0, 0x57, 0x2a, 0xed, 0x97, 0x2f, 0xfe, 0x92, 0xf2, 0x20, 0x2c, 0x7e, 0xee, 0x7d, 0x11, + 0x78, 0xe6, 0xb9, 0x9, 0xd1, 0x94, 0xce, 0xd1, 0x5b, 0xf4, 0x44, 0xa9, 0xcb, 0x26, 0x2, 0x36, + 0x57, 0x2c, 0xa2, 0xbe, 0x37, 0xde, 0x86, 0x46, 0x20, 0x27, 0x9d, 0xa0, 0x2f, 0x4, 0xc1, 0xcd, + 0xff, 0x81, 0xe5, 0xe6, 0x2c, 0x9e, 0x39, 0x82, 0x31, 0x54, 0x33, 0xf8, 0xe7, 0xa0, 0xe5, 0x96, + 0xa4, 0x40, 0xc4, 0x44, 0xfe, 0x93, 0x66, 0xe2, 0xda, 0xaa, 0xb8, 0xfb, 0x2f, 0x3b, 0x8c, 0xce, +}; + +#if 0 +static char rsa_e_2048[] = { + 0xaf, 0xd4, 0xf6, 0x45, 0x63, 0x21, 0x8d, 0x98, 0xc4, 0xab, 0x18, 0xd7, 0x2b, 0x3c, 0x1d, 0xde, + 0xe7, 0x1f, 0xe1, 0xc5, 0x79, 0x57, 0x60, 0x20, 0xfa, 0x99, 0xbd, 0x7b, 0xa2, 0x94, 0x0b, 0xa3, + 0xb4, 0xb3, 0x33, 0x4a, 0x2f, 0xd0, 0x17, 0x7, 0x2e, 0x70, 0x19, 0x84, 0x1f, 0x8e, 0xe9, 0x61, + 0xe5, 0x52, 0x3, 0x96, 0xea, 0xd8, 0xb6, 0x3, 0x9f, 0xc4, 0x3e, 0x23, 0x77, 0x17, 0x54, 0xfb, + 0x13, 0xf0, 0x3e, 0x9a, 0x27, 0x5d, 0x12, 0x99, 0x58, 0x8d, 0x41, 0x46, 0xd9, 0xc9, 0x29, 0xbd, + 0x40, 0xd1, 0x4f, 0xef, 0x63, 0x7b, 0x54, 0xe6, 0x59, 0x6d, 0xe2, 0x30, 0xe8, 0x2c, 0x2f, 0xf9, + 0x66, 0xa2, 0x12, 0xf5, 0x58, 0x61, 0xac, 0x43, 0xec, 0x7e, 0xf9, 0x2e, 0x27, 0x70, 0x35, 0x75, + 0xb4, 0x10, 0x29, 0xac, 0x0a, 0xab, 0x59, 0xb6, 0x68, 0x4c, 0x16, 0xaf, 0xf0, 0x4f, 0x21, 0xcd, + 0xcc, 0x48, 0x97, 0xe4, 0x21, 0x65, 0xa6, 0x55, 0xb8, 0xf3, 0xb2, 0x7b, 0x91, 0xd7, 0xca, 0xb9, + 0x17, 0x58, 0x31, 0x71, 0xc0, 0xc9, 0x69, 0x1e, 0xf0, 0x9e, 0x3f, 0xe2, 0x37, 0x4, 0x2d, 0xa8, + 0x55, 0x09, 0x6b, 0x9c, 0xc6, 0x37, 0xa9, 0x9b, 0xdf, 0x67, 0x73, 0x7b, 0x46, 0xf9, 0x63, 0x47, + 0xcb, 0xa0, 0x57, 0x2a, 0xed, 0x97, 0x2f, 0xfe, 0x92, 0xf2, 0x20, 0x2c, 0x7e, 0xee, 0x7d, 0x11, + 0x78, 0xe6, 0xb9, 0x9, 0xd1, 0x94, 0xce, 0xd1, 0x5b, 0xf4, 0x44, 0xa9, 0xcb, 0x26, 0x2, 0x36, + 0x57, 0x2c, 0xa2, 0xbe, 0x37, 0xde, 0x86, 0x46, 0x20, 0x27, 0x9d, 0xa0, 0x2f, 0x4, 0xc1, 0xcd, + 0xff, 0x81, 0xe5, 0xe6, 0x2c, 0x9e, 0x39, 0x82, 0x31, 0x54, 0x33, 0xf8, 0xe7, 0xa0, 0xe5, 0x96, + 0xa4, 0x40, 0xc4, 0x44, 0xfe, 0x93, 0x66, 0xe2, 0xda, 0xaa, 0xb8, 0xfb, 0x2f, 0x3b, 0x8c, 0xce, +}; + +static char rsa_p_2048[] = { + 0xce, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x09, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x04, 0xe8, 0x9a, 0xd2, 0x00, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x00, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x05, + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x07, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x03, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x01, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7 +}; + +static char rsa_q_2048[] = { + 0x44, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x9, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x4, 0xe8, 0x9a, 0xd2, 0x0, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x0, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x5, + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x7, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x3, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x1, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7 +}; +#endif + + +/******************************************* ECDH ********************************************/ +static char ecdh_a_secp128r1[] = { + 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc +}; + +static char ecdh_b_secp128r1[] = { + 0xe8, 0x75, 0x79, 0xc1, 0x10, 0x79, 0xf4, 0x3d, 0xd8, 0x24, 0x99, 0x3c, 0x2c, 0xee, 0x5e, 0xd3 +}; + +static char ecdh_p_secp128r1[] = { + 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +static char ecdh_n_secp128r1[] = { + 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x75, 0xa3, 0x0d, 0x1b, 0x90, 0x38, 0xa1, 0x15 +}; + +static char ecdh_g_secp128r1[] = { + 0x16, 0x1f, 0xf7, 0x52, 0x8b, 0x89, 0x9b, 0x2d, 0x0c, 0x28, 0x60, 0x7c, 0xa5, 0x2c, 0x5b, 0x86, + 0xcf, 0x5a, 0xc8, 0x39, 0x5b, 0xaf, 0xeb, 0x13, 0xc0, 0x2d, 0xa2, 0x92, 0xdd, 0xed, 0x7a, 0x83 +}; + +static char ecdh_da_secp128r1[] = { + 0xfe, 0x4e, 0xc2, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x78, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static char ecdh_cp_pubkey_secp128r1[] = { + 0x04, + 0xcc, 0x40, 0x99, 0x3b, 0xcd, 0x0b, 0xcf, 0xcb, 0x9a, 0x96, 0x08, 0x56, 0xc2, 0x96, 0x2c, 0xe1, + 0xdf, 0x69, 0x2a, 0x71, 0xaf, 0x96, 0xe2, 0xeb, 0x5a, 0x26, 0x7f, 0xd3, 0x7a, 0xe8, 0x70, 0xf3 +}; + +static char ecdh_except_b_pubkey_secp128r1[] = { + 0x04, + 0xcc, 0x40, 0x99, 0x3b, 0xcd, 0x0b, 0xcf, 0xcb, 0x9a, 0x96, 0x08, 0x56, 0xc2, 0x96, 0x2c, 0xe1, + 0xdf, 0x69, 0x2a, 0x71, 0xaf, 0x96, 0xe2, 0xeb, 0x5a, 0x26, 0x7f, 0xd3, 0x7a, 0xe8, 0x70, 0xf3 +}; + +static char ecdh_cp_sharekey_secp128r1[] = { + 0x68, 0x55, 0x71, 0xa4, 0xd7, 0x51, 0x49, 0xa8, 0x78, 0xa8, 0x3a, 0xc1, 0x3f, 0xb3, 0x8c, 0xcb +}; + +/* ecc sign or verf*/ +static char ecc_except_kinv_secp128r1[] = { + 0xfe, 0x4e, 0xc2, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x78, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static char ecc_except_e_secp128r1[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x4 +}; + +static char ecc_cp_sign_secp128r1[] = { + 0x2e, 0x69, 0xad, 0x4f, 0xd5, 0xd4, 0x62, 0xec, 0xf2, 0xde, 0x21, 0x4f, 0xbc, 0x1f, 0xe8, 0x19, + 0x7b, 0x98, 0x8d, 0xaf, 0xe4, 0x6c, 0x60, 0x73, 0x00, 0xb0, 0x8b, 0xef, 0x89, 0x65, 0x35, 0x84 +}; + +static char ecdh_a_secp192k1[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static char ecdh_b_secp192k1[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03 +}; + +static char ecdh_p_secp192k1[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xee, 0x37 +}; + +static char ecdh_n_secp192k1[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x26, 0xf2, 0xfc, 0x17, + 0x0f, 0x69, 0x46, 0x6a, 0x74, 0xde, 0xfd, 0x8d +}; + +static char ecdh_g_secp192k1[] = { + 0xdb, 0x4f, 0xf1, 0x0e, 0xc0, 0x57, 0xe9, 0xae, 0x26, 0xb0, 0x7d, 0x02, 0x80, 0xb7, 0xf4, 0x34, + 0x1d, 0xa5, 0xd1, 0xb1, 0xea, 0xe0, 0x6c, 0x7d, + 0x9b, 0x2f, 0x2f, 0x6d, 0x9c, 0x56, 0x28, 0xa7, 0x84, 0x41, 0x63, 0xd0, 0x15, 0xbe, 0x86, 0x34, + 0x40, 0x82, 0xaa, 0x88, 0xd9, 0x5e, 0x2f, 0x9d +}; + +static char ecdh_da_secp192k1[] = { + 0x2b, 0x58, 0xc2, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x58, 0xc2, 0x5e, 0x00, 0x00, 0x00, 0x00, + 0x67, 0x6a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static char ecdh_cp_pubkey_secp192k1[] = { + 0x04, + 0xec, 0x0e, 0x64, 0xac, 0x04, 0x2a, 0x88, 0x86, 0xed, 0xc1, 0xf2, 0x50, 0x0f, 0xe1, 0x27, 0x63, + 0x86, 0x63, 0x9e, 0xb2, 0x82, 0x21, 0x6e, 0x3f, 0x48, 0x59, 0x76, 0xb9, 0x4e, 0xd9, 0xe2, 0x02, + 0xb4, 0xdb, 0xfc, 0x8f, 0x49, 0xe7, 0x24, 0x9b, 0xbe, 0x33, 0xee, 0xc8, 0xcc, 0x9e, 0x00, 0x9a +}; + +static char ecdh_cp_sharekey_secp192k1[] = { + 0x79, 0xd3, 0x1c, 0x98, 0xfb, 0xd2, 0xb6, 0x7c, 0x60, 0x4b, 0x6e, 0x4c, 0xa9, 0x95, 0xcb, 0xac, + 0xb0, 0xf9, 0x05, 0xed, 0x9a, 0xcb, 0x2e, 0x5b +}; + +static char ecdh_except_b_pubkey_secp192k1[] = { + 0x04, + 0xec, 0x0e, 0x64, 0xac, 0x04, 0x2a, 0x88, 0x86, 0xed, 0xc1, 0xf2, 0x50, 0x0f, 0xe1, 0x27, 0x63, + 0x86, 0x63, 0x9e, 0xb2, 0x82, 0x21, 0x6e, 0x3f, 0x48, 0x59, 0x76, 0xb9, 0x4e, 0xd9, 0xe2, 0x02, + 0xb4, 0xdb, 0xfc, 0x8f, 0x49, 0xe7, 0x24, 0x9b, 0xbe, 0x33, 0xee, 0xc8, 0xcc, 0x9e, 0x00, 0x9a +}; + +/* ecc sign or verf*/ +static char ecc_except_kinv_secp192k1[] = { + 0x71, 0x71, 0xb4, 0x5b, 0x79, 0x51, 0x94, 0x70, 0x53, 0xf9, 0x77, 0x02, 0x64, 0xef, 0xc4, 0xdb, + 0x64, 0xfc, 0xbe, 0x4e, 0x44, 0x4a, 0xc6, 0x54 +}; + +static char ecc_except_e_secp192k1[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04 +}; + +/* 224 */ +static char ecdh_a_secp224r1[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE +}; + +static char ecdh_b_secp224r1[] = { + 0xB4, 0x05, 0x0A, 0x85, 0x0C, 0x04, 0xB3, 0xAB, 0xF5, 0x41, 0x32, 0x56, 0x50, 0x44, + 0xB0, 0xB7, 0xD7, 0xBF, 0xD8, 0xBA, 0x27, 0x0B, 0x39, 0x43, 0x23, 0x55, 0xFF, 0xB4 +}; + +static char ecdh_p_secp224r1[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 +}; + +static char ecdh_n_secp224r1[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x16, 0xA2, 0xE0, 0xB8, 0xF0, 0x3E, 0x13, 0xDD, 0x29, 0x45, 0x5C, 0x5C, 0x2A, 0x3D +}; + +static char ecdh_g_secp224r1[] = { + 0xB7, 0x0E, 0x0C, 0xBD, 0x6B, 0xB4, 0xBF, 0x7F, 0x32, 0x13, 0x90, 0xB9, 0x4A, 0x03, + 0xC1, 0xD3, 0x56, 0xC2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xD6, 0x11, 0x5C, 0x1D, 0x21, + 0xBD, 0x37, 0x63, 0x88, 0xB5, 0xF7, 0x23, 0xFB, 0x4C, 0x22, 0xDF, 0xE6, 0xCD, 0x43, + 0x75, 0xA0, 0x5A, 0x07, 0x47, 0x64, 0x44, 0xD5, 0x81, 0x99, 0x85, 0x00, 0x7E, 0x34 +}; + +static char ecdh_da_secp224r1[] = { + 0x41, 0x5c, 0x8c, 0x34, 0xfd, 0x70, 0x76, 0x3c, 0x6a, 0x81, 0x8e, 0x33, 0x7c, 0xa5, + 0x59, 0x6b, 0xfb, 0x58, 0x8e, 0x74, 0xb8, 0xc7, 0x3c, 0xcf, 0xde, 0xe3, 0x81, 0x60 +}; + +static char ecdh_cp_pubkey_secp224r1[] = { + 0x04, + 0x5b, 0x46, 0x50, 0x7c, 0x7a, 0x37, 0x82, 0x05, 0x5a, 0xc7, 0xd0, 0x29, 0xf8, 0xdd, + 0xe6, 0x3e, 0xb4, 0xc2, 0x31, 0x59, 0xfd, 0xa4, 0xb7, 0xee, 0x61, 0x83, 0x7c, 0x80, + 0xf1, 0x51, 0xf0, 0x5b, 0xfb, 0xc6, 0x63, 0x23, 0x9a, 0x13, 0xfa, 0x47, 0x68, 0x7b, + 0x3e, 0x47, 0xb3, 0x88, 0xca, 0x3e, 0x4b, 0x71, 0x24, 0x17, 0xc7, 0x4c, 0xd0, 0x06 +}; + +static char ecdh_except_b_pubkey_secp224r1[] = { + 0x04, + 0x5b, 0x46, 0x50, 0x7c, 0x7a, 0x37, 0x82, 0x05, 0x5a, 0xc7, 0xd0, 0x29, 0xf8, 0xdd, + 0xe6, 0x3e, 0xb4, 0xc2, 0x31, 0x59, 0xfd, 0xa4, 0xb7, 0xee, 0x61, 0x83, 0x7c, 0x80, + 0xf1, 0x51, 0xf0, 0x5b, 0xfb, 0xc6, 0x63, 0x23, 0x9a, 0x13, 0xfa, 0x47, 0x68, 0x7b, + 0x3e, 0x47, 0xb3, 0x88, 0xca, 0x3e, 0x4b, 0x71, 0x24, 0x17, 0xc7, 0x4c, 0xd0, 0x06 +}; + +static char ecdh_cp_sharekey_secp224r1[] = { + 0x2f, 0xc0, 0x04, 0x34, 0x0e, 0x03, 0xb0, 0xd2, 0x84, 0xe1, 0x4f, 0x4f, 0x7b, 0xac, + 0x53, 0xaa, 0x32, 0x5c, 0xbd, 0xe5, 0xbc, 0x2a, 0xe3, 0xda, 0x48, 0x38, 0x67, 0x16 +}; + + +/* 256 */ +static char ecdh_a_secp256k1[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static char ecdh_b_secp256k1[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07 +}; + +static char ecdh_p_secp256k1[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f +}; + +static char ecdh_n_secp256k1[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, + 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41 +}; + +static char ecdh_g_secp256k1[] = { + 0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B, 0x07, + 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9, 0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98, + 0x48, 0x3a, 0xda, 0x77, 0x26, 0xa3, 0xc4, 0x65, 0x5d, 0xa4, 0xfb, 0xfc, 0x0e, 0x11, 0x08, 0xa8, + 0xfd, 0x17, 0xb4, 0x48, 0xa6, 0x85, 0x54, 0x19, 0x9c, 0x47, 0xd0, 0x8f, 0xfb, 0x10, 0xd4, 0xb8 +}; + +static char ecdh_da_secp256k1[] = { + 0x71, 0x71, 0xb4, 0x5b, 0x79, 0x51, 0x94, 0x70, 0x53, 0xf9, 0x77, 0x02, 0x64, 0xef, 0xc4, 0xdb, + 0x64, 0xfc, 0xbe, 0x4e, 0x44, 0x4a, 0xc6, 0x54, 0x71, 0x69, 0x2e, 0x4a, 0x46, 0xa7, 0x2d, 0xa3 +}; + +#if 0 +static char ecdh_db_secp256k1[] = { + 0xe2, 0x74, 0x69, 0xc8, 0x17, 0x6c, 0x0d, 0xca, 0xdd, 0x9e, 0xf6, 0x2f, 0x30, 0x9f, 0xad, 0xf3, + 0xdd, 0x16, 0xcc, 0x0c, 0xb1, 0xd0, 0x7b, 0xf4, 0xde, 0x9d, 0xf2, 0x5d, 0x22, 0x03, 0xce, 0x41 +}; +#endif + +static char ecdh_cp_pubkey_secp256k1[] = { + 0x04, + 0x68, 0xae, 0x87, 0x7c, 0x45, 0xb3, 0x8b, 0xa8, 0xa8, 0x8e, 0x4b, 0xe5, 0x1f, 0x4e, 0xe6, 0x89, + 0x67, 0x73, 0x71, 0x96, 0x92, 0x2e, 0x57, 0x07, 0xc4, 0x30, 0xa5, 0xcf, 0x9f, 0x58, 0xb0, 0x6f, + 0x26, 0xd3, 0x58, 0xa4, 0xb6, 0xfc, 0xb6, 0x4b, 0x0f, 0x63, 0xd9, 0xa6, 0xa0, 0x1b, 0xba, 0x10, + 0x10, 0xa4, 0xab, 0x28, 0x6e, 0xab, 0x51, 0x34, 0xac, 0x3d, 0x2b, 0x39, 0xf1, 0xd7, 0x21, 0x48 +}; + +static char ecdh_except_b_pubkey_secp256k1[] = { + 0x04, + 0x90, 0x34, 0x99, 0xc8, 0x9e, 0x32, 0xdb, 0xcd, 0x24, 0x4e, 0x31, 0x51, 0x1c, 0x83, 0x4b, 0xf7, + 0x68, 0xf0, 0xbb, 0xa3, 0x91, 0x38, 0xa8, 0xf1, 0xab, 0x76, 0x36, 0xcd, 0x23, 0x3f, 0x57, 0x3b, + 0x22, 0x1a, 0x3f, 0x2e, 0x40, 0x8b, 0xe2, 0x7b, 0xd4, 0x91, 0xe4, 0xf2, 0x36, 0x00, 0xbe, 0xae, + 0x9c, 0xf2, 0xfc, 0xb4, 0xb9, 0x8b, 0x5b, 0xa7, 0x39, 0x88, 0xf2, 0x3b, 0xe2, 0xe5, 0xab, 0x1b +}; + +static char ecdh_cp_sharekey_secp256k1[] = { + 0xd8, 0x9d, 0x1e, 0x25, 0xa2, 0x5, 0xd8, 0xad, 0x0f, 0x1c, 0x7a, 0x44, 0xd4, 0xe6, 0x96, 0xc2, + 0xd3, 0xbc, 0x05, 0xa1, 0x8d, 0x4a, 0x2, 0x11, 0x0e, 0x93, 0xcd, 0xb9, 0x56, 0xd6, 0x44, 0x1c, +}; + +/* ecc sign or verf*/ +static char ecc_except_kinv_secp256k1[] = { + 0x71, 0x71, 0xb4, 0x5b, 0x79, 0x51, 0x94, 0x70, 0x53, 0xf9, 0x77, 0x02, 0x64, 0xef, 0xc4, 0xdb, + 0x64, 0xfc, 0xbe, 0x4e, 0x44, 0x4a, 0xc6, 0x54, 0x71, 0x69, 0x2e, 0x4a, 0x46, 0xa7, 0x2d, 0xa3 +}; + +static char ecc_except_e_secp256k1[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04 +}; + +static char ecc_cp_sign_secp256k1[] = { + 0x30,0x45,0x02,0x20,0x68,0xae,0x87,0x7c,0x45,0xb3,0x8b,0xa8,0xa8,0x8e,0x4b,0xe5, + 0x1f,0x4e,0xe6,0x89,0x67,0x73,0x71,0x96,0x92,0x2e,0x57,0x07,0xc4,0x30,0xa5,0xcf, + 0x9f,0x58,0xb0,0x6f,0x02,0x21,0x00,0xdb,0x14,0xac,0x48,0x0d,0x0a,0xe9,0xe4,0x1d, + 0x8d,0xca,0x47,0xb6,0x0e,0x44,0xf6,0xfb,0xde,0x86,0x9b,0x38,0x76,0x98,0x67,0x12, + 0x7f,0x1d,0x09,0x97,0xab,0xc2,0xcb +}; + +static char ecdh_a_secp320k1[] = { + 0x3e, 0xe3, 0x0b, 0x56, 0x8f, 0xba, 0xb0, 0xf8, 0x83, 0xcc, 0xeb, 0xd4, 0x6d, 0x3f, 0x3b, 0xb8, + 0xa2, 0xa7, 0x35, 0x13, 0xf5, 0xeb, 0x79, 0xda, 0x66, 0x19, 0x0e, 0xb0, 0x85, 0xff, 0xa9, 0xf4, + 0x92, 0xf3, 0x75, 0xa9, 0x7d, 0x86, 0x0e, 0xb4 +}; + +static char ecdh_b_secp320k1[] = { + 0x52, 0x08, 0x83, 0x94, 0x9d, 0xfd, 0xbc, 0x42, 0xd3, 0xad, 0x19, 0x86, 0x40, 0x68, 0x8a, 0x6f, + 0xe1, 0x3f, 0x41, 0x34, 0x95, 0x54, 0xb4, 0x9a, 0xcc, 0x31, 0xdc, 0xcd, 0x88, 0x45, 0x39, 0x81, + 0x6f, 0x5e, 0xb4, 0xac, 0x8f, 0xb1, 0xf1, 0xa6 +}; + +static char ecdh_p_secp320k1[] = { + 0xd3, 0x5e, 0x47, 0x20, 0x36, 0xbc, 0x4f, 0xb7, 0xe1, 0x3c, 0x78, 0x5e, 0xd2, 0x01, 0xe0, 0x65, + 0xf9, 0x8f, 0xcf, 0xa6, 0xf6, 0xf4, 0x0d, 0xef, 0x4f, 0x92, 0xb9, 0xec, 0x78, 0x93, 0xec, 0x28, + 0xfc, 0xd4, 0x12, 0xb1, 0xf1, 0xb3, 0x2e, 0x27 +}; + +static char ecdh_n_secp320k1[] = { + 0xd3, 0x5e, 0x47, 0x20, 0x36, 0xbc, 0x4f, 0xb7, 0xe1, 0x3c, 0x78, 0x5e, 0xd2, 0x01, 0xe0, 0x65, + 0xf9, 0x8f, 0xcf, 0xa5, 0xb6, 0x8f, 0x12, 0xa3, 0x2d, 0x48, 0x2e, 0xc7, 0xee, 0x86, 0x58, 0xe9, + 0x86, 0x91, 0x55, 0x5b, 0x44, 0xc5, 0x93, 0x11 +}; + +static char ecdh_g_secp320k1[] = { + 0x43, 0xbd, 0x7e, 0x9a, 0xfb, 0x53, 0xd8, 0xb8, 0x52, 0x89, 0xbc, 0xc4, 0x8e, 0xe5, 0xbf, 0xe6, + 0xf2, 0x01, 0x37, 0xd1, 0x0a, 0x08, 0x7e, 0xb6, 0xe7, 0x87, 0x1e, 0x2a, 0x10, 0xa5, 0x99, 0xc7, + 0x10, 0xaf, 0x8d, 0x0d, 0x39, 0xe2, 0x06, 0x11, + 0x14, 0xfd, 0xd0, 0x55, 0x45, 0xec, 0x1c, 0xc8, 0xab, 0x40, 0x93, 0x24, 0x7f, 0x77, 0x27, 0x5e, + 0x07, 0x43, 0xff, 0xed, 0x11, 0x71, 0x82, 0xea, 0xa9, 0xc7, 0x78, 0x77, 0xaa, 0xac, 0x6a, 0xc7, + 0xd3, 0x52, 0x45, 0xd1, 0x69, 0x2e, 0x8e, 0xe1, +}; + +static char ecdh_da_secp320k1[] = { + 0x6a, 0x5b, 0xc2, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x21, 0x8e, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x31, 0x00, 0xa0, 0xff, 0xff, 0x00, 0x00, 0x6a, 0x5b, 0xc2, 0x5e, 0x00, 0x00, 0x00, 0x00, + 0x21, 0x8e, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static char ecdh_cp_pubkey_secp320k1[] = { + 0x04, + 0x5f, 0x25, 0x77, 0xa9, 0xb5, 0x0a, 0x6f, 0xd3, 0xcb, 0x43, 0x93, 0xe0, 0xb7, 0x41, 0x3b, 0x56, + 0xc3, 0xfe, 0x1e, 0x5c, 0xb9, 0x32, 0x3a, 0x74, 0x68, 0xf8, 0x69, 0xea, 0xcf, 0x5b, 0x82, 0xd2, + 0x38, 0x8c, 0x96, 0x87, 0x97, 0xc3, 0x89, 0x9d, 0x13, 0x02, 0x40, 0xba, 0x88, 0xfa, 0x0c, 0x5a, + 0x64, 0x52, 0x7c, 0x36, 0xbd, 0xa6, 0x92, 0xb7, 0x6f, 0xb1, 0xd5, 0x81, 0xdb, 0xd5, 0x78, 0x96, + 0x50, 0x6a, 0x48, 0xec, 0x75, 0x04, 0x01, 0x3e, 0x86, 0x07, 0x74, 0x5b, 0xa7, 0x72, 0x44, 0x27 +}; + +static char ecdh_except_b_pubkey_secp320k1[] = { + 0x04, + 0x5f, 0x25, 0x77, 0xa9, 0xb5, 0x0a, 0x6f, 0xd3, 0xcb, 0x43, 0x93, 0xe0, 0xb7, 0x41, 0x3b, 0x56, + 0xc3, 0xfe, 0x1e, 0x5c, 0xb9, 0x32, 0x3a, 0x74, 0x68, 0xf8, 0x69, 0xea, 0xcf, 0x5b, 0x82, 0xd2, + 0x38, 0x8c, 0x96, 0x87, 0x97, 0xc3, 0x89, 0x9d, 0x13, 0x02, 0x40, 0xba, 0x88, 0xfa, 0x0c, 0x5a, + 0x64, 0x52, 0x7c, 0x36, 0xbd, 0xa6, 0x92, 0xb7, 0x6f, 0xb1, 0xd5, 0x81, 0xdb, 0xd5, 0x78, 0x96, + 0x50, 0x6a, 0x48, 0xec, 0x75, 0x04, 0x01, 0x3e, 0x86, 0x07, 0x74, 0x5b, 0xa7, 0x72, 0x44, 0x27 +}; + +static char ecdh_cp_sharekey_secp320k1[] = { + 0x69, 0x8a, 0x70, 0x4e, 0xf8, 0x4a, 0x9a, 0x80, 0xe8, 0x48, 0xc9, 0xb9, 0xac, 0x2a, 0x74, 0xf0, + 0xe5, 0x29, 0x60, 0x6d, 0xf3, 0x4e, 0x01, 0xa6, 0x20, 0x37, 0xc2, 0x0f, 0xba, 0x98, 0x91, 0x3b, + 0xc2, 0x75, 0xa3, 0xc6, 0x75, 0x90, 0x79, 0xb4 +}; + +/* ecc sign or verf*/ +static char ecc_except_kinv_secp320k1[] = { + 0x71, 0x71, 0xb4, 0x5b, 0x79, 0x51, 0x94, 0x70, 0x53, 0xf9, 0x77, 0x02, 0x64, 0xef, 0xc4, 0xdb, + 0x64, 0xfc, 0xbe, 0x4e, 0x44, 0x4a, 0xc6, 0x54, 0x71, 0x69, 0x2e, 0x4a, 0x46, 0xa7, 0x2d, 0xa3 +}; + +static char ecc_except_e_secp320k1[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04 +}; + +/* 384 */ +static char ecdh_a_secp384r1[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFC +}; + +static char ecdh_b_secp384r1[] = { + 0xB3, 0x31, 0x2F, 0xA7, 0xE2, 0x3E, 0xE7, 0xE4, 0x98, 0x8E, 0x05, 0x6B, + 0xE3, 0xF8, 0x2D, 0x19, 0x18, 0x1D, 0x9C, 0x6E, 0xFE, 0x81, 0x41, 0x12, + 0x03, 0x14, 0x08, 0x8F, 0x50, 0x13, 0x87, 0x5A, 0xC6, 0x56, 0x39, 0x8D, + 0x8A, 0x2E, 0xD1, 0x9D, 0x2A, 0x85, 0xC8, 0xED, 0xD3, 0xEC, 0x2A, 0xEF +}; + +static char ecdh_p_secp384r1[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF +}; + +static char ecdh_n_secp384r1[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC7, 0x63, 0x4D, 0x81, 0xF4, 0x37, 0x2D, 0xDF, 0x58, 0x1A, 0x0D, 0xB2, + 0x48, 0xB0, 0xA7, 0x7A, 0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73 +}; + +static char ecdh_g_secp384r1[] = { + 0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37, 0x8E, 0xB1, 0xC7, 0x1E, + 0xF3, 0x20, 0xAD, 0x74, 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98, + 0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38, 0x55, 0x02, 0xF2, 0x5D, + 0xBF, 0x55, 0x29, 0x6C, 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7, + 0x36, 0x17, 0xDE, 0x4A, 0x96, 0x26, 0x2C, 0x6F, 0x5D, 0x9E, 0x98, 0xBF, + 0x92, 0x92, 0xDC, 0x29, 0xF8, 0xF4, 0x1D, 0xBD, 0x28, 0x9A, 0x14, 0x7C, + 0xE9, 0xDA, 0x31, 0x13, 0xB5, 0xF0, 0xB8, 0xC0, 0x0A, 0x60, 0xB1, 0xCE, + 0x1D, 0x7E, 0x81, 0x9D, 0x7A, 0x43, 0x1D, 0x7C, 0x90, 0xEA, 0x0E, 0x5F +}; + +static char ecdh_da_secp384r1[] = { + 0xee, 0x57, 0xd7, 0xad, 0xbc, 0x8c, 0x5d, 0x82, 0x65, 0x7f, 0x03, 0xcb, 0x12, 0xc1, 0x38, 0x0d, + 0x02, 0x5c, 0xb7, 0x8f, 0xa4, 0x36, 0x56, 0x27, 0x25, 0x85, 0xaa, 0x3e, 0xdf, 0x22, 0x88, 0x7b, + 0xe3, 0xe7, 0xc5, 0xf1, 0xd7, 0x37, 0x8c, 0xc7, 0x56, 0xca, 0xa7, 0x93, 0x37, 0xbd, 0xf9, 0x37 +}; + +static char ecdh_cp_pubkey_secp384r1[] = { + 0x04, + 0x7d, 0x54, 0xd0, 0x72, 0x45, 0x4b, 0x5a, 0x48, 0xed, 0xc6, 0x19, 0xde, 0x8f, 0x1b, 0xa6, 0xfd, + 0xe5, 0x00, 0xbc, 0x74, 0xbb, 0xee, 0xdc, 0x6b, 0x1c, 0x6d, 0x36, 0xf1, 0x2a, 0x6a, 0x3c, 0xcd, + 0xd5, 0xb9, 0xf8, 0x3c, 0x57, 0xe8, 0xc2, 0xb2, 0xe6, 0x60, 0x58, 0x03, 0x3e, 0x48, 0xf4, 0xc4, + 0x4b, 0x80, 0x58, 0x8c, 0xc7, 0x65, 0x2e, 0xdd, 0x23, 0x31, 0xd2, 0xae, 0x62, 0x62, 0xc3, 0xb4, + 0x57, 0x88, 0xc6, 0x84, 0x51, 0xaf, 0x8c, 0x7b, 0x94, 0x2a, 0x43, 0x68, 0x31, 0xbd, 0x3d, 0x4f, + 0x43, 0xae, 0x79, 0x50, 0x80, 0x60, 0x09, 0xfa, 0x42, 0xfe, 0x9d, 0x18, 0xce, 0xbe, 0xfd, 0x64 +}; + +static char ecdh_except_b_pubkey_secp384r1[] = { + 0x04, + 0x7d, 0x54, 0xd0, 0x72, 0x45, 0x4b, 0x5a, 0x48, 0xed, 0xc6, 0x19, 0xde, 0x8f, 0x1b, 0xa6, 0xfd, + 0xe5, 0x00, 0xbc, 0x74, 0xbb, 0xee, 0xdc, 0x6b, 0x1c, 0x6d, 0x36, 0xf1, 0x2a, 0x6a, 0x3c, 0xcd, + 0xd5, 0xb9, 0xf8, 0x3c, 0x57, 0xe8, 0xc2, 0xb2, 0xe6, 0x60, 0x58, 0x03, 0x3e, 0x48, 0xf4, 0xc4, + 0x4b, 0x80, 0x58, 0x8c, 0xc7, 0x65, 0x2e, 0xdd, 0x23, 0x31, 0xd2, 0xae, 0x62, 0x62, 0xc3, 0xb4, + 0x57, 0x88, 0xc6, 0x84, 0x51, 0xaf, 0x8c, 0x7b, 0x94, 0x2a, 0x43, 0x68, 0x31, 0xbd, 0x3d, 0x4f, + 0x43, 0xae, 0x79, 0x50, 0x80, 0x60, 0x09, 0xfa, 0x42, 0xfe, 0x9d, 0x18, 0xce, 0xbe, 0xfd, 0x64 +}; + +static char ecdh_cp_sharekey_secp384r1[] = { + 0x82, 0x80, 0x4b, 0x00, 0x8c, 0x3c, 0x29, 0x51, 0xc8, 0x77, 0x1f, 0x72, 0xe2, 0x8c, 0x9d, 0x2a, + 0x3c, 0xf3, 0xe3, 0x7c, 0xc0, 0xc9, 0x80, 0x20, 0xe2, 0x1a, 0x45, 0xb6, 0x20, 0x13, 0x18, 0x91, + 0x61, 0xfa, 0xf1, 0x9d, 0x9f, 0xf2, 0x95, 0x78, 0xdd, 0xfe, 0x73, 0x9f, 0x09, 0x24, 0xa1, 0x4b +}; + +/* ecc sign or verf*/ +static char ecc_except_kinv_secp384r1[] = { + /* + 0x71, 0x71, 0xb4, 0x5b, 0x79, 0x51, 0x94, 0x70, 0x53, 0xf9, 0x77, 0x02, 0x64, 0xef, 0xc4, 0xdb, + 0x64, 0xfc, 0xbe, 0x4e, 0x44, 0x4a, 0xc6, 0x54, 0x71, 0x69, 0x2e, 0x4a, 0x46, 0xa7, 0x2d, 0xa3*/ +}; + +static char ecc_except_e_secp384r1[] = { + /* + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04*/ +}; + +/* 521 */ +static char ecdh_a_secp521r1[] = { + 0x01, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc +}; + +static char ecdh_b_secp521r1[] = { + 0x00, 0xe6, 0x15, 0x1c, 0x79, 0x17, 0x8d, 0x1b, 0x5c, 0xfa, + 0xbc, 0x7e, 0x53, 0x82, 0xb9, 0x33, 0xbc, 0x16, 0x2c, 0x9f, 0x27, 0xed, 0x6d, 0x79, 0x34, 0xf2, + 0xba, 0x07, 0x92, 0x9e, 0x96, 0xea, 0xe9, 0xdd, 0xb5, 0xae, 0x57, 0x7a, 0x54, 0xe1, 0x3c, 0x71, + 0xa9, 0x6e, 0x3e, 0x3d, 0x88, 0xaf, 0x92, 0x77, 0xe8, 0xe6, 0x61, 0xfe, 0xed, 0x39, 0xbd, 0x11, + 0x19, 0x25, 0x3f, 0x09, 0x4e, 0x71, 0x25, 0xcc +}; + +static char ecdh_p_secp521r1[] = { + 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +static char ecdh_n_secp521r1[] = { + 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x51, 0x86, 0x87, 0x83, 0xbf, 0x2f, 0x96, 0x6b, + 0x7f, 0xcc, 0x01, 0x48, 0xf7, 0x09, 0xa5, 0xd0, 0x3b, 0xb5, 0xc9, 0xb8, 0x89, 0x9c, 0x47, 0xae, + 0xbb, 0x6f, 0xb7, 0x1e, 0x91, 0x38, 0x64, 0x09 +}; + +static char ecdh_g_secp521r1[] = { + 0x00, 0xc6, + 0x85, 0x8e, 0x06, 0xb7, 0x04, 0x04, 0xe9, 0xcd, 0x9e, 0x3e, 0xcb, 0x66, 0x23, 0x95, 0xb4, 0x42, + 0x9c, 0x64, 0x81, 0x39, 0x05, 0x3f, 0xb5, 0x21, 0xf8, 0x28, 0xaf, 0x60, 0x6b, 0x4d, 0x3d, 0xba, + 0xa1, 0x4b, 0x5e, 0x77, 0xef, 0xe7, 0x59, 0x28, 0xfe, 0x1d, 0xc1, 0x27, 0xa2, 0xff, 0xa8, 0xde, + 0x33, 0x48, 0xb3, 0xc1, 0x85, 0x6a, 0x42, 0x9b, 0xf9, 0x7e, 0x7e, 0x31, 0xc2, 0xe5, 0xbd, 0x66, + + 0x01, 0x18, 0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b, 0xc0, 0x04, + 0x5c, 0x8a, 0x5f, 0xb4, 0x2c, 0x7d, 0x1b, 0xd9, 0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b, 0x44, 0x68, + 0x17, 0xaf, 0xbd, 0x17, 0x27, 0x3e, 0x66, 0x2c, 0x97, 0xee, 0x72, 0x99, 0x5e, 0xf4, 0x26, 0x40, + 0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad, 0x07, 0x61, 0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72, 0xc2, 0x40, + 0x88, 0xbe, 0x94, 0x76, 0x9f, 0xd1, 0x66, 0x50 +}; + +static char ecdh_da_secp521r1[] = { + 0x00, 0xe6, 0x15, 0x1c, 0x79, 0x17, 0x8d, 0x1b, 0x5c, 0xfa, + 0xbc, 0x7e, 0x53, 0x82, 0xb9, 0x33, 0xbc, 0x16, 0x2c, 0x9f, 0x27, 0xed, 0x6d, 0x79, 0x34, 0xf2, + 0xba, 0x07, 0x92, 0x9e, 0x96, 0xea, 0xe9, 0xdd, 0xb5, 0xae, 0x57, 0x7a, 0x54, 0xe1, 0x3c, 0x71, + 0xa9, 0x6e, 0x3e, 0x3d, 0x88, 0xaf, 0x92, 0x77, 0xe8, 0xe6, 0x61, 0xfe, 0xed, 0x39, 0xbd, 0x11, + 0x19, 0x25, 0x3f, 0x09, 0x4e, 0x71, 0x25, 0xcc +}; + +static char ecdh_except_b_pubkey_secp521r1[] = { + 0x04, + 0x01, 0x16, 0x0a, 0x52, 0xaa, 0x18, 0x96, 0x56, 0xf6, 0x27, 0xd1, 0x59, 0xbd, 0x7d, 0x0f, 0x57, + 0xfd, 0x34, 0xfa, 0x52, 0x1b, 0x04, 0xbd, 0x9a, 0x90, 0xd5, 0x8d, 0xad, 0x41, 0x32, 0x80, 0x14, + 0x6e, 0x73, 0x58, 0x83, 0x98, 0xeb, 0xb0, 0x6b, 0xb5, 0x63, 0x8e, 0xa1, 0x06, 0x04, 0x86, 0x94, + 0x9e, 0x34, 0x53, 0xf4, 0x93, 0x37, 0x1c, 0xbc, 0xbb, 0x7b, 0x4c, 0x97, 0x87, 0x32, 0x92, 0xf2, + 0x36, 0xdd, 0x01, 0x30, 0xa1, 0xa7, 0x68, 0x5a, 0x3e, 0x40, 0xe9, 0xbf, 0x3d, 0x2a, 0x1b, 0xbf, + 0x09, 0xa0, 0x51, 0xe8, 0x1d, 0x23, 0x27, 0x9c, 0x70, 0xb2, 0x18, 0x42, 0x02, 0x09, 0x02, 0x66, + 0xc7, 0xdb, 0x1a, 0xec, 0xe5, 0x20, 0x68, 0x31, 0x31, 0x6e, 0x70, 0xbe, 0x09, 0x72, 0x79, 0x42, + 0xe2, 0x3b, 0x3b, 0xd3, 0x0a, 0xe4, 0x9c, 0x34, 0x4c, 0x61, 0x74, 0x7c, 0xed, 0xe1, 0x84, 0x89, + 0x4b, 0xf4, 0xd5, 0xc3 +}; + +static char ecdh_cp_pubkey_secp521r1[] = { + 0x04, + 0x01, 0x16, 0x0a, 0x52, 0xaa, 0x18, 0x96, 0x56, 0xf6, 0x27, 0xd1, 0x59, 0xbd, 0x7d, 0x0f, 0x57, + 0xfd, 0x34, 0xfa, 0x52, 0x1b, 0x04, 0xbd, 0x9a, 0x90, 0xd5, 0x8d, 0xad, 0x41, 0x32, 0x80, 0x14, + 0x6e, 0x73, 0x58, 0x83, 0x98, 0xeb, 0xb0, 0x6b, 0xb5, 0x63, 0x8e, 0xa1, 0x06, 0x04, 0x86, 0x94, + 0x9e, 0x34, 0x53, 0xf4, 0x93, 0x37, 0x1c, 0xbc, 0xbb, 0x7b, 0x4c, 0x97, 0x87, 0x32, 0x92, 0xf2, + 0x36, 0xdd, 0x01, 0x30, 0xa1, 0xa7, 0x68, 0x5a, 0x3e, 0x40, 0xe9, 0xbf, 0x3d, 0x2a, 0x1b, 0xbf, + 0x09, 0xa0, 0x51, 0xe8, 0x1d, 0x23, 0x27, 0x9c, 0x70, 0xb2, 0x18, 0x42, 0x02, 0x09, 0x02, 0x66, + 0xc7, 0xdb, 0x1a, 0xec, 0xe5, 0x20, 0x68, 0x31, 0x31, 0x6e, 0x70, 0xbe, 0x09, 0x72, 0x79, 0x42, + 0xe2, 0x3b, 0x3b, 0xd3, 0x0a, 0xe4, 0x9c, 0x34, 0x4c, 0x61, 0x74, 0x7c, 0xed, 0xe1, 0x84, 0x89, + 0x4b, 0xf4, 0xd5, 0xc3 +}; + +static char ecdh_cp_sharekey_secp521r1[] = { + 0x01, 0xaf, 0x53, 0x84, 0x60, 0x59, 0x79, 0x64, 0x09, 0x5f, 0x2b, 0x4e, 0x82, 0xc4, 0x79, 0x21, + 0x55, 0x9c, 0xb0, 0x2f, 0x7d, 0xd4, 0x2f, 0x5d, 0xca, 0xfc, 0x4f, 0x70, 0x28, 0x6e, 0x2b, 0x13, + 0x2e, 0x5f, 0xf0, 0x1f, 0x50, 0x87, 0xf5, 0x82, 0x2f, 0xa7, 0x31, 0x5b, 0xfd, 0x5c, 0x0e, 0xef, + 0xaf, 0x5c, 0x80, 0x53, 0x48, 0xed, 0xcf, 0x14, 0xdc, 0x91, 0xc5, 0xc9, 0x1b, 0xff, 0xa8, 0x16, + 0x42, 0xa8 +}; + +/* ecc sign or verf*/ +static char ecc_except_kinv_secp521r1[] = { + 0x71, 0x71, 0xb4, 0x5b, 0x79, 0x51, 0x94, 0x70, 0x53, 0xf9, 0x77, 0x02, 0x64, 0xef, 0xc4, 0xdb, + 0x64, 0xfc, 0xbe, 0x4e, 0x44, 0x4a, 0xc6, 0x54, 0x71, 0x69, 0x2e, 0x4a, 0x46, 0xa7, 0x2d, 0xa3 +}; + +static char ecc_except_e_secp521r1[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04 +}; + +static char sm2_k[] = { + 0x7c, 0x47, 0x81, 0x10, 0x54, 0xc6, 0xf9, 0x96, 0x13, 0xa5, 0x78, 0xeb, 0x84, 0x53, 0x70, 0x6c, + 0xcb, 0x96, 0x38, 0x4f, 0xe7, 0xdf, 0x5c, 0x17, 0x16, 0x71, 0xe7, 0x60, 0xbf, 0xa8, 0xbe, 0x3a +}; + +static char sm2_id[] = { + 0x41, 0x4c, 0x49, 0x43, 0x45, 0x31, 0x32, 0x33, 0x40, 0x59, 0x41, 0x48, 0x4f, 0x4f, 0x2e, 0x43, + 0x4f, 0x4d +}; + +static char sm2_plaintext[] = { + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74 +}; + +static char sm2_plaintext_l[513] = { + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74 +}; + +static char sm2_sign_data[] = { + /* r */ + 0xe6, 0xcd, 0x2d, 0xf9, 0x4f, 0x57, 0x40, 0x9e, 0x6b, 0xec, 0x8c, 0x0e, 0xf0, 0x44, 0x5c, 0xa4, + 0xfa, 0xea, 0x24, 0xe3, 0xf2, 0x28, 0x0e, 0xad, 0xc1, 0xa4, 0x1c, 0xf6, 0x24, 0x88, 0xaf, 0xd2, + + /* s */ + 0x98, 0x0e, 0x4f, 0xda, 0xbd, 0xe9, 0x9e, 0xc1, 0x6d, 0x59, 0x87, 0xd0, 0x23, 0x19, 0x84, 0xd1, + 0x94, 0x07, 0x7b, 0xb5, 0x43, 0xa8, 0x93, 0x00, 0xd4, 0xbb, 0xc7, 0xf8, 0x83, 0xb3, 0xf0, 0xc3, +}; + +static char sm2_ciphertext[] = { + /* c1 x */ + 0xe6, 0xcd, 0x2d, 0xf9, 0x4f, 0x57, 0x40, 0x9e, 0x6b, 0xec, 0x8c, 0x0e, 0xf0, 0x44, 0x5c, 0xa4, + 0xfa, 0xe9, 0xb7, 0x7e, 0x7e, 0xb4, 0xad, 0x46, 0x5c, 0x83, 0xb8, 0x8c, 0xbd, 0x23, 0x3c, 0x5e, + /* c1 y */ + 0x80, 0x89, 0xf0, 0xea, 0x2c, 0x84, 0x63, 0x45, 0xd8, 0x99, 0x7b, 0x5c, 0x2c, 0x75, 0x7d, 0x8e, + 0x5c, 0x99, 0x6e, 0x46, 0x85, 0x9f, 0x19, 0xd3, 0x7e, 0xb0, 0x3b, 0x24, 0xde, 0xab, 0xae, 0x30, + /* c3 */ + 0xfb, 0xcf, 0x24, 0x19, 0xf8, 0x61, 0x1c, 0xba, 0xb1, 0xd0, 0x6f, 0x4f, 0x84, 0xda, 0x9a, 0xe6, + 0x2d, 0x42, 0x27, 0xa1, 0x2b, 0x27, 0x26, 0x32, 0xc2, 0x6d, 0xda, 0x35, 0x54, 0xf9, 0xfc, 0xf8, + /* c2 */ + 0xdf, 0xe8, 0x59, 0xe8, 0x35, 0xb3, 0x98, 0x18, 0xca, 0x56, 0xaa, 0x29, 0x7b, 0x01, +}; + +static char sm2_ciphertext_l[609] = { + 0xe6, 0xcd, 0x2d, 0xf9, 0x4f, 0x57, 0x40, 0x9e, 0x6b, 0xec, 0x8c, 0x0e, 0xf0, 0x44, 0x5c, 0xa4, + 0xfa, 0xe9, 0xb7, 0x7e, 0x7e, 0xb4, 0xad, 0x46, 0x5c, 0x83, 0xb8, 0x8c, 0xbd, 0x23, 0x3c, 0x5e, + 0x80, 0x89, 0xf0, 0xea, 0x2c, 0x84, 0x63, 0x45, 0xd8, 0x99, 0x7b, 0x5c, 0x2c, 0x75, 0x7d, 0x8e, + 0x5c, 0x99, 0x6e, 0x46, 0x85, 0x9f, 0x19, 0xd3, 0x7e, 0xb0, 0x3b, 0x24, 0xde, 0xab, 0xae, 0x30, + 0xb6, 0x1b, 0x64, 0x56, 0x32, 0x5c, 0x33, 0x34, 0xa6, 0x68, 0x5f, 0x7a, 0x4c, 0x9b, 0xf0, 0x0c, + 0xbf, 0x4d, 0x2a, 0xbf, 0x2f, 0xc2, 0xf4, 0x42, 0x13, 0x61, 0xd4, 0xbb, 0x78, 0x29, 0x0c, 0x10, + 0xdf, 0xe8, 0x59, 0xe8, 0x35, 0xb3, 0x98, 0x18, 0xca, 0x56, 0xaa, 0x29, 0x7b, 0x01, 0xfc, 0xc3, + 0x78, 0xcd, 0x8e, 0x0f, 0x12, 0x24, 0xdc, 0xaf, 0xc1, 0x3c, 0x28, 0x3d, 0xeb, 0x7c, 0x46, 0x69, + 0x5f, 0x69, 0x4e, 0xc7, 0x86, 0x99, 0xa2, 0x41, 0x2b, 0xb4, 0xce, 0x91, 0xe5, 0x6c, 0x2e, 0x10, + 0x98, 0xcd, 0x1a, 0xf8, 0xac, 0x8a, 0x26, 0x92, 0xbd, 0x62, 0xe1, 0x27, 0x7e, 0xbd, 0xe1, 0xe6, + 0xec, 0x71, 0x9c, 0xa2, 0xfd, 0xf1, 0xa6, 0xaa, 0xf0, 0x4f, 0xa6, 0x05, 0x44, 0xd7, 0xc4, 0x8a, + 0xee, 0x61, 0x44, 0x41, 0xc5, 0x27, 0x76, 0x3e, 0x55, 0x0e, 0x70, 0xb7, 0xcc, 0x9d, 0x8e, 0xe4, + 0xea, 0x45, 0xc4, 0xce, 0xfc, 0x90, 0x44, 0xb7, 0xe9, 0x98, 0x63, 0x30, 0xfd, 0xca, 0x9f, 0x45, + 0x11, 0x08, 0x59, 0x80, 0xbd, 0xf2, 0xa5, 0x62, 0x9f, 0x5d, 0xb6, 0x1a, 0x5d, 0x3c, 0x72, 0x44, + 0x3e, 0x5a, 0x7c, 0xc4, 0x1a, 0xb1, 0x77, 0x3a, 0xb7, 0xfb, 0x01, 0x8b, 0xef, 0xc0, 0xf9, 0x87, + 0x46, 0x20, 0xb7, 0xef, 0x64, 0xc8, 0x9c, 0xeb, 0x26, 0x25, 0x8a, 0x6b, 0x4f, 0x75, 0x7c, 0x86, + 0xfd, 0xe4, 0x47, 0x40, 0x2c, 0xb7, 0x5c, 0x7e, 0x98, 0xad, 0xa3, 0x3f, 0x95, 0xa0, 0x1f, 0x47, + 0x3a, 0x1f, 0xde, 0xa0, 0x29, 0x78, 0x93, 0xcd, 0xc7, 0xc8, 0x29, 0xd6, 0xbe, 0x8d, 0xee, 0x76, + 0xd0, 0xed, 0x19, 0x2b, 0x0f, 0x57, 0x52, 0xf2, 0x19, 0x8a, 0x95, 0xcf, 0x23, 0x50, 0xbb, 0x13, + 0x5e, 0x89, 0xe6, 0x30, 0x87, 0x90, 0x28, 0xa5, 0x3a, 0xba, 0x16, 0x2f, 0x15, 0x98, 0x40, 0x82, + 0xd6, 0xbb, 0xc7, 0xaf, 0xa2, 0xf5, 0x33, 0xa7, 0xba, 0xb5, 0x29, 0x78, 0x53, 0x6a, 0x03, 0xd5, + 0x5a, 0x0d, 0x9c, 0xa4, 0x31, 0xab, 0x33, 0xc2, 0x19, 0x75, 0xbb, 0x25, 0x37, 0x44, 0x00, 0xd2, + 0xfb, 0xd9, 0xa0, 0xa0, 0xb6, 0x80, 0x4b, 0xd5, 0xc2, 0x2e, 0x80, 0xec, 0x86, 0x5a, 0x9f, 0x18, + 0x7b, 0x7f, 0x40, 0x92, 0xcb, 0x98, 0x60, 0x74, 0x60, 0x48, 0xd2, 0xe2, 0x56, 0x6d, 0xee, 0x2f, + 0x97, 0x96, 0x8b, 0xaa, 0x75, 0x94, 0xb7, 0x92, 0xfc, 0xd3, 0x37, 0xfd, 0x19, 0x6b, 0x1a, 0xba, + 0xf2, 0x33, 0x5e, 0x15, 0x93, 0xb0, 0xc9, 0x0f, 0x7c, 0x6e, 0x4b, 0xc0, 0xce, 0xf2, 0x22, 0x7f, + 0xfa, 0xff, 0x78, 0x90, 0xdb, 0x3c, 0xf5, 0x4d, 0x6a, 0x5d, 0x80, 0xcb, 0x62, 0x54, 0x67, 0xae, + 0x03, 0x82, 0xaa, 0xa3, 0x63, 0x4e, 0x01, 0x25, 0x32, 0x8f, 0xe9, 0x11, 0xe7, 0x12, 0x58, 0xda, + 0x3c, 0x4d, 0x5f, 0x1e, 0xae, 0x10, 0x6c, 0x12, 0x18, 0x5d, 0xa6, 0x7a, 0x37, 0x64, 0x83, 0x64, + 0xca, 0x78, 0xd6, 0x15, 0xbc, 0xb9, 0xb6, 0xfb, 0x54, 0xf3, 0xed, 0x13, 0xc3, 0x3e, 0xad, 0x3e, + 0x57, 0xb8, 0x8c, 0xc4, 0x9f, 0x7b, 0x1f, 0x40, 0x86, 0x13, 0x40, 0xfc, 0xba, 0x0a, 0x73, 0x98, + 0xf5, 0xee, 0xc7, 0x53, 0xbb, 0x87, 0xd6, 0x9d, 0x99, 0x78, 0x8b, 0xce, 0x4a, 0x1f, 0xf7, 0x46, + 0x93, 0xd5, 0x27, 0x7e, 0x69, 0xd1, 0xe9, 0xba, 0xfd, 0x06, 0x36, 0x44, 0x21, 0xee, 0x5a, 0x5a, + 0xb0, 0xdc, 0xd6, 0xe7, 0x4e, 0x28, 0x71, 0x36, 0x45, 0xa8, 0x89, 0x3b, 0x9e, 0xfd, 0x1f, 0x0b, + 0xcd, 0x86, 0xa7, 0xb9, 0xb1, 0x74, 0xd0, 0x51, 0x3d, 0x1e, 0x8d, 0xb3, 0x4f, 0x46, 0x9f, 0xfb, + 0x36, 0x43, 0x3d, 0xff, 0xaf, 0x19, 0x29, 0xb5, 0x41, 0x4c, 0x75, 0x4d, 0x75, 0x41, 0x5e, 0xe1, + 0x86, 0x5b, 0xbb, 0x94, 0x13, 0xd3, 0xa7, 0x23, 0xb4, 0xfb, 0x6f, 0x7f, 0x36, 0xfe, 0x9f, 0xec, + 0x80, 0x56, 0x5c, 0x79, 0x78, 0x9d, 0xed, 0xe0, 0x0a, 0x68, 0xd9, 0xc1, 0x19, 0x93, 0x94, 0x2c, + 0x3d, +}; + +static char sm2_pubkey[] = { + 0x04, + 0x09, 0xf9, 0xdf, 0x31, 0x1e, 0x54, 0x21, 0xa1, 0x50, 0xdd, 0x7d, 0x16, 0x1e, 0x4b, 0xc5, 0xc6, + 0x72, 0x17, 0x9f, 0xad, 0x18, 0x33, 0xfc, 0x07, 0x6b, 0xb0, 0x8f, 0xf3, 0x56, 0xf3, 0x50, 0x20, + 0xcc, 0xea, 0x49, 0x0c, 0xe2, 0x67, 0x75, 0xa5, 0x2d, 0xc6, 0xea, 0x71, 0x8c, 0xc1, 0xaa, 0x60, + 0x0a, 0xed, 0x05, 0xfb, 0xf3, 0x5e, 0x08, 0x4a, 0x66, 0x32, 0xf6, 0x07, 0x2d, 0xa9, 0xad, 0x13 +}; + +static char sm2_priv[] = { + 0x39, 0x45, 0x20, 0x8f, 0x7b, 0x21, 0x44, 0xb1, 0x3f, 0x36, 0xe3, 0x8a, 0xc6, 0xd3, 0x9f, 0x95, + 0x88, 0x93, 0x93, 0x69, 0x28, 0x60, 0xb5, 0x1a, 0x42, 0xfb, 0x81, 0xef, 0x4d, 0xf7, 0xc5, 0xb8 +}; + +static char sm2_digest[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74 +}; +#endif diff --git a/uadk/test/hisi_hpre_test/test_hisi_hpre.c b/uadk/test/hisi_hpre_test/test_hisi_hpre.c new file mode 100644 index 0000000..57d76fd --- /dev/null +++ b/uadk/test/hisi_hpre_test/test_hisi_hpre.c @@ -0,0 +1,9318 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. */ + +//#define DEBUG +//#define WITH_OPENSSL_DIR + +#include +#include +#include +#include +#define __USE_GNU +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hpre_test_sample.h" +#include "test_hisi_hpre.h" +#include "../../include/wd.h" +#include "../../include/wd_rsa.h" +#include "../../include/wd_dh.h" +#include "../../include/wd_ecc.h" +#include "../../include/drv/wd_ecc_drv.h" + +#define HPRE_TST_PRT printf +#define BN_ULONG unsigned long +#define RSA_NO_PADDING 3 +#define HPRE_TST_MAX_Q 1 +#define HPRE_PADDING_SZ 16 +#define TEST_MAX_THRD 256 +#define MAX_TRY_TIMES 10000 +#define LOG_INTVL_NUM 8 +#define WD_RSA_CTX_MSG_NUM 64 +#define WD_DH_CTX_MSG_NUM 64 +#define DH_GENERATOR_2 2 +#define DH_GENERATOR_5 5 +#define TEST_CNT 10 +#define INVALID_LEN 0xFFFFFFFF + +typedef unsigned int u32; + +pthread_mutex_t mute; + +struct bignum_st { + BN_ULONG *d; /* Pointer to an array of 'BN_BITS2' bit + * chunks. */ + int top; /* Index of last used d +1. */ + /* The next are internal book keeping for bn_expand. */ + int dmax; /* Size of the d array. */ + int neg; /* one if the number is negative */ + int flags; +}; + +typedef struct { + int nid; + const char *comment; +} EC_builtin_curve; + +/* stub structures */ +struct rsa_st { + int xxx; +}; + +struct dh_st { + int xxx; +}; + +struct bn_gencb_st { + int xxx; +}; + +struct test_hpre_pthread_dt { + int cpu_id; + enum alg_op_type op_type; + const char *alg_name; + int thread_num; + float perf; + struct timeval start_tval; + u32 send_task_num; + u32 recv_task_num; +}; + +struct ec_key_st { + int xxx; +}; + +struct ec_point_st { + int xxx; +}; + +struct ec_group_st { + int xxx; +}; + +struct ec_method_st { + int xxx; +}; + +struct ec_sig_st { + int xxx; +}; + +struct evp_md_st { + int xxx; +}; + +struct evp_md_ctx_st { + int xxx; +}; + +struct bn_ctx_st { + int xxx; +}; + +typedef struct rand_meth_st { + int (*seed)(const void *buf, int num); + int (*bytes)(unsigned char *buf, int num); + void (*cleanup)(void); + int (*add)(const void *buf, int num, double entropy); + int (*pseudorand)(unsigned char *buf, int num); + int (*status)(void); +}RAND_METHOD; + +/* stub definitions */ +typedef struct rsa_st RSA; +typedef struct dh_st DH; +typedef struct bignum_st BIGNUM; +typedef struct bn_gencb_st BN_GENCB; + +typedef struct ec_key_st EC_KEY; +typedef struct ec_point_st EC_POINT; +typedef struct ec_group_st EC_GROUP; +typedef struct ec_method_st EC_METHOD; +typedef struct ec_sig_st ECDSA_SIG; + +typedef struct evp_md_st EVP_MD; +typedef struct evp_md_ctx_st EVP_MD_CTX; +typedef struct bn_ctx_st BN_CTX; + +enum ecc_msg_type { + MSG_PLAINTEXT, + MSG_DIGEST, + MSG_CIPHERTEXT +}; + +enum ecc_rand_type { + RAND_NON, + RAND_CB, + RAND_PARAM +}; + +enum dh_check_index { + DH_INVALID, + DH_ALICE_PUBKEY, + DH_BOB_PUBKEY, + DH_ALICE_PRIVKEY +}; + +enum ecc_hash_type { + HASH_NON, + HASH_SM3, + HASH_SHA1, + HASH_SHA224, + HASH_SHA256, + HASH_SHA384, + HASH_SHA512, + HASH_MD4, + HASH_MD5 + +}; + +struct rsa_async_tag { + handle_t sess; + int thread_id; + int cnt; + struct test_hpre_pthread_dt *thread_info; +}; + +struct dh_user_tag_info { + u32 op; + int pid; + int thread_id; + void *test_ctx; + void *thread_data; +}; + +struct async_test_openssl_param { + RSA *rsa; + BIGNUM *p; + BIGNUM *q; + BIGNUM *e; + BIGNUM *n; + BIGNUM *d; + BIGNUM *dp; + BIGNUM *dq; + BIGNUM *qinv; + void *ssl_verify_result; + void *ssl_sign_result; + void *plantext; + int size; +}; + +struct ecc_curve_tbl { + const char *name; + unsigned int nid; + unsigned int curve_id; +}; + +struct hpre_test_config { + __u32 key_bits; + __u32 times; + __u32 seconds; + __u8 check; + __u8 perf_test; + __u8 soft_test; + __u8 use_env; + __u8 with_log; + __u8 data_from; // 0 - openssl generate 1 - sample data + __u8 trd_num; + __u8 msg_type; // 0-plaintext 1-digest 2-ciphertext; + __u8 rand_type; // 0-non 1-cb 2-param; + __u8 hash_type; + __u32 msg_len; + __u32 id_len; + __u32 k_len; + __u64 core_mask[2]; + char alg_mode[10]; + char trd_mode[10]; + char op[20]; + char curve[20]; + char dev_path[PATH_STR_SIZE]; +}; + +static struct hpre_test_config g_config = { + .key_bits = 1024, + .times = 100, + .seconds = 0, + .trd_num = 2, + .use_env = 0, + .msg_type = MSG_PLAINTEXT, + .msg_len = INVALID_LEN, + .id_len = INVALID_LEN, + .k_len = INVALID_LEN, + .hash_type = HASH_SM3, + .rand_type = RAND_CB, + #ifdef WITH_OPENSSL_DIR + .check = 1, + #else + .check = 0, + #endif + .data_from = 0, + .perf_test = 0, + .with_log = 0, + .soft_test = 0, + .core_mask = {0, 0}, + .trd_mode = "sync", + .op = "rsa-gen", + .alg_mode = "com", + .curve = "secp256K1", + .dev_path = "/dev/hisi_hpre-0", +}; + +static volatile int asyn_thread_exit = 0; +static pthread_t system_test_thrds[TEST_MAX_THRD]; +static struct test_hpre_pthread_dt test_thrds_data[TEST_MAX_THRD]; +static struct async_test_openssl_param ssl_params; +struct wd_ctx_config g_ctx_cfg; +static __thread u32 g_is_set_prikey; // ecdh used +static __thread u32 g_is_set_pubkey; // ecc used +static pthread_spinlock_t g_lock; + +static bool is_exit(struct test_hpre_pthread_dt *pdata); + +struct ecc_curve_tbl ecc_curve_tbls[] = { + {"secp128R1", 706, WD_SECP128R1}, + {"secp192K1", 711, WD_SECP192K1}, + {"secp224R1", 712, WD_SECP224R1}, + {"secp256K1", 714, WD_SECP256K1}, + {"brainpoolP320R1", 929, WD_BRAINPOOLP320R1}, + {"secp384R1", 715, WD_SECP384R1}, + {"secp521R1", 716, WD_SECP521R1}, + {"null", 0, 0}, +}; + +enum dh_test_item { + TEST_ITEM_INVALID, + SW_GENERATE_KEY, + SW_COMPUTE_KEY, + HW_GENERATE_KEY, + HW_COMPUTE_KEY, +}; + +struct hpre_dh_test_ctx_setup { + const void *x; + const void *p; + const void *g; + const void *except_pub_key; + const void *pub_key; + const void *share_key; + u32 x_size; + u32 p_size; + u32 g_size; + u32 pub_key_size; + u32 share_key_size; + u32 except_pub_key_size; + u32 op_type; + u32 generator; + u32 key_bits; + u32 key_from; //0 - Openssl 1 - Designed + handle_t sess; +}; + +struct hpre_dh_sw_opdata { + BIGNUM *except_pub_key; + unsigned char *pub_key; + u32 pub_key_size; + unsigned char *share_key; + u32 share_key_size; +}; + +struct hpre_dh_test_ctx { + void *priv; + void *req; + unsigned char *cp_share_key; + u32 cp_share_key_size; + unsigned char *cp_pub_key; + u32 cp_pub_key_size; + u32 op; + u32 key_size; + void *pool; +}; + +struct hpre_rsa_test_key_in { + void *e; + void *p; + void *q; + u32 e_size; + u32 p_size; + u32 q_size; + void *data[]; +}; + +#define X25519_KEYLEN 32 +#define X448_KEYLEN 56 +#define ED448_KEYLEN 57 +#define MAX_KEYLEN ED448_KEYLEN + +/* **************** x25519/x448 *******************/ +#define NID_X25519 1034 +#define NID_X448 1035 +# define EVP_PKEY_X25519 NID_X25519 +# define EVP_PKEY_X448 NID_X448 +#define EVP_PKEY_SM2 1172 + +typedef struct { + unsigned char pubkey[MAX_KEYLEN]; + unsigned char *privkey; +} ECX_KEY; + +struct evp_pkey_ctx_st; +typedef struct evp_pkey_ctx_st EVP_PKEY_CTX; + +struct evp_pkey_asn1_method_st { + int pkey_id; + int pkey_base_id; + unsigned long pkey_flags; +}; +typedef struct evp_pkey_asn1_method_st EVP_PKEY_ASN1_METHOD; + +struct engine_st { +}; + +typedef struct engine_st ENGINE; +//typedef _Atomic int CRYPTO_REF_COUNT; +typedef int CRYPTO_REF_COUNT; + +struct evp_pkey_st { + int type; + int save_type; + CRYPTO_REF_COUNT references; + const EVP_PKEY_ASN1_METHOD *ameth; + ENGINE *engine; + ENGINE *pmeth_engine; /* If not NULL public key ENGINE to use */ + union { + void *ptr; + # ifndef OPENSSL_NO_RSA + struct rsa_st *rsa; /* RSA */ + # endif + # ifndef OPENSSL_NO_DSA + struct dsa_st *dsa; /* DSA */ + # endif + # ifndef OPENSSL_NO_DH + struct dh_st *dh; /* DH */ + # endif + # ifndef OPENSSL_NO_EC + struct ec_key_st *ec; /* ECC */ + ECX_KEY *ecx; /* X25519, X448, Ed25519, Ed448 */ + # endif + } pkey; + int save_parameters; + // STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */ + // CRYPTO_RWLOCK *lock; +} /* EVP_PKEY */ ; + +typedef struct evp_pkey_st EVP_PKEY; + +struct evp_pkey_method_st; +typedef struct evp_pkey_method_st EVP_PKEY_METHOD; + +struct evp_pkey_ctx_st { + /* Method associated with this operation */ + const EVP_PKEY_METHOD *pmeth; + /* Engine that implements this method or NULL if builtin */ + ENGINE *engine; + /* Key: may be NULL */ + EVP_PKEY *pkey; + /* Peer key for key agreement, may be NULL */ + EVP_PKEY *peerkey; + /* Actual operation */ + int operation; + /* Algorithm specific data */ + void *data; + /* Application specific data */ + void *app_data; + /* Keygen callback */ + //EVP_PKEY_gen_cb *pkey_gencb; + /* implementation specific keygen data */ + int *keygen_info; + int keygen_info_count; +} /* EVP_PKEY_CTX */ ; + +struct evp_pkey_method_st { + int pkey_id; + int flags; + int (*init) (EVP_PKEY_CTX *ctx); + int (*copy) (EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src); + void (*cleanup) (EVP_PKEY_CTX *ctx); + int (*paramgen_init) (EVP_PKEY_CTX *ctx); + int (*paramgen) (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey); + int (*keygen_init) (EVP_PKEY_CTX *ctx); + int (*keygen) (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey); + int (*sign_init) (EVP_PKEY_CTX *ctx); + int (*sign) (EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, + const unsigned char *tbs, size_t tbslen); + int (*verify_init) (EVP_PKEY_CTX *ctx); + int (*verify) (EVP_PKEY_CTX *ctx, + const unsigned char *sig, size_t siglen, + const unsigned char *tbs, size_t tbslen); + int (*verify_recover_init) (EVP_PKEY_CTX *ctx); + int (*verify_recover) (EVP_PKEY_CTX *ctx, + unsigned char *rout, size_t *routlen, + const unsigned char *sig, size_t siglen); + int (*signctx_init); // (EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx); + int (*signctx); /* (EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, + EVP_MD_CTX *mctx); */ + int (*verifyctx_init); // (EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx); + int (*verifyctx); /* (EVP_PKEY_CTX *ctx, const unsigned char *sig, int siglen, + EVP_MD_CTX *mctx); */ + int (*encrypt_init) (EVP_PKEY_CTX *ctx); + int (*encrypt) (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen); + int (*decrypt_init) (EVP_PKEY_CTX *ctx); + int (*decrypt) (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen); + int (*derive_init) (EVP_PKEY_CTX *ctx); + int (*derive) (EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen); + int (*ctrl) (EVP_PKEY_CTX *ctx, int type, int p1, void *p2); + int (*ctrl_str) (EVP_PKEY_CTX *ctx, const char *type, const char *value); + int (*digestsign); /*(EVP_MD_CTX *ctx, unsigned char *sig, size_t *siglen, + const unsigned char *tbs, size_t tbslen); */ + int (*digestverify); /* (EVP_MD_CTX *ctx, const unsigned char *sig, + size_t siglen, const unsigned char *tbs, + size_t tbslen); */ + int (*check) (EVP_PKEY *pkey); + int (*public_check) (EVP_PKEY *pkey); + int (*param_check) (EVP_PKEY *pkey); + + int (*digest_custom); // (EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx); +} /* EVP_PKEY_METHOD */ ; + +EVP_PKEY *EVP_PKEY_new(void); +EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type); + +int RAND_priv_bytes(unsigned char *buf, int num); +/* **************** x25519/x448 *******************/ + +/******************** ECC *********************/ +enum ecc_test_item { + ECC_TEST_ITEM_INVALID, + ECDH_SW_GENERATE, + ECDH_SW_COMPUTE, + ECDH_HW_GENERATE, + ECDH_HW_COMPUTE, + ECC_SW_SIGN, + ECC_SW_VERF, + ECC_HW_SIGN, + ECC_HW_VERF, + SM2_SW_SIGN, + SM2_SW_VERF, + SM2_HW_SIGN, + SM2_HW_VERF, + SM2_HW_ENC, + SM2_HW_DEC, + SM2_SW_ENC, + SM2_SW_DEC, + SM2_SW_KG, + SM2_HW_KG, + ECC_TEST_ITEM_MAX +}; + +struct ecc_test_ctx_setup { + void *except_pub_key; // use in ecdh phase 2 + const void *pub_key; // use in ecdh phase 1 + const void *share_key; // use in ecdh phase 2 + const void *degist; //ecdsa sign in + const void *k; //ecdsa sign in + const void *rp; //ecdsa sign in + const void *sign; // ecdsa sign out or verf in + const void *priv_key; // use in ecdsa sign + void *msg; // sm2 plaintext,ciphertext or digest input + const void *userid; // sm2 user id + const void *ciphertext; // sm2 ciphertext + const void *plaintext; // sm2 plaintext + u32 key_size; + u32 share_key_size; + u32 except_pub_key_size; + u32 degist_size; + u32 k_size; + u32 rp_size; + u32 sign_size; + u32 priv_key_size; + u32 pub_key_size; + u32 msg_size; + u32 userid_size; + u32 ciphertext_size; + u32 plaintext_size; + u32 op_type; + u32 key_bits; + u32 key_from; //0 - Openssl 1 - Designed + u32 nid; //openssl ecc nid + u32 curve_id; // WD ecc curve_id + handle_t sess; + void *openssl_handle; +}; + +struct ecc_test_ctx { + void *priv; + void *priv1; // openssl key handle used in hpre sign and openssl verf + void *req; + unsigned char *cp_share_key; + u32 cp_share_key_size; + unsigned char *cp_pub_key; + u32 cp_pub_key_size; + u32 key_size; + /* ecdsa sign*/ +#define MAX_SIGN_LEN 200 + unsigned char cp_sign[MAX_SIGN_LEN]; +#define MAX_ENC_LEN 8192 + unsigned char cp_enc[MAX_ENC_LEN]; + size_t cp_sign_size; + size_t cp_enc_size; + __u8 is_x25519_x448; + struct ecc_test_ctx_setup setup; +}; + +struct ecdh_sw_opdata { + EC_POINT *except_pub_key; + unsigned char *pub_key; + u32 pub_key_size; + unsigned char *share_key; + u32 share_key_size; + + /* ecdsa sign / verf */ + unsigned char *except_e; + u32 except_e_size; + BIGNUM *except_kinv; + BIGNUM *except_rp; + unsigned char *sign; // sign out or verf in + u32 sign_size; + +}; + +static char *ecc_op_str[ECC_TEST_ITEM_MAX] = { + "invalid_op", + "xdh sw gen", + "xdh sw compute", + "xdh hw gen", + "xdh hw compute", + "ecdsa sw sign", + "ecdsa sw verf", + "ecdsa hw sign", + "ecdsa hw verf", + "sm2 sw sign", + "sm2 sw verf", + "sm2 hw sign", + "sm2 hw verf", + "sm2 sw enc", + "sm2 sw dec", + "sm2 hw enc", + "sm2 hw dec", + "sm2 sw kg", + "sm2 hw kg", +}; + +static __thread struct hpre_rsa_test_key_in *rsa_key_in = NULL; + +void CRYPTO_free(void *ptr, const char *file, int line); + +# define OPENSSL_free(addr) CRYPTO_free(addr, __FILE__, __LINE__) + +/* OpenSSL RSA and BN APIs */ +BIGNUM *BN_new(void); +int BN_bn2bin(const BIGNUM *a, unsigned char *to); +BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret); +void BN_free(BIGNUM *a); +BIGNUM *BN_dup(const BIGNUM *a); +RSA *RSA_new(void); +void RSA_free(RSA *rsa); +int BN_set_word(BIGNUM *a, BN_ULONG w); +int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb); +void RSA_get0_key(const RSA *r, + const BIGNUM **n, const BIGNUM **e, const BIGNUM **d); +void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q); +void RSA_get0_crt_params(const RSA *r, + const BIGNUM **dmp1, const BIGNUM **dmq1, + const BIGNUM **iqmp); +int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, + BIGNUM *iqmp); +int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d); +int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q); +int RSA_public_encrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +int RSA_private_decrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +DH *DH_new(void); +void DH_free(DH *r); +int DH_generate_parameters_ex(DH *dh, int prime_len, int generator, + BN_GENCB *cb); +void DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, + const BIGNUM **g); +int DH_generate_key(DH *dh); +void DH_get0_key(const DH *dh, const BIGNUM **pub_key, + const BIGNUM **priv_key); +int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g); +int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key); +int DH_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh); +void *_hpre_sys_test_thread(void *data); + +EC_KEY *EC_KEY_new(void); +int EC_KEY_set_group(EC_KEY *key, EC_GROUP *group); +void EC_KEY_free(EC_KEY *key); +EC_KEY *EC_KEY_new_by_curve_name(int nid); +int EC_KEY_generate_key(EC_KEY *key); +int ERR_load_CRYPTO_strings(void); +int ERR_load_SSL_strings(void); +EC_GROUP *EC_GROUP_new_by_curve_name(int nid); +int ECDH_compute_key(void *out, size_t outlen, EC_POINT *pub_key, + EC_KEY *ecdh, + void *(*KDF) (void *in, size_t inlen, + void *out, size_t *outlen)); +EC_POINT *EC_GROUP_get0_generator(EC_GROUP *group); +int DHparams_print_fp(FILE *fp, DH *x); +int EC_KEY_set_private_key(EC_KEY *key, BIGNUM *priv_key); +EC_POINT *EC_POINT_bn2point(EC_GROUP *, BIGNUM *, + EC_POINT *, void *); +EC_POINT *EC_POINT_dup(EC_POINT *a, EC_GROUP *group); +EC_POINT *EC_KEY_get0_public_key(EC_KEY *key); +BIGNUM *EC_KEY_get0_private_key(EC_KEY *key); +int ECParameters_print_fp(FILE *fp, EC_KEY *x); +int EC_KEY_print_fp(FILE *fp, EC_KEY *x, int off); +int RSA_print_fp(FILE *fp, RSA *x, int off); +void EC_POINT_free(EC_POINT *point); +void EC_GROUP_free(EC_GROUP *group); +size_t EC_POINT_point2buf(EC_GROUP *group, EC_POINT *point, + __u32 form, + char **pbuf, void *ctx); +int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, + const EC_POINT *p, + BIGNUM *x, + BIGNUM *y, + void *ctx); +int ECDSA_sign(int type, const unsigned char *dgst, int dgstlen, + unsigned char *sig, unsigned int *siglen, EC_KEY *eckey); +int ECDSA_verify(int type, const unsigned char *dgst, int dgstlen, + const unsigned char *sig, int siglen, EC_KEY *eckey); +int RAND_priv_bytes(unsigned char *buf, int num); +int ECDSA_sign_ex(int type, const unsigned char *dgst, int dgstlen, + unsigned char *sig, unsigned int *siglen, + const BIGNUM *kinv, const BIGNUM *rp, EC_KEY *eckey); +int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub); +int ECDSA_sign_setup(EC_KEY *eckey, void *ctx_in, BIGNUM **kinvp, + BIGNUM **rp); +int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s); +void ECDSA_SIG_free(ECDSA_SIG *sig); +ECDSA_SIG *ECDSA_SIG_new(void); +ECDSA_SIG *ECDSA_do_sign(const unsigned char *dgst, int dgst_len, + EC_KEY *eckey); +const BIGNUM *ECDSA_SIG_get0_r(const ECDSA_SIG *sig); +const BIGNUM *ECDSA_SIG_get0_s(const ECDSA_SIG *sig); +int ECDSA_do_verify(const unsigned char *dgst, int dgst_len, + const ECDSA_SIG *sig, EC_KEY *eckey); +int ECDSA_size(const EC_KEY *eckey); + +//SM2 +const EVP_MD *EVP_sm3(void); +int EVP_MD_size(const EVP_MD *md); +int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type); +int EVP_DigestFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s); +int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *d, size_t cnt); +EVP_MD_CTX *EVP_MD_CTX_new(void); +EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx); +EC_POINT *EC_POINT_new(const EC_GROUP *group); +int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, + const BIGNUM *order, const BIGNUM *cofactor); +char *BN_bn2hex(const BIGNUM *a); +int EC_POINT_set_affine_coordinates(const EC_GROUP *group, EC_POINT *p, + const BIGNUM *x, const BIGNUM *y, + BN_CTX *ctx); +const RAND_METHOD *RAND_get_rand_method(void); +unsigned char *OPENSSL_hexstr2buf(const char *str, long *len); +char *OPENSSL_buf2hexstr(const unsigned char *buffer, long len); +void RAND_set_rand_method(const RAND_METHOD *meth); +ECDSA_SIG *sm2_do_sign(const EC_KEY *key, + const EVP_MD *digest, + const uint8_t *id, + const size_t id_len, + const uint8_t *msg, size_t msg_len); +EVP_PKEY *EVP_PKEY_new(void); +int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, struct ec_key_st *key); +int EVP_PKEY_set_alias_type(EVP_PKEY *pkey, int type); +EVP_MD_CTX *EVP_MD_CTX_new(void); +EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e); +void EVP_MD_CTX_set_pkey_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pctx); +int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype, + int cmd, int p1, void *p2); +int EVP_DigestSignInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, const EVP_MD *type, + ENGINE *e, EVP_PKEY *pkey); +int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, size_t *siglen); +int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *d, size_t cnt); +int EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx); +int EVP_PKEY_sign(EVP_PKEY_CTX *ctx, + unsigned char *sig, size_t *siglen, + const unsigned char *tbs, size_t tbslen); +int EVP_DigestSign(EVP_MD_CTX *ctx, unsigned char *sigret, + size_t *siglen, const unsigned char *tbs, + size_t tbslen); +void EVP_PKEY_free(EVP_PKEY *pkey); +void EVP_MD_CTX_free(EVP_MD_CTX *ctx); +void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx); +int BN_hex2bn(BIGNUM **a, const char *str); +struct ec_key_st *EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey); +struct ec_key_st *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey); +void *EVP_PKEY_get0(EVP_PKEY *pkey); +EVP_PKEY *EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *ctx); +EVP_PKEY_CTX *EVP_MD_CTX_pkey_ctx(EVP_MD_CTX *md_ctx); +int EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret, + size_t siglen, const unsigned char *tbs, + size_t tbslen); +int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, + const EVP_MD *type, ENGINE *e, + EVP_PKEY *pkey); +int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig, + size_t siglen); +const EVP_MD *EVP_sm3(void); +const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key); +int EVP_PKEY_decrypt_init(EVP_PKEY_CTX *ctx); +int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx, + unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen); +int EVP_PKEY_encrypt_init(EVP_PKEY_CTX *ctx); +int EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx, + unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen); +int EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx); +int EVP_PKEY_verify(EVP_PKEY_CTX *ctx, + const unsigned char *sig, size_t siglen, + const unsigned char *tbs, size_t tbslen); +void ERR_print_errors_fp(FILE *fp); + +const EVP_MD *EVP_sha1(void); +const EVP_MD *EVP_sha224(void); +const EVP_MD *EVP_sha256(void); +const EVP_MD *EVP_sha384(void); +const EVP_MD *EVP_sha512(void); +const EVP_MD *EVP_md4(void); +const EVP_MD *EVP_md5(void); + +#define EVP_PKEY_CTRL_MD 1 +#define EVP_PKEY_ALG_CTRL 0x1000 +#define EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID (EVP_PKEY_ALG_CTRL + 1) +#define EVP_PKEY_CTRL_EC_PARAM_ENC (EVP_PKEY_ALG_CTRL + 2) +#define EVP_PKEY_CTRL_EC_ECDH_COFACTOR (EVP_PKEY_ALG_CTRL + 3) +#define EVP_PKEY_CTRL_EC_KDF_TYPE (EVP_PKEY_ALG_CTRL + 4) +#define EVP_PKEY_CTRL_EC_KDF_MD (EVP_PKEY_ALG_CTRL + 5) +#define EVP_PKEY_CTRL_GET_EC_KDF_MD (EVP_PKEY_ALG_CTRL + 6) +#define EVP_PKEY_CTRL_EC_KDF_OUTLEN (EVP_PKEY_ALG_CTRL + 7) +#define EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN (EVP_PKEY_ALG_CTRL + 8) +#define EVP_PKEY_CTRL_EC_KDF_UKM (EVP_PKEY_ALG_CTRL + 9) +#define EVP_PKEY_CTRL_GET_EC_KDF_UKM (EVP_PKEY_ALG_CTRL + 10) +#define EVP_PKEY_CTRL_SET1_ID (EVP_PKEY_ALG_CTRL + 11) +#define EVP_PKEY_CTRL_GET1_ID (EVP_PKEY_ALG_CTRL + 12) +#define EVP_PKEY_CTRL_GET1_ID_LEN (EVP_PKEY_ALG_CTRL + 13) +#define EVP_PKEY_CTX_set1_id(ctx, id, id_len) \ + EVP_PKEY_CTX_ctrl(ctx, -1, -1, \ + EVP_PKEY_CTRL_SET1_ID, (int)id_len, (void *)id) + +#ifndef WITH_OPENSSL_DIR +BIGNUM *BN_new(void) +{ + return NULL; +} + +int BN_bn2bin(const BIGNUM *a, unsigned char *to) +{ + return 0; +} +BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret) +{ + void *buf; + + buf = malloc(len); + if (!buf) + return NULL; + + memcpy(buf, s, len); + + return buf; +} + +void BN_free(BIGNUM *a) +{ + return; +} + +BIGNUM *BN_dup(const BIGNUM *a) +{ + return NULL; +} + +RSA *RSA_new(void) +{ + return NULL; +} + +void RSA_free(RSA *rsa) +{ + return; +} + +int BN_set_word(BIGNUM *a, BN_ULONG w) +{ + return 0; +} + +int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb) +{ + return 0; +} + +void RSA_get0_key(const RSA *r, + const BIGNUM **n, const BIGNUM **e, const BIGNUM **d) +{ + return; +} + +void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q) +{ + return; +} + +void RSA_get0_crt_params(const RSA *r, + const BIGNUM **dmp1, const BIGNUM **dmq1, + const BIGNUM **iqmp) +{ + return; +} + +int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, + BIGNUM *iqmp) +{ + return 0; +} + +int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) +{ + return 0; +} + +int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q) +{ + return 0; +} + +int RSA_public_encrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) +{ + return 0; +} + +int RSA_private_decrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) +{ + return 0; +} + +int RSA_print_fp(FILE *fp, RSA *x, int off) +{ + return 0; +} + +DH *DH_new(void) +{ + return NULL; +} + +void DH_free(DH *r) +{ + return; +} + +int DH_generate_parameters_ex(DH *dh, int prime_len, int generator, + BN_GENCB *cb) +{ + return 0; +} + +void DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, + const BIGNUM **g) +{ + return; +} + +int DH_generate_key(DH *dh) +{ + return 0; +} + +void DH_get0_key(const DH *dh, const BIGNUM **pub_key, + const BIGNUM **priv_key) +{ + return; +} + +int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g) +{ + return 0; +} + +int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key) +{ + return 0; +} + +int DH_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh) +{ + return 0; +} + +EC_KEY *EC_KEY_new(void) +{ + return NULL; +} + +int EC_KEY_set_group(EC_KEY *key, EC_GROUP *group) +{ + return 0; +} + +void EC_KEY_free(EC_KEY *key) +{ + return; +} + +EC_KEY *EC_KEY_new_by_curve_name(int nid) +{ + return NULL; +} + +int EC_KEY_generate_key(EC_KEY *key) +{ + return 0; +} + +int ERR_load_CRYPTO_strings(void) +{ + return 0; +} + +int ERR_load_SSL_strings(void) +{ + return 0; +} + +EC_GROUP *EC_GROUP_new_by_curve_name(int nid) +{ + return NULL; +} + +int ECDH_compute_key(void *out, size_t outlen, EC_POINT *pub_key, + EC_KEY *ecdh, + void *(*KDF) (void *in, size_t inlen, + void *out, size_t *outlen)) +{ + return 0; +} + +EC_POINT *EC_GROUP_get0_generator(EC_GROUP *group) +{ + return NULL; +} + +int DHparams_print_fp(FILE *fp, DH *x) +{ + return 0; +} + +int EC_KEY_set_private_key(EC_KEY *key, BIGNUM *priv_key) +{ + return 0; +} + +EC_POINT *EC_POINT_bn2point(EC_GROUP *group, BIGNUM *bn, + EC_POINT *point, void *ff) +{ + return NULL; +} + +EC_POINT *EC_POINT_dup(EC_POINT *a, EC_GROUP *group) +{ + return NULL; +} + +EC_POINT *EC_KEY_get0_public_key(EC_KEY *key) +{ + return NULL; +} + +BIGNUM *EC_KEY_get0_private_key(EC_KEY *key) +{ + return NULL; +} + +int ECParameters_print_fp(FILE *fp, EC_KEY *x) +{ + return 0; +} + +int EC_KEY_print_fp(FILE *fp, EC_KEY *x, int off) +{ + return 0; +} + +void EC_POINT_free(EC_POINT *point) +{ + return; +} + +void EC_GROUP_free(EC_GROUP *group) +{ + return; +} + +size_t EC_POINT_point2buf(EC_GROUP *group, EC_POINT *point, + __u32 form, + char **pbuf, void *ctx) +{ + return 0; +} + +int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, + const EC_POINT *p, + BIGNUM *x, + BIGNUM *y, + void *ctx) +{ + return 0; +} + +int ECDSA_sign(int type, const unsigned char *dgst, int dgstlen, + unsigned char *sig, unsigned int *siglen, EC_KEY *eckey) +{ + return 0; +} + +int ECDSA_verify(int type, const unsigned char *dgst, int dgstlen, + const unsigned char *sig, int siglen, EC_KEY *eckey) +{ + return 0; +} + +int RAND_priv_bytes(unsigned char *buf, int num) +{ + return 0; +} + +int ECDSA_sign_ex(int type, const unsigned char *dgst, int dgstlen, + unsigned char *sig, unsigned int *siglen, + const BIGNUM *kinv, const BIGNUM *rp, EC_KEY *eckey) +{ + return 0; +} + +int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub) +{ + return 0; +} + +int ECDSA_sign_setup(EC_KEY *eckey, void *ctx_in, BIGNUM **kinvp, + BIGNUM **rp) +{ + return 0; +} + +int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s) +{ + return 0; +} + +void ECDSA_SIG_free(ECDSA_SIG *sig) +{ + return; +} + +ECDSA_SIG *ECDSA_SIG_new(void) +{ + return NULL; +} + +ECDSA_SIG *ECDSA_do_sign(const unsigned char *dgst, int dgst_len, + EC_KEY *eckey) +{ + return NULL; +} + +const BIGNUM *ECDSA_SIG_get0_r(const ECDSA_SIG *sig) +{ + return NULL; +} + +const BIGNUM *ECDSA_SIG_get0_s(const ECDSA_SIG *sig) +{ + return NULL; +} + +int ECDSA_do_verify(const unsigned char *dgst, int dgst_len, + const ECDSA_SIG *sig, EC_KEY *eckey) +{ + return 0; +} + +int ECDSA_size(const EC_KEY *eckey) +{ + return 0; +} + +EVP_PKEY_CTX *EVP_MD_CTX_pkey_ctx(EVP_MD_CTX *ctx) +{ + return NULL; +} + +EVP_PKEY *EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *ctx) +{ + return NULL; +} + +void *EVP_PKEY_get0(EVP_PKEY *pkey) +{ + return NULL; +} + +void EVP_PKEY_free(EVP_PKEY *pkey) +{ + return; +} + +void EVP_PKEY_CTX_free(EVP_PKEY_CTX *pctx) +{ + return; + +} + +void EVP_MD_CTX_free(EVP_MD_CTX *md_ctx) +{ + return; +} + +int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype, + int cmd, int p1, void *p2) +{ + return 0; +} + +int EVP_DigestSignInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,const EVP_MD *type, + ENGINE *imp, EVP_PKEY *pkey) +{ + return 0; +} + +int EVP_DigestSign(EVP_MD_CTX *ctx, unsigned char *sigret, size_t *siglen, + const unsigned char *tbs, size_t tbs_len) +{ + return 0; +} + +int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, + const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey) +{ + return 0; +} + +int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sigbuf, + size_t siglen) +{ + return 0; +} + +int EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx) +{ + return 0; +} + +int EVP_PKEY_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig, + size_t siglen, const unsigned char *tbs, size_t tbslen) +{ + return 0; +} + +int EVP_PKEY_encrypt_init(EVP_PKEY_CTX *ctx) +{ + return 0; +} + +int EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen) +{ + return 0; +} + +int EVP_PKEY_decrypt_init(EVP_PKEY_CTX *ctx) +{ + return 0; +} + +int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, size_t *siglen) +{ + return 0; +} + +int EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx) +{ + return 0; +} + +int EVP_PKEY_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, + const unsigned char *tbs, size_t tbslen) +{ + return 0; +} + +int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen) +{ + return 0; +} + +const EVP_MD *EVP_sha1(void) +{ + return NULL; +} + +const EVP_MD *EVP_sha224(void) +{ + return NULL; +} + +const EVP_MD *EVP_sha256(void) +{ + return NULL; +} + +const EVP_MD *EVP_sha384(void) +{ + return NULL; +} + +const EVP_MD *EVP_sha512(void) +{ + return NULL; +} + +const EVP_MD *EVP_sm3(void) +{ + return NULL; +} + +const EVP_MD *EVP_md4(void) +{ + return NULL; +} + +const EVP_MD *EVP_md5(void) +{ + return NULL; +} + +EVP_MD_CTX *EVP_MD_CTX_new(void) +{ + return NULL; +} + +int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type) +{ + return 0; +} + +int EVP_DigestFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s) +{ + return 0; +} + +int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *d, size_t cnt) +{ + return 0; +} + +unsigned char *OPENSSL_hexstr2buf(const char *str, long *len) +{ + return NULL; +} + +char *OPENSSL_buf2hexstr(const unsigned char *buffer, long len) +{ + return NULL; +} + +void RAND_set_rand_method(const RAND_METHOD *meth) +{} + +int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, struct ec_key_st *key) +{ + return 0; +} + +int EVP_PKEY_set_alias_type(EVP_PKEY *pkey, int type) +{ + return 0; +} + +EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e) +{ + return NULL; +} + +void EVP_MD_CTX_set_pkey_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pctx) +{} + +void CRYPTO_free(void *ptr, const char *file, int line) +{} + +const RAND_METHOD *RAND_get_rand_method(void) +{ + return NULL; +} + +EVP_PKEY *EVP_PKEY_new(void) +{ + return NULL; +} +#endif + +#define EVP_DigestSignUpdate(a, b, c) EVP_DigestUpdate(a, b, c) +#define EVP_DigestVerifyUpdate(a, b, c) EVP_DigestUpdate(a, b, c) + +static RAND_METHOD fake_rand; +static const RAND_METHOD *saved_rand; +static uint8_t *fake_rand_bytes = NULL; +static size_t fake_rand_bytes_offset = 0; +static size_t fake_rand_size = 0; +static int get_faked_bytes(__u8 *buf, int num) +{ + int i; + + if (fake_rand_bytes == NULL) + return saved_rand->bytes(buf, num); + + for (i = 0; i != num; ++i) + buf[i] = fake_rand_bytes[fake_rand_bytes_offset + i]; + + fake_rand_bytes_offset += num; + + return 1; +} + +static int start_fake_rand(const char *hex_bytes) +{ + /* save old rand method */ + if (!(saved_rand = RAND_get_rand_method())) + return 0; + + fake_rand = *saved_rand; + /* use own random function */ + fake_rand.bytes = get_faked_bytes; + + fake_rand_bytes = OPENSSL_hexstr2buf(hex_bytes, NULL); + fake_rand_bytes_offset = 0; + fake_rand_size = strlen(hex_bytes) / 2; + + /* set new RAND_METHOD */ + RAND_set_rand_method(&fake_rand); + + return 1; +} + +static void print_data(void *ptr, int size, const char *name) +{ + __u32 i = 0; + __u8* p = ptr; + + printf("\n%s:start_addr=%p, size %d\n", name, ptr, size); + for (i = 1; i <= size; i++) { + printf("0x%02x ", p[i - 1]); + if (i % 16 == 0) + printf("\n"); + } + printf("\n"); +} + +static int crypto_bin_to_hpre_bin(char *dst, const char *src, + int b_size, int d_size) +{ + int i = d_size - 1; + char *buff = NULL; + char *src_tmp; + int j = 0; + + if (!dst || !src || b_size <= 0 || d_size <= 0) { + WD_ERR("crypto bin to hpre bin params err!\n"); + return -WD_EINVAL; + } + + if (b_size < d_size) { + WD_ERR("crypto bin to hpre bin param data is too long!\n"); + return -WD_EINVAL; + } + + if (b_size == d_size) + return WD_SUCCESS; + + if (dst == src) { + buff = malloc(d_size); + if (!buff) + return -WD_ENOMEM; + memcpy(buff, src, d_size); + src_tmp = buff; + } else { + src_tmp = (void *)src; + } + + for (j = b_size - 1; j >= 0; j--, i--) { + if (i >= 0) + dst[j] = src_tmp[i]; + else + dst[j] = 0; + } + + if (buff) + free(buff); + + return WD_SUCCESS; +} + +static __u8 is_async_test(__u32 opType) +{ + if (opType == RSA_KEY_GEN || opType == RSA_PUB_EN || opType == RSA_PRV_DE || + opType == DH_GEN || opType == DH_COMPUTE || + opType == ECDSA_SIGN || opType == ECDSA_VERF || + opType == SM2_SIGN || opType == SM2_VERF || + opType == SM2_ENC || opType == SM2_DEC || opType == SM2_KG || + opType == ECDH_GEN || opType == ECDH_COMPUTE || + opType == X25519_GEN || opType == X25519_COMPUTE || + opType == X448_GEN || opType == X448_COMPUTE) + return false; + + return true; +} + +static void evp_sign_to_hpre_bin(char *evp, size_t *evp_size, __u32 ksz) +{ + __u32 r_sz = evp[3]; + __u32 s_sz = evp[4 + r_sz + 1]; + char *r_data = evp + 4; + char *s_data = evp + 4 + r_sz + 2; + char tmp[MAX_SIGN_LEN] = {0}; + + if (r_sz >= ksz) + memcpy(tmp, r_data + r_sz - ksz, ksz); + else if (r_sz < ksz) + memcpy(tmp + ksz - r_sz, r_data, r_sz); + + if (s_sz >= ksz) + memcpy(tmp + ksz, s_data + s_sz - ksz, ksz); + else if (s_sz < ksz) + memcpy(tmp + ksz + ksz - s_sz, s_data, s_sz); + + memset(evp, 0, *evp_size); + memcpy(evp, tmp, 2 * ksz); + *evp_size = 2 * ksz; +} + +static int hpre_bin_sign_to_evp(char *evp, char *bin, __u32 ksz) +{ + char tmp[MAX_SIGN_LEN] = {0}; + char head[2] = {0x30, 0x44}; + char r_head[3] = {0x02, 0x20}; + char s_head[3] = {0x02, 0x20}; + __u8 head_bytes = 2; + __u8 r_head_bytes = 2; + __u8 s_head_bytes = 2; + __u32 total_len = 0x46; + __u8 r_size = ksz; + __u8 s_size = ksz; + __u8 val; + int i; + + i = 0; + val = bin[i]; + while (!val && i++ < ksz - 1) + val = bin[i]; + r_size -= i; + total_len -= i; + head[1] -= i; + r_head[1] -= i; + if (bin[i] & 0x80) { + r_head_bytes = 3; + total_len += 1; + head[1]++; + r_head[1]++; + } + + i = 0; + val = bin[ksz + i]; + while (!val && i++ < ksz - 1) + val = bin[ksz + i]; + s_size -= i; + total_len -= i; + head[1] -= i; + s_head[1] -= i; + if (bin[ksz + i] & 0x80) { + s_head_bytes = 3; + total_len += 1; + head[1]++; + s_head[1]++; + } + + memcpy(tmp, head, head_bytes); + memcpy(tmp + head_bytes, r_head, r_head_bytes); + memcpy(tmp + head_bytes + r_head_bytes, bin + ksz - r_size, r_size); + memcpy(tmp + head_bytes + r_head_bytes + r_size, s_head, s_head_bytes); + memcpy(tmp + head_bytes + r_head_bytes + r_size + s_head_bytes, bin + 2 * ksz - s_size, s_size); + memcpy(evp, tmp, total_len); + + return total_len; +} + +static int sm2_enc_in_bin_to_evp(char *evp, char *bin, __u32 m_len, __u32 ksz, __u32 c3_sz) + +{ + char *tmp; + char *c1 = bin; + char *c2 = bin + ksz * 2; + char *c3 = c2 + m_len; + __u32 total_len; + char head[4] = {0x30, 0x00}; + char c1x_head[3] = {0x02, 0x20}; + char c1y_head[3] = {0x02, 0x20, 0x00}; + char c3_head[3] = {0x04, 0x20}; + char c2_head[4] = {0x04, 0x00}; + __u8 head_bytes = 2; + __u8 c1x_head_bytes = 2; + __u8 c1y_head_bytes = 2; + __u8 c3_head_bytes = 2; + __u8 c2_head_bytes = 2; + __u8 c1x_size = ksz; + __u8 c1y_size = ksz; + __u8 c3_size = c3_sz; + __u8 val; + int i; + + tmp = malloc(MAX_ENC_LEN); + if (!tmp) { + HPRE_TST_PRT("%s: malloc fail\n", __func__); + return 0; + } + + if (m_len > 127) { + c2_head_bytes = 4; + c2_head[1] = 0x82; + c2_head[2] = m_len >> 8; + c2_head[3] = m_len & 0xff; + } else { + c2_head[1] = m_len; + } + + c3_head[1] = c3_sz; + total_len = 64 + c3_sz + head_bytes + c1x_head_bytes + c1y_head_bytes + + c3_head_bytes + c2_head_bytes + m_len; + + i = 0; + val = bin[i]; + while (!val && i++ < ksz - 1) { + val = bin[i]; + } + + c1x_size -= i; + total_len -= i; + c1x_head[1] -= i; + if (bin[i] & 0x80) { + c1x_head_bytes = 3; + total_len += 1; + c1x_head[1]++; + } + + i = 0; + val = bin[i + ksz]; + while (!val && i++ < ksz - 1) { + val = bin[i + ksz]; + } + + c1y_size -= i; + total_len -= i; + c1y_head[1] -= i; + if (bin[i + ksz] & 0x80) { + c1y_head_bytes = 3; + total_len += 1; + c1y_head[1]++; + } + + if (total_len >= 130) { + head_bytes = 4; + total_len += 2; + head[1] = 0x82; + head[2] = (total_len - 4) >> 8; + head[3] = (total_len - 4) & 0xff; + } else { + head[1] = (total_len - 2) & 0xff; + } + + memcpy(tmp, head, head_bytes); // head + memcpy(tmp + head_bytes, c1x_head, c1x_head_bytes); // c1 x head + memcpy(tmp + head_bytes + c1x_head_bytes, bin + ksz - c1x_size, c1x_size); // c1 x + memcpy(tmp + head_bytes + c1x_head_bytes + c1x_size, c1y_head, c1y_head_bytes); //c1 y head + memcpy(tmp + head_bytes + c1x_head_bytes + c1x_size + c1y_head_bytes, c1 + 2 * ksz - c1y_size, c1y_size); // c1 y + memcpy(tmp + head_bytes + c1x_head_bytes + c1x_size + c1y_head_bytes + c1y_size, c3_head, c3_head_bytes); //c3 head + memcpy(tmp + head_bytes + c1x_head_bytes + c1x_size + c1y_head_bytes + c1y_size + c3_head_bytes, c3, c3_size); //c3 head + memcpy(tmp + head_bytes + c1x_head_bytes + c1x_size + c1y_head_bytes + c1y_size + c3_head_bytes + c3_size, c2_head, c2_head_bytes); //c2 head + memcpy(tmp + head_bytes + c1x_head_bytes + c1x_size + c1y_head_bytes + c1y_size + c3_head_bytes + c3_size + c2_head_bytes, c2, m_len); //c2 + memcpy(evp, tmp, total_len); + //print_data(evp, total_len, "evp"); + + free(tmp); + return total_len; +} + +__u32 get_big_endian_value(char *buf, __u32 size) +{ + __u32 ret = 0; + char tmp[4] = {0}; + + if (size == 1) { + ret = buf[0]; + } else if (size == 2) { + tmp[0] = buf[1]; + tmp[1] = buf[0]; + ret = *(unsigned short *)tmp; + } + + return ret; + } + +static int evp_to_wd_crypto(char *evp, size_t *evp_size, __u32 ksz, __u8 op_type) +{ + __u32 total_len = 0; + __u32 l_sz = 0; + __u8 *data; + __u32 d_sz = 0; + __u32 cur_len = 0; + __u32 out_len = 0; + __u32 i = 0; + char *buf; + char *buf_backup; + + buf = malloc(*evp_size + 64); /* may crypto bin len > evp_size */ + if (!buf) { + HPRE_TST_PRT("%s: malloc fail\n", __func__); + return -1; + } + + memset(buf, 0, *evp_size); + buf_backup = buf; + cur_len += 1; + if (evp[cur_len] & 0x80) { + l_sz = evp[cur_len] & 0x7f; + cur_len += 1; + } else { + l_sz = 1; + } + + if (l_sz == 1) + total_len = evp[cur_len]; + else if (l_sz == 2) + total_len = get_big_endian_value(&evp[cur_len], 2); + cur_len += l_sz; + + while (cur_len < *evp_size) { + if (evp[cur_len] == 0x2) { + cur_len += 1; + l_sz = 1; + } else if (evp[cur_len] == 0x4) { + cur_len += 1; + if (evp[cur_len] & 0x80) { + l_sz = evp[cur_len] & 0x7f; + cur_len += 1; + } else { + l_sz = 1; + } + } + + if (l_sz == 1) + d_sz = evp[cur_len]; + else if (l_sz == 2) + d_sz = get_big_endian_value(&evp[cur_len], 2); + cur_len += l_sz; + + data = (void *)&evp[cur_len]; + if (!data[0] && i < 2) { //c3 c2 no need + cur_len += 1; + d_sz -= 1; + } + + if (op_type == SM2_HW_ENC && cur_len + d_sz >= *evp_size) { + memcpy(buf, &evp[cur_len], d_sz); + buf += d_sz; + cur_len += d_sz; + out_len += d_sz; + } else if (op_type == SM2_HW_ENC && i == 2) { + memcpy(buf, &evp[cur_len], d_sz); + buf += d_sz; + cur_len += d_sz; + out_len += d_sz; + } else { + memcpy(buf + ksz - d_sz, &evp[cur_len], d_sz); + buf += ksz; + cur_len += ksz; + out_len += ksz; + } + i++; + } + + memcpy(evp, buf_backup, out_len); + *evp_size = out_len; + free(buf_backup); + + return total_len; +} + +static handle_t hpre_sched_init(handle_t h_sched_ctx, void *sched_param) +{ + return (handle_t)0; +} + +static __u32 hpre_pick_next_ctx(handle_t sched_ctx, + void *sched_key, const int sched_mode) +{ + static int last_ctx = 0; + + if (!strncmp(g_config.trd_mode, "async", 5)) + return 0; + + pthread_spin_lock(&g_lock); + if (++last_ctx == g_ctx_cfg.ctx_num) + last_ctx = 0; + pthread_spin_unlock(&g_lock); + + return last_ctx; +} + +int rsa_poll_policy(handle_t h_sched_ctx, __u32 expect, __u32 *count) +{ + int ret; + struct wd_ctx *ctxs; + int i; + + while (1) { + for (i = 0; i < g_ctx_cfg.ctx_num; i++) { + ctxs = &g_ctx_cfg.ctxs[i]; + if (ctxs->ctx_mode == CTX_MODE_ASYNC) { + ret = wd_rsa_poll_ctx(i, 1, count); + if (ret != -EAGAIN && ret < 0) { + HPRE_TST_PRT("fail poll ctx %d!\n", i); + return ret; + } + } + } + + break; + } + + return 0; +} + +static int dh_poll_policy(handle_t h_sched_ctx, __u32 expect, __u32 *count) +{ + int ret; + struct wd_ctx *ctxs; + int i; + + while (1) { + for (i = 0; i < g_ctx_cfg.ctx_num; i++) { + ctxs = &g_ctx_cfg.ctxs[i]; + if (ctxs->ctx_mode == CTX_MODE_ASYNC) { + ret = wd_dh_poll_ctx(i, 1, count); + if (ret != -EAGAIN && ret < 0) { + HPRE_TST_PRT("fail poll ctx %d!\n", i); + return ret; + } + } + } + break; + } + + return 0; +} + +static int ecc_poll_policy(handle_t h_sched_ctx, __u32 expect, __u32 *count) +{ + int ret; + struct wd_ctx *ctxs; + int i; + + while (1) { + for (i = 0; i < g_ctx_cfg.ctx_num; i++) { + ctxs = &g_ctx_cfg.ctxs[i]; + if (ctxs->ctx_mode == CTX_MODE_ASYNC) { + ret = wd_ecc_poll_ctx(i, 1, count); + if (ret != -EAGAIN && ret < 0) { + HPRE_TST_PRT("fail poll ctx %d!\n", i); + return ret; + } + } + } + break; + } + + return 0; +} + +static __u32 get_alg_op_type(enum alg_op_type op_type) +{ + __u32 value = 0; + + switch (op_type) { + case RSA_KEY_GEN: + case RSA_ASYNC_GEN: + value = WD_RSA_GENKEY; + break; + case RSA_PUB_EN: + case RSA_ASYNC_EN: + value = WD_RSA_VERIFY; + break; + case RSA_PRV_DE: + case RSA_ASYNC_DE: + value = WD_RSA_SIGN; + break; + default: + break; + } + + return value; +} + +static struct uacce_dev_list *get_uacce_dev_by_alg(struct uacce_dev_list *list, + char *alg) +{ + while (list) { + if (!strncmp(alg, list->dev->char_dev_path, strlen(alg))) + break; + else + list = list->next; + } + + return list; + +} + +static int env_init(__u32 op_type) +{ + if (op_type > HPRE_ALG_INVLD_TYPE && op_type < MAX_RSA_ASYNC_TYPE) + return wd_rsa_env_init(NULL); + else if (op_type > MAX_RSA_ASYNC_TYPE && op_type < MAX_DH_TYPE) + return wd_dh_env_init(NULL); + else if (op_type > MAX_DH_TYPE && op_type < MAX_ECDH_TYPE) + return wd_ecc_env_init(NULL); + else if (op_type > MAX_ECDH_TYPE && op_type < MAX_ECDSA_TYPE) + return wd_ecc_env_init(NULL); + else if (op_type >= SM2_SIGN && op_type <= SM2_ASYNC_KG) + return wd_ecc_env_init(NULL); + else { + HPRE_TST_PRT("op_type = %u error\n", op_type); + return -ENODEV; + } +} + +static int init_hpre_global_config(__u32 op_type) +{ + struct uacce_dev_list *list = NULL; + struct uacce_dev_list *uacce_node; + struct wd_ctx *ctx_attr; + struct wd_sched sched; + int ctx_num = g_config.trd_num; + int ret = 0; + int j; + + if (g_config.use_env) + return env_init(op_type); + +#ifdef DEBUG + HPRE_TST_PRT("request ctx[%d] from %s!\n", ctx_num, g_config.dev_path); +#endif + + if (op_type > HPRE_ALG_INVLD_TYPE && op_type < MAX_RSA_ASYNC_TYPE) + list = wd_get_accel_list("rsa"); + else if (op_type > MAX_RSA_ASYNC_TYPE && op_type < MAX_DH_TYPE) + list = wd_get_accel_list("dh"); + else if (op_type > MAX_DH_TYPE && op_type < MAX_ECDH_TYPE) + list = wd_get_accel_list("ecdh"); + else if (op_type > MAX_ECDH_TYPE && op_type < MAX_ECDSA_TYPE) + list = wd_get_accel_list("ecdsa"); + else if (op_type >= SM2_SIGN && op_type <= SM2_ASYNC_KG) + list = wd_get_accel_list("sm2"); + else + HPRE_TST_PRT("op_type = %u error\n", op_type); + if (!list) + return -ENODEV; + + uacce_node = get_uacce_dev_by_alg(list, g_config.dev_path); + if (!uacce_node) { + HPRE_TST_PRT("dev_path %s error\n", g_config.dev_path); + return -ENODEV; + } + + ctx_attr = malloc(ctx_num * sizeof(struct wd_ctx)); + if (!ctx_attr) { + HPRE_TST_PRT("malloc ctx_attr memory fail!\n"); + return -ENOMEM; + } + memset(ctx_attr, 0, ctx_num * sizeof(struct wd_ctx)); + + for (j = 0; j < ctx_num; j++) { + ctx_attr[j].ctx = wd_request_ctx(uacce_node->dev); + if (!ctx_attr[j].ctx) { + HPRE_TST_PRT("failed to request ctx!\n"); + return -1; + } + ctx_attr[j].ctx_mode = is_async_test(op_type); + ctx_attr[j].op_type = get_alg_op_type(op_type); + } + + g_ctx_cfg.ctx_num = ctx_num; + g_ctx_cfg.ctxs = ctx_attr; + sched.name = "hpre-sched-0"; + sched.pick_next_ctx = hpre_pick_next_ctx; + sched.sched_init = hpre_sched_init; + if (op_type > HPRE_ALG_INVLD_TYPE && op_type < MAX_RSA_ASYNC_TYPE) { + sched.poll_policy = rsa_poll_policy; + ret = wd_rsa_init(&g_ctx_cfg, &sched); + } else if (op_type > MAX_RSA_ASYNC_TYPE && op_type < MAX_DH_TYPE) { + sched.poll_policy = dh_poll_policy; + ret = wd_dh_init(&g_ctx_cfg, &sched); + } else { + sched.poll_policy = ecc_poll_policy; + ret = wd_ecc_init(&g_ctx_cfg, &sched); + } + + if (ret) { + HPRE_TST_PRT("failed to init alg, ret %d!\n", ret); + return -1; + } + + wd_free_list_accels(list); + + return ret; + +} + +static void uninit_hpre_global_config(__u32 op_type) +{ + if (op_type > HPRE_ALG_INVLD_TYPE && op_type < MAX_RSA_ASYNC_TYPE) + wd_rsa_uninit(); + else if (op_type > MAX_RSA_ASYNC_TYPE && op_type < MAX_DH_TYPE) + wd_dh_uninit(); + else + wd_ecc_uninit(); +} + +static int init_opdata_param(struct wd_dh_req *req, + int key_size, enum dh_check_index step) +{ + unsigned char *ag_bin = NULL; + + memset(req, 0, sizeof(*req)); + if (step == DH_ALICE_PRIVKEY) { + ag_bin = malloc(2 * key_size); + if (!ag_bin) + return -ENOMEM; + memset(ag_bin, 0, 2 * key_size); + req->pv = ag_bin; + } + + req->x_p = malloc(2 * key_size); + if (!req->x_p) { + if (ag_bin) + free(ag_bin); + return -ENOMEM; + } + memset(req->x_p, 0, 2 * key_size); + + req->pri = malloc(2 * key_size); + if (!req->pri) { + if (ag_bin) + free(ag_bin); + free(req->x_p); + return -ENOMEM; + } + memset(req->pri, 0, 2 * key_size); + req->pri_bytes = 2 * key_size; + + return 0; +} + + +void hpre_dh_del_test_ctx(struct hpre_dh_test_ctx *test_ctx) +{ + if (!test_ctx) + return; + + if (SW_GENERATE_KEY == test_ctx->op) { + DH_free(test_ctx->priv); + } else if (SW_COMPUTE_KEY == test_ctx->op) { + struct hpre_dh_sw_opdata *req = test_ctx->req; + + free(req->except_pub_key); + free(req->share_key); + free(req); + DH_free(test_ctx->priv); + } else if (HW_GENERATE_KEY == test_ctx->op) { + struct wd_dh_req *req = test_ctx->req; + + free(req->x_p); + free(req->pri); + free(req); + free(test_ctx->cp_pub_key); + } else if (HW_COMPUTE_KEY == test_ctx->op) { + struct wd_dh_req *req = test_ctx->req; + + free(req->pv); + free(req->x_p); + free(req->pri); + free(req); + free(test_ctx->cp_share_key); + } else { + HPRE_TST_PRT("%s: no op %d\n", __func__, test_ctx->op); + } + + free(test_ctx); +} + +static struct hpre_dh_test_ctx *create_sw_gen_key_test_ctx(struct hpre_dh_test_ctx_setup setup) +{ + BIGNUM *p = NULL, *g = NULL, *x = NULL; + struct hpre_dh_test_ctx *test_ctx; + DH *dh = NULL; + + if (SW_GENERATE_KEY != setup.op_type) { + HPRE_TST_PRT("%s: err op type %d\n", __func__, setup.op_type); + return NULL; + } + + dh = DH_new(); + if (!dh) + return NULL; + + printf("dh %p\n", dh); + + test_ctx = malloc(sizeof(struct hpre_dh_test_ctx)); + if (!test_ctx) { + DH_free(dh); + return NULL; + } + + if (setup.key_from) { + p = BN_bin2bn(setup.p, setup.p_size, NULL); + g = BN_bin2bn(setup.g, setup.g_size, NULL); + x = BN_bin2bn(setup.x, setup.x_size, NULL); + DH_set0_pqg(dh, p, NULL, g); + DH_set0_key(dh, NULL, x); + } else { + if (!DH_generate_parameters_ex(dh, setup.key_bits, setup.generator, NULL)) { + HPRE_TST_PRT("DH_generate_parameters_ex fail!\n"); + DH_free(dh); + free(test_ctx); + return NULL; + } + } + + test_ctx->op = SW_GENERATE_KEY; + test_ctx->priv = dh; + test_ctx->key_size = setup.key_bits >> 3; + +//#ifdef DEBUG + DHparams_print_fp(stdout, dh); +//#endif + + return test_ctx; +} + +static struct hpre_dh_test_ctx *create_sw_compute_key_test_ctx(struct hpre_dh_test_ctx_setup setup) +{ + struct hpre_dh_sw_opdata *req; + struct hpre_dh_test_ctx *test_ctx; + DH *dh = NULL; + + if (!setup.except_pub_key || + !setup.except_pub_key_size || + setup.op_type !=SW_COMPUTE_KEY) { + HPRE_TST_PRT("%s: parm err!\n", __func__); + return NULL; + } + + dh = DH_new(); + if (!dh) + return NULL; + + req = malloc(sizeof(struct hpre_dh_sw_opdata)); + if (!req) { + DH_free(dh); + return NULL; + } + memset(req, 0, sizeof(struct hpre_dh_sw_opdata)); + + test_ctx = malloc(sizeof(struct hpre_dh_test_ctx)); + if (!test_ctx) { + DH_free(dh); + free(req); + return NULL; + } + memset(test_ctx, 0, sizeof(struct hpre_dh_test_ctx)); + + req->share_key = malloc(setup.key_bits >> 3); + if (!req->share_key) { + DH_free(dh); + free(req); + free(test_ctx); + return NULL; + } + + if (setup.key_from) { + BIGNUM *p = NULL, *g = NULL, *x = NULL; + p = BN_bin2bn(setup.p, setup.p_size, NULL); + g = BN_bin2bn(setup.g, setup.g_size, NULL); + x = BN_bin2bn(setup.x, setup.x_size, NULL); + DH_set0_pqg(dh, p, NULL, g); + DH_set0_key(dh, NULL, x); + + req->except_pub_key = BN_bin2bn(setup.except_pub_key, + setup.except_pub_key_size, NULL); + + } else { + req->except_pub_key = BN_bin2bn(setup.except_pub_key, + setup.except_pub_key_size, NULL); + + if (!DH_generate_parameters_ex(dh, setup.key_bits, setup.generator, NULL)) { + HPRE_TST_PRT("DH_generate_parameters_ex fail!\n"); + goto exit_free; + } + + if (!DH_generate_key(dh)) { + HPRE_TST_PRT("Alice DH_generate_key fail!\n"); + goto exit_free; + } + } +#ifdef DEBUG + //DHparams_print_fp(stdout, dh); +#endif + test_ctx->op = SW_COMPUTE_KEY; + test_ctx->priv = dh; + test_ctx->req = req; + test_ctx->key_size = setup.key_bits >> 3; + + return test_ctx; + +exit_free: + hpre_dh_del_test_ctx(test_ctx); + + return NULL; +} + +static struct hpre_dh_test_ctx *create_hw_gen_key_test_ctx(struct hpre_dh_test_ctx_setup setup) +{ + const BIGNUM *p = NULL, *g = NULL, *x = NULL; + const BIGNUM *pub_key = NULL; + struct wd_dh_req *req; + struct hpre_dh_test_ctx *test_ctx; + struct wd_dtb ctx_g; + int ret; + u32 key_size = setup.key_bits >> 3; + DH *dh = NULL; + + if (setup.op_type != HW_GENERATE_KEY) { + HPRE_TST_PRT("%s: parm err!\n", __func__); + return NULL; + } + + req = malloc(sizeof(struct wd_dh_req)); + if (!req) + return NULL; + memset(req, 0, sizeof(struct wd_dh_req)); + + dh = DH_new(); + if (!dh) { + free(req); + return NULL; + } + + test_ctx = malloc(sizeof(struct hpre_dh_test_ctx)); + if (!test_ctx) { + free(req); + DH_free(dh); + return NULL; + } + memset(test_ctx, 0, sizeof(struct hpre_dh_test_ctx)); + + ctx_g.data = malloc(key_size); + if (!ctx_g.data) { + free(test_ctx); + free(req); + DH_free(dh); + return NULL; + } + memset(ctx_g.data, 0, key_size); + + test_ctx->cp_pub_key = malloc(key_size); + if (!test_ctx->cp_pub_key) { + free(test_ctx); + free(req); + DH_free(dh); + free(ctx_g.data); + return NULL; + } + + ret = init_opdata_param(req, key_size, DH_ALICE_PUBKEY); + if (ret < 0) { + HPRE_TST_PRT("init_opdata_param failed\n"); + free(test_ctx); + free(req); + DH_free(dh); + free(ctx_g.data); + return NULL; + } + + if (setup.key_from) { + if (!setup.x || !setup.x_size || !setup.p || !setup.pub_key || + !setup.p_size || !setup.g || !setup.g_size || !setup.pub_key_size) { + HPRE_TST_PRT("%s: x/p/g parm err\n", __func__); + goto exit_free; + } + + memcpy(req->x_p, setup.x, setup.x_size); + memcpy(req->x_p + key_size, setup.p, setup.p_size); + memcpy(ctx_g.data, setup.g, setup.g_size); + memcpy(test_ctx->cp_pub_key, setup.pub_key, setup.pub_key_size); + req->pbytes = setup.p_size; + req->xbytes = setup.x_size; + ctx_g.dsize = setup.g_size; + ctx_g.bsize = key_size; + test_ctx->cp_pub_key_size = setup.pub_key_size; + } else { + ret = DH_generate_parameters_ex(dh, setup.key_bits, setup.generator, NULL); + if (!ret) { + HPRE_TST_PRT("DH_generate_parameters_ex failed\n"); + goto exit_free; + } + + if (!DH_generate_key(dh)) { + HPRE_TST_PRT("DH_generate_key failed\n"); + goto exit_free; + } + + DH_get0_pqg(dh, &p, NULL, &g); + DH_get0_key(dh, &pub_key, &x); + + req->pbytes = BN_bn2bin(p, req->x_p + key_size); + req->xbytes = BN_bn2bin(x, req->x_p); + ctx_g.dsize = BN_bn2bin(g, (unsigned char*)ctx_g.data); + ctx_g.bsize = key_size; + test_ctx->cp_pub_key_size = BN_bn2bin(pub_key, test_ctx->cp_pub_key); + } + +#ifdef DEBUG + print_data(ctx_g.data, ctx_g.dsize, "g"); + print_data(req->x_p, req->xbytes, "x"); + print_data(req->x_p + key_size, req->pbytes, "p"); + print_data(test_ctx->cp_pub_key, test_ctx->cp_pub_key_size, "cp_pub_key"); +#endif + + req->op_type = WD_DH_PHASE1; + test_ctx->req = req; + test_ctx->op = setup.op_type; + test_ctx->priv = (void *)setup.sess; + test_ctx->key_size = key_size; + + ret = wd_dh_set_g((handle_t)test_ctx->priv, &ctx_g); + if (ret) { + HPRE_TST_PRT("wd_dh_set_g failed\n"); + goto exit_free; + } + + + DH_free(dh); + free(ctx_g.data); + + return test_ctx; +exit_free: + DH_free(dh); + free(ctx_g.data); + hpre_dh_del_test_ctx(test_ctx); + + return NULL; +} + +static struct hpre_dh_test_ctx *create_hw_compute_key_test_ctx(struct hpre_dh_test_ctx_setup setup) +{ + const BIGNUM *p = NULL, *g = NULL, *x = NULL; + struct wd_dh_req *req; + struct hpre_dh_test_ctx *test_ctx; + int ret; + u32 key_size = setup.key_bits >> 3; + DH *dh = NULL; + DH *b = NULL; + + if (setup.op_type !=HW_COMPUTE_KEY) { + HPRE_TST_PRT("%s: parm err!\n", __func__); + return NULL; + } + + req = malloc(sizeof(struct wd_dh_req)); + if (!req) + return NULL; + memset(req, 0, sizeof(struct wd_dh_req)); + + dh = DH_new(); + if (!dh) { + free(req); + return NULL; + } + + test_ctx = malloc(sizeof(struct hpre_dh_test_ctx)); + if (!test_ctx) { + free(req); + DH_free(dh); + return NULL; + } + memset(test_ctx, 0, sizeof(struct hpre_dh_test_ctx)); + + test_ctx->cp_share_key = malloc(key_size); + if (!test_ctx->cp_share_key) { + free(test_ctx); + free(req); + DH_free(dh); + return NULL; + } + + ret = init_opdata_param(req, key_size, DH_ALICE_PRIVKEY); + if (ret < 0) { + HPRE_TST_PRT("init_opdata_param failed\n"); + free(test_ctx); + free(req); + DH_free(dh); + return NULL; + } + + if (setup.key_from) { + memcpy(req->x_p, setup.x, setup.x_size); + memcpy(req->x_p + key_size, setup.p, setup.p_size); + memcpy(req->pv, setup.except_pub_key, setup.except_pub_key_size); + memcpy(test_ctx->cp_share_key, setup.share_key, setup.share_key_size); + req->pbytes = setup.p_size; + req->xbytes = setup.x_size; + req->pvbytes = setup.except_pub_key_size; + test_ctx->cp_share_key_size = setup.share_key_size; + } else { + const BIGNUM *bp = NULL, *bg = NULL, + *bpub_key = NULL, *bpriv_key = NULL; + b = DH_new(); + + ret = DH_generate_parameters_ex(dh, setup.key_bits, setup.generator, NULL); + if (!ret) { + HPRE_TST_PRT("DH_generate_parameters_ex fail!\n"); + goto exit_free; + } + + if (!DH_generate_key(dh)) { + HPRE_TST_PRT("Alice DH_generate_key fail!\n"); + goto exit_free; + } + + DH_get0_pqg(dh, &p, NULL, &g); + DH_get0_key(dh, NULL, &x); + bp = BN_dup(p); + bg = BN_dup(g); + DH_set0_pqg(b, (BIGNUM *)bp, NULL, (BIGNUM *)bg); + if (!DH_generate_key(b)) { + HPRE_TST_PRT("a DH_generate_key fail!\n"); + ret = -1; + goto exit_free; + } + DH_get0_key(b, &bpub_key, &bpriv_key); + + test_ctx->cp_share_key_size = DH_compute_key(test_ctx->cp_share_key, bpub_key, dh); + if (!test_ctx->cp_share_key_size || test_ctx->cp_share_key_size == -1) { + HPRE_TST_PRT("DH_compute_key fail!\n"); + goto exit_free; + } + + req->pbytes = BN_bn2bin(p, req->x_p + key_size); + req->xbytes = BN_bn2bin(x, req->x_p); + req->pvbytes = setup.except_pub_key_size; + req->pvbytes = BN_bn2bin(bpub_key, req->pv); + } + + req->op_type = WD_DH_PHASE2; + test_ctx->priv = (void *)setup.sess; //init sess + test_ctx->req = req; + test_ctx->op = setup.op_type; + test_ctx->key_size = key_size; + +#ifdef DEBUG + print_data(req->pv, req->pvbytes, "pv"); + print_data(req->x_p, req->xbytes, "x"); + print_data(req->x_p + key_size, req->pbytes, "p"); + print_data(test_ctx->cp_share_key, test_ctx->cp_share_key_size, "cp_share_key"); +#endif + + DH_free(dh); + if (b) + DH_free(b); + + return test_ctx; +exit_free: + DH_free(dh); + if (b) + DH_free(b); + hpre_dh_del_test_ctx(test_ctx); + + return NULL; +} + + +struct hpre_dh_test_ctx *hpre_dh_create_test_ctx(struct hpre_dh_test_ctx_setup setup) +{ + struct hpre_dh_test_ctx *test_ctx = NULL; + + switch (setup.op_type) { + case SW_GENERATE_KEY: + { + test_ctx = create_sw_gen_key_test_ctx(setup); + } + break; + case HW_GENERATE_KEY: + { + test_ctx = create_hw_gen_key_test_ctx(setup); + } + break; + case SW_COMPUTE_KEY: + { + test_ctx = create_sw_compute_key_test_ctx(setup); + } + break; + case HW_COMPUTE_KEY: + { + test_ctx = create_hw_compute_key_test_ctx(setup); + } + break; + default: + break; + } + + return test_ctx; +} + +int dh_generate_key(void *test_ctx, void *tag) +{ + struct hpre_dh_test_ctx *t_c = test_ctx; + int ret = 0; + + if (t_c->op == SW_GENERATE_KEY) { + DH *dh = t_c->priv; + + if (!DH_generate_key(dh)) { + HPRE_TST_PRT("DH_generate_key fail!\n"); + return -1; + } + +#ifdef DEBUG + //DHparams_print_fp(stdout, dh); +#endif + + } else { + struct wd_dh_req *req = t_c->req; + handle_t sess = (handle_t)t_c->priv; +try_again: + if (tag) + ret = wd_do_dh_async(sess, req); + else + ret = wd_do_dh_sync(sess, req); + if (ret == -WD_EBUSY) { + usleep(100); + goto try_again; + } else if (ret) { + HPRE_TST_PRT("wd_do_dh fail!\n"); + return -1; + } + } + + return 0; +} + +int dh_compute_key(void *test_ctx, void *tag) +{ + struct hpre_dh_test_ctx *t_c = test_ctx; + int ret = 0; + + if (t_c->op == SW_COMPUTE_KEY) { + struct hpre_dh_sw_opdata *req = t_c->req; + DH *dh = t_c->priv; + + ret = DH_compute_key(req->share_key, req->except_pub_key, dh); + if (ret <= 0) { + HPRE_TST_PRT("DH_compute_key fail!\n"); + return -1; + } + req->share_key_size = ret; + +#ifdef DEBUG + //DHparams_print_fp(stdout, dh); + //print_data(req->share_key, ret, "openssl share key"); + +#endif + } else { + struct wd_dh_req *req = t_c->req; + handle_t sess = (uintptr_t)t_c->priv; +try_again: + if (tag) + ret = wd_do_dh_async(sess, req); + else + ret = wd_do_dh_sync(sess, req); + if (ret == -WD_EBUSY) { + usleep(100); + goto try_again; + } else if (ret) { + HPRE_TST_PRT("wd_do_dh fail!\n"); + return -1; + } +#ifdef DEBUG + //print_data(req->pri, req->pri_bytes,"hpre share key"); +#endif + } + + return 0; +} + +static bool is_exit(struct test_hpre_pthread_dt *pdata) +{ + struct timeval cur_tval; + float time_used; + + gettimeofday(&cur_tval, NULL); + time_used = (float)((cur_tval.tv_sec -pdata->start_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - pdata->start_tval.tv_usec); + + if (g_config.seconds) + return time_used >= g_config.seconds * 1000000; + else if (g_config.times) + return pdata->send_task_num >= g_config.times; + + return false; +} + +static int dh_result_check(struct hpre_dh_test_ctx *test_ctx) +{ + struct wd_dh_req *req = test_ctx->req; + unsigned char *cp_key; + u32 cp_size; + + if (test_ctx->op == HW_GENERATE_KEY) { + cp_key = test_ctx->cp_pub_key; + cp_size = test_ctx->cp_pub_key_size; + + } else { + cp_key = test_ctx->cp_share_key; + cp_size = test_ctx->cp_share_key_size; + } + + if (req->pri_bytes != cp_size || memcmp(cp_key, req->pri, cp_size)) { + HPRE_TST_PRT("dh op %d mismatch!\n", test_ctx->op); + +#ifdef DEBUG + print_data(req->pri, req->pri_bytes, "hpre out"); + print_data(cp_key, cp_size, "openssl out"); +#endif + + return -1; + } + + return 0; + +} + +static bool is_allow_print(int cnt, enum alg_op_type opType, int thread_num) +{ + int intval_index = 0; + unsigned int log_intval_adjust = 0; + int log_intval[LOG_INTVL_NUM] = {0x1, 0xff, 0x3ff, 0x7ff, 0xfff, 0x1fff}; + + if (!g_config.with_log || g_config.perf_test) + return false; + + if (g_config.soft_test) + return true; + + switch (opType) { + case RSA_ASYNC_GEN: + case RSA_ASYNC_EN: + case RSA_ASYNC_DE: + case DH_ASYNC_COMPUTE: + case DH_ASYNC_GEN: + case RSA_KEY_GEN: + { + intval_index = 0x04; + } + break; + case ECDH_ASYNC_COMPUTE: + case ECDH_ASYNC_GEN: + case ECDSA_ASYNC_SIGN: + case ECDSA_ASYNC_VERF: + case ECDH_COMPUTE: + case ECDH_GEN: + { + intval_index = 0x01; + } + break; + case DH_COMPUTE: + case DH_GEN: + { + intval_index = 0x00; + } + break; + default: + { + intval_index = 0x01; + } + break; + } + + if (!thread_num) + return false; + log_intval_adjust = log_intval[intval_index] * ((thread_num - 1) / 16 + 1); + + if (!(cnt % log_intval_adjust)) + return true; + else + return false; +} + +static void _dh_perf_cb(void *req_t) +{ + struct wd_dh_req *req = req_t; + struct dh_user_tag_info* pTag = (struct dh_user_tag_info*)req->cb_param; + struct test_hpre_pthread_dt *thread_data = pTag->thread_data; + + thread_data->recv_task_num++; + hpre_dh_del_test_ctx(pTag->test_ctx); + free(pTag); +} + +static void _dh_cb(void *req_t) +{ + struct wd_dh_req *req = req_t; + struct dh_user_tag_info* pSwData = (struct dh_user_tag_info*)req->cb_param; + struct timeval start_tval, end_tval; + int pid, threadId; + float time, speed; + int ret; + static int failTimes = 0; + struct hpre_dh_test_ctx *test_ctx = pSwData->test_ctx; + struct test_hpre_pthread_dt *thread_data = pSwData->thread_data; + + start_tval = thread_data->start_tval; + pid = pSwData->pid; + threadId = pSwData->thread_id; + thread_data->recv_task_num++; + + if (req->status != WD_SUCCESS) { + HPRE_TST_PRT("Proc-%d, %d-TD dh %dtimes fail!, status 0x%02x\n", + pid, threadId, thread_data->send_task_num, req->status); + goto err; + } + + if (g_config.check) { + ((struct wd_dh_req *)test_ctx->req)->pri_bytes = req->pri_bytes; + ret = dh_result_check(test_ctx); + if (ret) { + failTimes++; + HPRE_TST_PRT("TD-%d:dh %d result mismatching!\n", + threadId, test_ctx->op); + } + } + + gettimeofday(&end_tval, NULL); + if (is_allow_print(thread_data->send_task_num, DH_ASYNC_GEN, 1)) { + time = (end_tval.tv_sec - start_tval.tv_sec) * 1000000 + + (end_tval.tv_usec - start_tval.tv_usec); + speed = 1 / (time / thread_data->send_task_num) * 1000 * 1000; + HPRE_TST_PRT("Proc-%d, %d-TD dh %dtimes,%f us, %0.3fps, fail %dtimes(all TD)\n", + pid, threadId, thread_data->send_task_num, time, speed, failTimes); + } + +err: + if (is_allow_print(thread_data->send_task_num, DH_ASYNC_GEN, 1)) + HPRE_TST_PRT("thread %d do DH %dth time success!\n", threadId, thread_data->send_task_num); + hpre_dh_del_test_ctx(test_ctx); + if (pSwData) + free(pSwData); +} + + +int dh_init_test_ctx_setup(struct hpre_dh_test_ctx_setup *setup) +{ + __u32 key_bits = g_config.key_bits; + + if (!setup) + return -1; + + if (!strcmp(g_config.alg_mode, "g2")) + setup->generator = DH_GENERATOR_2; + else + setup->generator = DH_GENERATOR_5; + + if (g_config.perf_test) + setup->key_from = 1; //0 - Openssl 1 - Designed + else + setup->key_from = 0; //0 - Openssl 1 - Designed + + setup->key_bits = g_config.key_bits; + + if (key_bits == 768) { + setup->x = dh_xa_768; + setup->p = dh_p_768; + setup->except_pub_key = dh_except_b_pubkey_768; + setup->pub_key = dh_except_a_pubkey_768; + setup->share_key = dh_share_key_768; + setup->x_size = sizeof(dh_xa_768); + setup->p_size = sizeof(dh_p_768); + setup->except_pub_key_size = sizeof(dh_except_b_pubkey_768); + setup->pub_key_size = sizeof(dh_except_a_pubkey_768); + setup->share_key_size = sizeof(dh_share_key_768); + } else if (key_bits == 1024) { + setup->x = dh_xa_1024; + setup->p = dh_p_1024; + setup->except_pub_key = dh_except_b_pubkey_1024; + setup->pub_key = dh_except_a_pubkey_1024; + setup->share_key = dh_share_key_1024; + setup->x_size = sizeof(dh_xa_1024); + setup->p_size = sizeof(dh_p_1024); + setup->except_pub_key_size = sizeof(dh_except_b_pubkey_1024); + setup->pub_key_size = sizeof(dh_except_a_pubkey_1024); + setup->share_key_size = sizeof(dh_share_key_1024); + } else if (key_bits == 1536) { + setup->x = dh_xa_1536; + setup->p = dh_p_1536; + setup->except_pub_key = dh_except_b_pubkey_1536; + setup->pub_key = dh_except_a_pubkey_1536; + setup->share_key = dh_share_key_1536; + setup->x_size = sizeof(dh_xa_1536); + setup->p_size = sizeof(dh_p_1536); + setup->except_pub_key_size = sizeof(dh_except_b_pubkey_1536); + setup->pub_key_size = sizeof(dh_except_a_pubkey_1536); + setup->share_key_size = sizeof(dh_share_key_1536); + } else if (key_bits == 2048) { + setup->x = dh_xa_2048; + setup->p = dh_p_2048; + setup->except_pub_key = dh_except_b_pubkey_2048; + setup->pub_key = dh_except_a_pubkey_2048; + setup->share_key = dh_share_key_2048; + setup->x_size = sizeof(dh_xa_2048); + setup->p_size = sizeof(dh_p_2048); + setup->except_pub_key_size = sizeof(dh_except_b_pubkey_2048); + setup->pub_key_size = sizeof(dh_except_a_pubkey_2048); + setup->share_key_size = sizeof(dh_share_key_2048); + } else if (key_bits == 3072) { + setup->x = dh_xa_3072; + setup->p = dh_p_3072; + setup->except_pub_key = dh_except_b_pubkey_3072; + setup->pub_key = dh_except_a_pubkey_3072; + setup->share_key = dh_share_key_3072; + setup->x_size = sizeof(dh_xa_3072); + setup->p_size = sizeof(dh_p_3072); + setup->except_pub_key_size = sizeof(dh_except_b_pubkey_3072); + setup->pub_key_size = sizeof(dh_except_a_pubkey_3072); + setup->share_key_size = sizeof(dh_share_key_3072); + } else if (key_bits == 4096) { + setup->x = dh_xa_4096; + setup->p = dh_p_4096; + setup->except_pub_key = dh_except_b_pubkey_4096; + setup->pub_key = dh_except_a_pubkey_4096; + setup->share_key = dh_share_key_4096; + setup->x_size = sizeof(dh_xa_4096); + setup->p_size = sizeof(dh_p_4096); + setup->except_pub_key_size = sizeof(dh_except_b_pubkey_4096); + setup->pub_key_size = sizeof(dh_except_a_pubkey_4096); + setup->share_key_size = sizeof(dh_share_key_4096); + } else { + HPRE_TST_PRT("not find this keybits %d\n", key_bits); + return -1; + } + + if (!strcmp(g_config.alg_mode, "g2")) { + setup->g = dh_g_2; + } else { + setup->g = dh_g_5; + } + setup->g_size = 1; + + return 0; +} + +static void *_hpre_dh_sys_test_thread(void *data) +{ + struct test_hpre_pthread_dt *pdata = data; + struct dh_user_tag_info *pTag = NULL; + struct hpre_dh_test_ctx *test_ctx; + struct hpre_dh_test_ctx_setup setup; + struct timeval cur_tval; + enum alg_op_type opType; + float time_used, speed = 0.0; + int thread_num; + cpu_set_t mask; + int pid = getpid(); + int thread_id = (int)syscall(__NR_gettid); + int ret, cpuid; + handle_t sess = 0llu; + struct wd_dh_sess_setup dh_setup; + struct wd_dh_req *req; + + CPU_ZERO(&mask); + cpuid = pdata->cpu_id; + opType = pdata->op_type; + thread_num = pdata->thread_num; + + if (g_config.perf_test && (!g_config.times && !g_config.seconds)) { + HPRE_TST_PRT("g_config.times or g_config.seconds err\n"); + return NULL; + } + + CPU_SET(cpuid, &mask); + if (cpuid) { + ret = pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask); + if (ret < 0) { + HPRE_TST_PRT("Proc-%d, thrd-%d:set affinity fail!\n", + pid, thread_id); + return NULL; + } + HPRE_TST_PRT("Proc-%d, thrd-%d bind to cpu-%d!\n", + pid, thread_id, cpuid); + } + + if (!g_config.soft_test) { + memset(&dh_setup, 0, sizeof(dh_setup)); + dh_setup.key_bits = g_config.key_bits; + if (!strcmp(g_config.alg_mode, "g2")) + dh_setup.is_g2 = true; + else + dh_setup.is_g2 = false; + + sess = wd_dh_alloc_sess(&dh_setup); + if (!sess) { + HPRE_TST_PRT("wd_dh_alloc_ctx failed\n"); + return NULL; + } + } + + if (dh_init_test_ctx_setup(&setup)) { + wd_dh_free_sess(sess); + return NULL; + } + + setup.sess = sess; + + if (opType == DH_ASYNC_GEN || opType == DH_GEN) + setup.op_type = (g_config.soft_test) ? SW_GENERATE_KEY: HW_GENERATE_KEY; + else + setup.op_type = (g_config.soft_test) ? SW_COMPUTE_KEY: HW_COMPUTE_KEY; + +new_test_again: + test_ctx = hpre_dh_create_test_ctx(setup); + if (!test_ctx) { + HPRE_TST_PRT("hpre_dh_create_test_ctx failed\n"); + return NULL; + } + + req = test_ctx->req; + do { + if (opType == DH_ASYNC_GEN || + opType == DH_ASYNC_COMPUTE) { + + pTag = malloc(sizeof(struct dh_user_tag_info)); + if (!pTag) { + HPRE_TST_PRT("malloc pTag fail!\n"); + goto fail_release; + } + + pTag->test_ctx = test_ctx; + pTag->thread_data = pdata; + pTag->pid = pid; + pTag->thread_id = thread_id; + if (g_config.perf_test) + req->cb = _dh_perf_cb; + else + req->cb = _dh_cb; + req->cb_param = pTag; + } + + if (opType == DH_ASYNC_GEN || opType == DH_GEN) { + if (dh_generate_key(test_ctx, pTag)) { + goto fail_release; + } + } else { + if (dh_compute_key(test_ctx, pTag)) { + goto fail_release; + } + } + + pdata->send_task_num++; + if (opType == DH_GEN ||opType == DH_COMPUTE) { + if (!g_config.perf_test && !g_config.soft_test) { + if (dh_result_check(test_ctx)) + goto fail_release; + + if (is_allow_print(pdata->send_task_num, opType, thread_num)) { + HPRE_TST_PRT("Proc-%d, %d-TD %s succ!\n", + getpid(), (int)syscall(__NR_gettid), g_config.op); + } + + hpre_dh_del_test_ctx(test_ctx); + if (is_exit(pdata)) + return 0; + goto new_test_again; + } + } else { + if (is_exit(pdata)) + break; + goto new_test_again; + } + + }while(!is_exit(pdata)); + + if (opType == DH_GEN || opType == DH_COMPUTE) + pdata->recv_task_num = pdata->send_task_num; + + if (g_config.perf_test) { + gettimeofday(&cur_tval, NULL); + time_used = (float)((cur_tval.tv_sec -pdata->start_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - pdata->start_tval.tv_usec); + + if (g_config.seconds){ + speed = pdata->recv_task_num / time_used * 1000000; + } else if (g_config.times) { + speed = pdata->recv_task_num * 1.0 * 1000 * 1000 / time_used; + } + HPRE_TST_PRT("<< Proc-%d, %d-TD: run %s %s mode %u key_bits at %0.3f ops!\n", + pid, thread_id, g_config.op, g_config.alg_mode, g_config.key_bits, speed); + pdata->perf = speed; + } + + /* wait for recv finish */ + while (pdata->send_task_num != pdata->recv_task_num) { + usleep(1000 * 1000); + if (g_config.with_log) + HPRE_TST_PRT("<< Proc-%d, %d-TD: total send %u: recv %u, wait recv finish...!\n", + pid, thread_id, pdata->send_task_num, pdata->recv_task_num); + } + +fail_release: + if (opType == DH_ASYNC_GEN || + opType == DH_ASYNC_COMPUTE) { + return NULL; + } + if (test_ctx->op == HW_COMPUTE_KEY || test_ctx->op == HW_GENERATE_KEY) + wd_dh_free_sess((uintptr_t)test_ctx->priv); + + if (opType == DH_GEN || opType == DH_COMPUTE) + hpre_dh_del_test_ctx(test_ctx); + + return NULL; +} + + +static void ecc_del_test_ctx(struct ecc_test_ctx *test_ctx) +{ + if (!test_ctx) + return; + + if (ECDH_SW_GENERATE == test_ctx->setup.op_type) { + if (test_ctx->is_x25519_x448 == 1) { + + } else { + EC_KEY_free(test_ctx->setup.openssl_handle); + } + } else if (ECDH_SW_COMPUTE == test_ctx->setup.op_type) { + struct ecdh_sw_opdata *opdata = test_ctx->req; + + if (test_ctx->is_x25519_x448 == 1) { + + } else { + free(opdata->share_key); + free(opdata); + EC_KEY_free(test_ctx->setup.openssl_handle); + } + } else if (ECDH_HW_GENERATE == test_ctx->setup.op_type) { + struct wd_ecc_req *req = test_ctx->req; + + wd_ecc_del_out(test_ctx->setup.sess, req->dst); + free(req); + free(test_ctx->cp_pub_key); + } else if (ECDH_HW_COMPUTE == test_ctx->setup.op_type) { + struct wd_ecc_req *req = test_ctx->req; + + wd_ecc_del_out(test_ctx->setup.sess, req->dst); + wd_ecc_del_in(test_ctx->setup.sess, req->src); + free(req); + free(test_ctx->cp_share_key); + } else if (ECC_SW_SIGN == test_ctx->setup.op_type) { + struct ecdh_sw_opdata *opdata = test_ctx->req; + + free(opdata->sign); + BN_free(opdata->except_kinv); + free(opdata); + EC_KEY_free(test_ctx->priv); + } else if (ECC_SW_VERF == test_ctx->setup.op_type) { + struct ecdh_sw_opdata *opdata = test_ctx->req; + + free(opdata); + EC_KEY_free(test_ctx->priv); + } else if (ECC_HW_SIGN == test_ctx->setup.op_type) { + struct wd_ecc_req *req = test_ctx->req; + + if (test_ctx->priv1) + EC_KEY_free(test_ctx->priv1); + + wd_ecc_del_out((handle_t)test_ctx->priv, req->dst); + wd_ecc_del_in((handle_t)test_ctx->priv, req->src); + free(req); + } else if (ECC_HW_VERF == test_ctx->setup.op_type) { + struct wd_ecc_req *req = test_ctx->req; + + wd_ecc_del_in((handle_t)test_ctx->priv, req->src); + free(req); + } else if (SM2_SW_SIGN == test_ctx->setup.op_type) { + } else if (SM2_HW_SIGN == test_ctx->setup.op_type || + SM2_HW_VERF == test_ctx->setup.op_type || + SM2_HW_ENC == test_ctx->setup.op_type || + SM2_HW_DEC == test_ctx->setup.op_type || + SM2_HW_KG == test_ctx->setup.op_type) { + struct wd_ecc_req *req = test_ctx->req; + + if (req->src) + wd_ecc_del_in(test_ctx->setup.sess, req->src); + if (req->dst) + wd_ecc_del_out(test_ctx->setup.sess, req->dst); + free(req); + } else { + HPRE_TST_PRT("%s: no op %d\n", __func__, test_ctx->setup.op_type); + } + + free(test_ctx); +} + +static int get_ecc_nid(const char *name, __u32 *nid, __u32 *curve_id) +{ + int i; + + for (i = 0; i < sizeof(ecc_curve_tbls) / sizeof(ecc_curve_tbls[0]); i++) { + + if (!strcmp(name, ecc_curve_tbls[i].name)) { + *nid = ecc_curve_tbls[i].nid; + *curve_id = ecc_curve_tbls[i].curve_id; + return 0; + } + } + + return -1; +} + +static int hpre_get_rand(char *out, size_t out_len, void *usr) +{ + int ret; + + if (!out) { + return -1; + } + + ret = RAND_priv_bytes((void *)out, out_len); + if (ret != 1) { + HPRE_TST_PRT("RAND_priv_bytes fail = %d\n", ret); + return -1; + } + + return 0; +} + +static int get_hash_bytes(void) +{ + __u32 val = 0; + + switch (g_config.hash_type) { + case HASH_MD4: + case HASH_MD5: + val = BITS_TO_BYTES(128); + break; + case HASH_SHA1: + val = BITS_TO_BYTES(160); + break; + case HASH_SHA224: + val = BITS_TO_BYTES(224); + break; + case HASH_SHA256: + case HASH_SM3: + val = BITS_TO_BYTES(256); + break; + case HASH_SHA384: + val = BITS_TO_BYTES(384); + break; + case HASH_SHA512: + val = BITS_TO_BYTES(512); + break; + default: + break; + } + + return val; +} + +static const EVP_MD *get_digest_handle(void) +{ + const EVP_MD *digest; + + switch (g_config.hash_type) { + case HASH_MD4: + digest = EVP_md4(); + break; + case HASH_MD5: + digest = EVP_md5(); + break; + case HASH_SHA1: + digest = EVP_sha1(); + break; + case HASH_SHA224: + digest = EVP_sha224(); + break; + case HASH_SHA256: + digest = EVP_sha256(); + break; + case HASH_SM3: + digest = EVP_sm3(); + break; + case HASH_SHA384: + digest = EVP_sha384(); + break; + case HASH_SHA512: + digest = EVP_sha512(); + break; + default: + digest = EVP_sm3(); + break; + } + + return digest; +} + +static int hpre_compute_hash(const char *in, size_t in_len, + char *out, size_t out_len, void *usr) +{ + const EVP_MD *digest; + EVP_MD_CTX *hash = EVP_MD_CTX_new(); + int ret = 0; + + digest = get_digest_handle(); + if (EVP_DigestInit(hash, digest) == 0 || + EVP_DigestUpdate(hash, in, in_len) == 0 || + EVP_DigestFinal(hash, (void *)out, NULL) == 0) { + HPRE_TST_PRT("compute hash failed\n"); + ret = -1; + } + + EVP_MD_CTX_free(hash); + + return ret; +} + +static EC_KEY *create_ec_key(__u32 nid, struct wd_dtb *pubkey, struct wd_dtb *prikey) +{ + EC_KEY *key_a = NULL; + EC_GROUP *group_a; + BIGNUM *pub, *priv; + EC_POINT *point_tmp, *ptr; + int ret; + + key_a = EC_KEY_new(); + if (!key_a) { + printf("EC_KEY_new err!\n"); + return NULL; + } + + group_a = EC_GROUP_new_by_curve_name(nid); + if(!group_a) { + printf("EC_GROUP_new_by_curve_name err!\n"); + goto free_key; + } + + ret = EC_KEY_set_group(key_a, group_a); + if(ret != 1) { + printf("EC_KEY_set_group err.\n"); + goto free_group; + } + + /* set pubkey */ + if (pubkey) { + point_tmp = EC_GROUP_get0_generator(group_a); + pub = BN_bin2bn((unsigned char *)pubkey->data, pubkey->dsize, NULL); + ptr = EC_POINT_bn2point(group_a, pub, point_tmp, NULL); + if (!ptr) { + printf("EC_POINT_bn2point failed\n"); + print_data(pubkey->data, pubkey->dsize, "pub"); + BN_free(pub); + goto free_group; + } + + ret = EC_KEY_set_public_key(key_a, point_tmp); + if (ret != 1) { + printf("EC_KEY_set_public_key failed\n"); + BN_free(pub); + goto free_group; + } + BN_free(pub); + } + + /* set prikey */ + if (prikey) { + priv = BN_bin2bn((unsigned char *)prikey->data, prikey->dsize, NULL); + ret = EC_KEY_set_private_key(key_a, priv); + if (ret != 1) { + printf("EC_KEY_set_private_key failed\n"); + BN_free(priv); + goto free_group; + } + BN_free(priv); + } + + EC_GROUP_free(group_a); + + return key_a; + +free_group: + EC_GROUP_free(group_a); +free_key: + EC_KEY_free(key_a); + + return NULL; +} + +static EVP_MD_CTX *create_evp_md_ctx(__u32 nid, EC_KEY *ecc_key) +{ + EVP_MD_CTX *md_ctx; + EVP_PKEY_CTX *pctx; + EVP_PKEY *pkey; + + pkey = EVP_PKEY_new(); + if (!pkey) { + printf("EVP_PKEY_new failed\n"); + return NULL; + } + + EVP_PKEY_set1_EC_KEY(pkey, ecc_key); + EVP_PKEY_set_alias_type(pkey, nid); + pctx = EVP_PKEY_CTX_new(pkey, NULL); + if (!pctx) { + printf("EVP_PKEY_CTX_new failed\n"); + goto del_pkey; + } + + md_ctx = EVP_MD_CTX_new(); + if (!md_ctx) { + printf("EVP_MD_CTX_new failed\n"); + goto del_pkey_ctx; + } + + EVP_MD_CTX_set_pkey_ctx(md_ctx, pctx); + + return md_ctx; +del_pkey_ctx: + EVP_PKEY_CTX_free(pctx); +del_pkey: + EVP_PKEY_free(pkey); + + return NULL; +} + +static void del_evp_md_ctx(EVP_MD_CTX *md_ctx) +{ + EVP_PKEY_CTX *pctx = EVP_MD_CTX_pkey_ctx(md_ctx); + EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(pctx); + + EVP_PKEY_free(pkey); + EVP_PKEY_CTX_free(pctx); + EVP_MD_CTX_free(md_ctx); +} + +static void *ecc_create_openssl_handle(struct wd_dtb *prk, struct wd_dtb *pbk) +{ + EVP_MD_CTX *md_ctx; + EC_KEY *ec_key; + + ec_key = create_ec_key(EVP_PKEY_SM2, pbk, prk); + if (!ec_key) + return NULL; + + md_ctx = create_evp_md_ctx(EVP_PKEY_SM2, ec_key); + if (!md_ctx) + goto del_ec_key; + + return md_ctx; + +del_ec_key: + EC_KEY_free(ec_key); + + return NULL; +} + +static void ecc_del_openssl_handle(void *handle) +{ + EVP_MD_CTX *md_ctx = handle; + EVP_PKEY_CTX *pctx = EVP_MD_CTX_pkey_ctx(md_ctx); + EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(pctx); + EC_KEY *ec_key = EVP_PKEY_get0(pkey); + + EC_KEY_free(ec_key); + del_evp_md_ctx(md_ctx); +} + +static int set_sess_key(handle_t sess, struct wd_dtb *prk, struct wd_ecc_point *pbk) +{ + struct wd_ecc_key *ecc_key; + int ret; + + ecc_key = wd_ecc_get_key(sess); + if (prk) { + ret = wd_ecc_set_prikey(ecc_key, prk); + if (ret) { + HPRE_TST_PRT("%s: set prikey err\n", __func__); + return -1; + } + } + + if (pbk) { + ret = wd_ecc_set_pubkey(ecc_key, pbk); + if (ret) { + HPRE_TST_PRT("%s: set pubkey err\n", __func__); + return -1; + } + } + + return 0; +} + +static struct ecc_test_ctx *ecdh_create_sw_gen_test_ctx(struct ecc_test_ctx_setup setup, u32 optype) +{ + struct ecc_test_ctx *test_ctx; + EC_KEY *key = NULL; + EC_GROUP *group; + int ret; + + if (ECDH_SW_GENERATE != setup.op_type) { + HPRE_TST_PRT("%s: err op type %d\n", __func__, setup.op_type); + return NULL; + } + + key = EC_KEY_new(); + if (!key) { + printf("EC_KEY_new err!\n"); + return NULL; + } + + group = EC_GROUP_new_by_curve_name(setup.nid); + if(!group) { + printf("EC_GROUP_new_by_curve_name err!\n"); + goto free_ec_key; + } + + ret = EC_KEY_set_group(key, group); + if(ret != 1) { + printf("EC_KEY_set_group err.\n"); + goto free_ec_key; + } + + EC_GROUP_free(group); + + test_ctx = malloc(sizeof(struct ecc_test_ctx)); + if (!test_ctx) { + printf("malloc failed.\n"); + goto free_ec_key; + } + + if (setup.key_from) { + BIGNUM *privKey; + + privKey = BN_bin2bn(setup.priv_key, setup.priv_key_size, NULL); + ret = EC_KEY_set_private_key(key, privKey); + if (ret != 1) { + printf("EC_KEY_set_private_key failed\n"); + goto free_ctx; + } + } else {} + + test_ctx->priv = key; + test_ctx->key_size = setup.key_bits >> 3; + +#ifdef DEBUG + ECParameters_print_fp(stdout, key); + EC_KEY_print_fp(stdout, key, 0); +#endif + + return test_ctx; + +free_ctx: + free(test_ctx); +free_ec_key: + EC_KEY_free(key); + return NULL; +} + + +static struct ecc_test_ctx *ecxdh_create_hw_gen_test_ctx(struct ecc_test_ctx_setup setup, u32 op_type) +{ + struct ecc_test_ctx *test_ctx; + struct wd_ecc_key *ecc_key; + struct wd_ecc_out *ecc_out; + struct wd_ecc_req *req; + handle_t sess = setup.sess; + struct wd_dtb d; + int ret; + u32 key_size; + + req = malloc(sizeof(struct wd_ecc_req)); + if (!req) + return NULL; + memset(req, 0, sizeof(struct wd_ecc_req)); + + test_ctx = malloc(sizeof(struct ecc_test_ctx)); + if (!test_ctx) { + HPRE_TST_PRT("%s: malloc fail!\n", __func__); + goto free_req; + } + memset(test_ctx, 0, sizeof(struct ecc_test_ctx)); + + key_size = (wd_ecc_get_key_bits(sess) + 7) / 8; + test_ctx->cp_pub_key = malloc(2 * key_size); + if (!test_ctx->cp_pub_key) { + HPRE_TST_PRT("%s: malloc fail!\n", __func__); + goto free_ctx; + } + + ecc_out = wd_ecxdh_new_out(sess); + if (!ecc_out) { + HPRE_TST_PRT("%s: new ecc out fail!\n", __func__); + goto free_cp_key; + } + + ecc_key = wd_ecc_get_key(sess); + + if (setup.key_from || !setup.nid) { // performance || async, the param is ready by curve + if ((!g_is_set_prikey && is_async_test(op_type)) || !is_async_test(op_type)) { + d.data = (void *)setup.priv_key; + d.dsize = setup.priv_key_size; + d.bsize = setup.priv_key_size; + ret = wd_ecc_set_prikey(ecc_key, &d); + if (ret) { + HPRE_TST_PRT("%s: set prikey err\n", __func__); + goto del_ecc_out; + } + g_is_set_prikey = true; + } + + if (op_type >= X25519_GEN && op_type <= X448_ASYNC_COMPUTE) { + memcpy(test_ctx->cp_pub_key, setup.pub_key, key_size); + test_ctx->cp_pub_key_size = setup.pub_key_size; + } else { + memcpy(test_ctx->cp_pub_key, setup.pub_key + 1, key_size * 2); + test_ctx->cp_pub_key_size = setup.pub_key_size - 1; + } + } else { // sync && not performance, the prikey/pubkey are from openssl + if (op_type == X25519_GEN ||op_type == X25519_COMPUTE) { // x25519 + /* ret = x_genkey_by_openssl(test_ctx, ecc_key, key_size, 1); + if (ret == 0) { + return NULL; + } */ + } else if (op_type == X448_GEN ||op_type == X448_COMPUTE) { // x448 + /* ret = x_genkey_by_openssl(test_ctx, ecc_key, key_size, 2); + if (ret == 0) { + return NULL; + } */ + } else { // ecdh + EC_KEY *key_a = NULL; + EC_GROUP *group_a; + EC_POINT *point; + BIGNUM *d; + struct wd_dtb dtb_d; + char *tmp; + size_t len; + + key_a = EC_KEY_new(); + if (!key_a) { + printf("EC_KEY_new err!\n"); + goto del_ecc_out; + } + + group_a = EC_GROUP_new_by_curve_name(setup.nid); + if(!group_a) { + printf("EC_GROUP_new_by_curve_name err!\n"); + EC_KEY_free(key_a); + goto del_ecc_out; + } + + ret = EC_KEY_set_group(key_a, group_a); + if(ret != 1) { + printf("EC_KEY_set_group err.\n"); + EC_KEY_free(key_a); + goto del_ecc_out; + } + + ret = EC_KEY_generate_key(key_a); + if(ret != 1) { + printf("EC_KEY_generate_key err.\n"); + ECParameters_print_fp(stdout, key_a); + EC_KEY_print_fp(stdout, key_a, 4); + EC_KEY_free(key_a); + goto del_ecc_out; + } + + d = EC_KEY_get0_private_key(key_a); + if (!d) { + printf("EC_KEY_get0_private_key err.\n"); + EC_KEY_free(key_a); + goto del_ecc_out; + } + + tmp = malloc(key_size); + if (!tmp) { + printf("malloc fail!\n"); + EC_KEY_free(key_a); + goto del_ecc_out; + } + + memset(tmp, 0, key_size); + dtb_d.dsize = BN_bn2bin(d, (void *)tmp); + dtb_d.bsize = key_size; + dtb_d.data = tmp; + ret = wd_ecc_set_prikey(ecc_key, &dtb_d); + if (ret) { + HPRE_TST_PRT("%s: set prikey err\n", __func__); + EC_KEY_free(key_a); + free(tmp); + goto del_ecc_out; + } + free(tmp); + + point = EC_KEY_get0_public_key(key_a); + if (!point) { + printf("EC_KEY_get0_public_key err.\n"); + EC_KEY_free(key_a); + goto del_ecc_out; + } + len = EC_POINT_point2buf(group_a, point, 4, &tmp, NULL); + memcpy(test_ctx->cp_pub_key, tmp + 1, 2 * key_size); + test_ctx->cp_pub_key_size = len - 1; + + EC_GROUP_free(group_a); + OPENSSL_free(tmp); + EC_KEY_free(key_a); + } + } + +#ifdef DEBUG + //struct wd_dtb *p; + + //wd_ecc_get_prikey_params(ecc_key, &p, NULL, NULL, NULL, NULL, NULL); + //print_data(p->data, ECC_PRIKEY_SZ(p->bsize), "prikey"); + //print_data(test_ctx->cp_pub_key, test_ctx->cp_pub_key_size, "cp_pub_key"); +#endif + + req->op_type = WD_ECXDH_GEN_KEY; + req->dst = ecc_out; + test_ctx->req = req; + test_ctx->priv = (void *)sess; + test_ctx->key_size = key_size; + + return test_ctx; + +del_ecc_out: + (void)wd_ecc_del_out(sess, ecc_out); +free_cp_key: + free(test_ctx->cp_pub_key); +free_ctx: + free(test_ctx); +free_req: + free(req); + + return NULL; +} + +static struct ecc_test_ctx *ecdh_create_sw_compute_test_ctx(struct ecc_test_ctx_setup setup, u32 optype) +{ + struct ecc_test_ctx *test_ctx; + struct ecdh_sw_opdata *req; + + EC_KEY *key_a = NULL; + EC_KEY *key_b = NULL; + EC_GROUP *group_a, *group_b; + BIGNUM *privKey, *pubKey; + EC_POINT *point_tmp, *ptr; + int ret; + + if (ECDH_SW_COMPUTE != setup.op_type) { + HPRE_TST_PRT("%s: err op type %d\n", __func__, setup.op_type); + return NULL; + } + + key_a = EC_KEY_new(); + if (!key_a) { + printf("EC_KEY_new err!\n"); + return NULL; + } + + group_a = EC_GROUP_new_by_curve_name(setup.nid); + if(!group_a) { + printf("EC_GROUP_new_by_curve_name err!\n"); + goto free_ec_key_a; + } + + ret = EC_KEY_set_group(key_a, group_a); + if(ret != 1) { + printf("EC_KEY_set_group err.\n"); + goto free_ec_key_a; + } + + test_ctx = malloc(sizeof(struct ecc_test_ctx)); + if (!test_ctx) { + printf("malloc failed.\n"); + goto free_ec_key_a; + } + + req = malloc(sizeof(struct ecdh_sw_opdata)); + if (!req) { + EC_KEY_free(key_a); + free(test_ctx); + goto free_ctx; + } + + memset(req, 0, sizeof(struct ecdh_sw_opdata)); + test_ctx->req = req; + + req->share_key = malloc((setup.key_bits >> 3) * 3); + if (!req->share_key) { + goto free_req; + } + req->share_key_size = (setup.key_bits >> 3) * 3; + + if (setup.key_from) { + point_tmp = EC_GROUP_get0_generator(group_a); + pubKey = BN_bin2bn(setup.except_pub_key, setup.except_pub_key_size, NULL); + ptr = EC_POINT_bn2point(group_a, pubKey, point_tmp, NULL); + if (!ptr) { + printf("EC_POINT_bn2point failed\n"); + BN_free(pubKey); + goto free_req; + } + BN_free(pubKey); + req->except_pub_key = point_tmp; + privKey = BN_bin2bn(setup.priv_key, setup.priv_key_size, NULL); + ret = EC_KEY_set_private_key(key_a, privKey); + if (ret != 1) { + printf("EC_KEY_set_private_key failed\n"); + goto free_req; + } + BN_free(privKey); + } else { + ret = EC_KEY_generate_key(key_a); + if(ret != 1) { + printf("EC_KEY_generate_key err.\n"); + goto free_share_key; + } + + key_b = EC_KEY_new(); + if (!key_b) { + printf("EC_KEY_new err!\n"); + goto free_share_key; + } + + group_b = EC_GROUP_new_by_curve_name(setup.nid); + if(!group_b) { + printf("EC_GROUP_new_by_curve_name err!\n"); + goto free_ec_key_b; + } + + ret = EC_KEY_set_group(key_b, group_b); + if(ret != 1) { + printf("EC_KEY_set_group err.\n"); + goto free_ec_key_b; + } + + ret = EC_KEY_generate_key(key_b); + if(ret != 1) { + printf("EC_KEY_generate_key err.\n"); + goto free_ec_key_b; + } + + req->except_pub_key = EC_POINT_dup(EC_KEY_get0_public_key(key_b), group_b); + if (!req->except_pub_key) { + printf("EC_KEY_get0_public_key err.\n"); + goto free_ec_key_b; + } + + EC_GROUP_free(group_b); +#ifdef DEBUG + printf("except_pub_key:\n"); + ECParameters_print_fp(stdout, key_b); + EC_KEY_print_fp(stdout, key_b, 0); +#endif + EC_KEY_free(key_b); + } + + EC_GROUP_free(group_a); + test_ctx->priv = key_a; + test_ctx->key_size = setup.key_bits >> 3; + +#ifdef DEBUG + ECParameters_print_fp(stdout, key_a); + EC_KEY_print_fp(stdout, key_a, 0); +#endif + return test_ctx; + +free_ec_key_b: + EC_KEY_free(key_b); +free_share_key: + free(req->share_key); +free_req: + free(test_ctx->req); +free_ctx: + free(test_ctx); +free_ec_key_a: + EC_KEY_free(key_a); + + return NULL; +} + +static struct ecc_test_ctx *ecxdh_create_hw_compute_test_ctx(struct ecc_test_ctx_setup setup, u32 op_type) +{ + struct ecc_test_ctx *test_ctx; + struct wd_ecc_key *ecc_key; + struct wd_ecc_out *ecc_out; + struct wd_ecc_in *ecc_in; + struct wd_ecc_req *req; + struct wd_ecc_point tmp; + struct wd_dtb d; + int ret; + u32 key_size; + size_t len; + + req = malloc(sizeof(struct wd_ecc_req)); + if (!req) + return NULL; + memset(req, 0, sizeof(struct wd_ecc_req)); + + test_ctx = malloc(sizeof(struct ecc_test_ctx)); + if (!test_ctx) { + HPRE_TST_PRT("%s: malloc fail!\n", __func__); + goto free_req; + } + memset(test_ctx, 0, sizeof(struct ecc_test_ctx)); + + key_size = (wd_ecc_get_key_bits(setup.sess) + 7) / 8; + test_ctx->cp_share_key = malloc(key_size * 4); + if (!test_ctx->cp_share_key) { + HPRE_TST_PRT("%s: malloc fail!\n", __func__); + goto free_ctx; + } + + ecc_out = wd_ecxdh_new_out(setup.sess); + if (!ecc_out) { + goto free_cp_key; + } + + ecc_key = wd_ecc_get_key(setup.sess); + if (setup.key_from || !setup.nid) { + if (op_type == X25519_GEN || op_type == X25519_COMPUTE || + op_type == X448_GEN || op_type == X448_COMPUTE || + op_type == X25519_ASYNC_GEN || op_type == X25519_ASYNC_COMPUTE || + op_type == X448_ASYNC_GEN || op_type == X448_ASYNC_COMPUTE) + tmp.x.data = setup.except_pub_key; + else + tmp.x.data = setup.except_pub_key + 1; // step 0x04 + + tmp.x.bsize = key_size; + tmp.x.dsize = key_size; + tmp.y.data = tmp.x.data + key_size; + tmp.y.bsize = key_size; + tmp.y.dsize = key_size; + ecc_in = wd_ecxdh_new_in(setup.sess, &tmp); + if (!ecc_in) { + goto del_ecc_out; + } + + if ((!g_is_set_prikey && is_async_test(op_type)) || !is_async_test(op_type)) { + d.data = (void *)setup.priv_key; + d.dsize = setup.priv_key_size; + d.bsize = setup.priv_key_size; + ret = wd_ecc_set_prikey(ecc_key, &d); + if (ret) { + HPRE_TST_PRT("%s: set prikey err\n", __func__); + goto del_ecc_in; + } + g_is_set_prikey = true; + } + + memcpy(test_ctx->cp_share_key, setup.share_key, setup.share_key_size); + test_ctx->cp_share_key_size = setup.share_key_size; + } else { +#if 0 + if (op_type == X25519_GEN ||op_type == X25519_COMPUTE) { // x25519 + ret = x_compkey_by_openssl(test_ctx, sess, &ecc_in, ecc_key, key_size, 1); + if (ret == 0) { + return NULL; + } + } else if (op_type == X448_GEN ||op_type == X448_COMPUTE) { // x448 + ret = x_compkey_by_openssl(test_ctx, sess, &ecc_in, ecc_key, key_size, 2); + if (ret == 0) { + return NULL; + } + } else { // ecdh +#endif + EC_KEY *key_a = NULL; + EC_GROUP *group_a; + EC_POINT *point; + BIGNUM *d; + struct wd_dtb dtb_d; + char *buff; + + key_a = EC_KEY_new(); + if (!key_a) { + printf("EC_KEY_new err!\n"); + goto del_ecc_out; + } + + group_a = EC_GROUP_new_by_curve_name(setup.nid); + if(!group_a) { + printf("EC_GROUP_new_by_curve_name err!\n"); + EC_KEY_free(key_a); + goto del_ecc_out; + } + + ret = EC_KEY_set_group(key_a, group_a); + if(ret != 1) { + printf("EC_KEY_set_group err.\n"); + EC_KEY_free(key_a); + goto del_ecc_out; + } + + ret = EC_KEY_generate_key(key_a); + if(ret != 1) { + printf("EC_KEY_generate_key err.\n"); + ECParameters_print_fp(stdout, key_a); + EC_KEY_print_fp(stdout, key_a, 4); + EC_KEY_free(key_a); + goto del_ecc_out; + } + + d = EC_KEY_get0_private_key(key_a); + if (!d) { + printf("EC_KEY_get0_private_key err.\n"); + EC_KEY_free(key_a); + goto del_ecc_out; + } + + buff = malloc(key_size); + if (!buff) { + printf("malloc fail!\n"); + EC_KEY_free(key_a); + goto del_ecc_out; + } + + dtb_d.dsize = BN_bn2bin(d, (void *)buff); + dtb_d.bsize = key_size; + dtb_d.data = buff; + ret = wd_ecc_set_prikey(ecc_key, &dtb_d); + if (ret) { + HPRE_TST_PRT("%s: set prikey err\n", __func__); + EC_KEY_free(key_a); + free(buff); + goto del_ecc_out; + } + free(buff); + + point = EC_KEY_get0_public_key(key_a); + if (!point) { + printf("EC_KEY_get0_public_key err.\n"); + EC_KEY_free(key_a); + goto del_ecc_out; + } + + len = EC_POINT_point2buf(group_a, point, 4, &buff, NULL); + if (len != 2 * key_size + 1) { + printf("EC_POINT_point2buf err.\n"); + } + + EC_GROUP_free(group_a); + + tmp.x.data = buff + 1; + tmp.x.dsize = key_size; + tmp.x.bsize = key_size; + tmp.y.data = tmp.x.data + key_size; + tmp.y.dsize = key_size; + tmp.y.bsize = key_size; + ecc_in = wd_ecxdh_new_in(setup.sess, &tmp); + if (!ecc_in) { + printf("wd_ecc_new_in err.\n"); + EC_KEY_free(key_a); + free(buff); + goto del_ecc_out; + } + +#ifdef DEBUG + //print_data(buff + 1, len - 1, "except_pub_key"); +#endif + free(buff); + + ret = ECDH_compute_key(test_ctx->cp_share_key, key_size * 4, + point, key_a, NULL); + if (ret <= 0) { + printf("ECDH_compute_key err.\n"); + EC_KEY_free(key_a); + goto del_ecc_out; + } + + test_ctx->cp_share_key_size = ret; + EC_KEY_free(key_a); + } + +#ifdef DEBUG + //struct wd_dtb *p; + + //wd_ecc_get_prikey_params(ecc_key, &p, NULL, NULL, NULL, NULL, NULL); + //print_data(p->data, ECC_PRIKEY_SZ(p->bsize), "prikey"); + //print_data(test_ctx->cp_share_key, test_ctx->cp_share_key_size, "cp_share_key"); +#endif + + req->op_type = WD_ECXDH_COMPUTE_KEY; + req->src = ecc_in; + req->dst = ecc_out; + test_ctx->req = req; + test_ctx->priv = (void *)(setup.sess); //init sess + test_ctx->key_size = key_size; + + return test_ctx; + +del_ecc_in: + (void)wd_ecc_del_in(setup.sess, ecc_in); +del_ecc_out: + (void)wd_ecc_del_out(setup.sess, ecc_out); +free_cp_key: + free(test_ctx->cp_pub_key); +free_ctx: + free(test_ctx); +free_req: + free(req); + + return NULL; +} + +static struct ecc_test_ctx *sm2_create_hw_sign_test_ctx(struct ecc_test_ctx_setup setup, u32 op_type) +{ + __u8 is_dgst = g_config.msg_type == MSG_DIGEST; + struct wd_ecc_req *req; + struct ecc_test_ctx *test_ctx; + struct wd_ecc_out *ecc_out; + struct wd_ecc_in *ecc_in = NULL; + handle_t sess = setup.sess; + struct wd_dtb e, k, id; + struct wd_dtb *kptr = NULL; + struct wd_dtb *idptr = NULL; + char buff[32] = {0}; + char *hex_str; + u32 key_size; + int ret; + + req = malloc(sizeof(struct wd_ecc_req)); + if (!req) + return NULL; + memset(req, 0, sizeof(struct wd_ecc_req)); + + test_ctx = malloc(sizeof(struct ecc_test_ctx)); + if (!test_ctx) { + HPRE_TST_PRT("%s: malloc fail!\n", __func__); + goto free_req; + } + memset(test_ctx, 0, sizeof(struct ecc_test_ctx)); + + key_size = (wd_ecc_get_key_bits(sess) + 7) / 8; + ecc_out = wd_sm2_new_sign_out(sess); + if (!ecc_out) { + HPRE_TST_PRT("%s: new ecc out fail!\n", __func__); + goto free_ctx; + } + + e.data = setup.msg; + e.dsize = setup.msg_size; + e.bsize = setup.msg_size; + if (setup.key_from) { + k.data = (void *)setup.k; + k.dsize = setup.k_size; + k.bsize = key_size; + ecc_in = wd_sm2_new_sign_in(sess, &e, &k, NULL, 1); + if (!ecc_in) { + HPRE_TST_PRT("%s: new ecc in fail!\n", __func__); + goto del_ecc_out; + } + + memcpy(test_ctx->cp_sign, (void *)setup.sign, setup.sign_size); + test_ctx->cp_sign_size = setup.sign_size; + } else { + EVP_MD_CTX *md_ctx = setup.openssl_handle; + EVP_PKEY_CTX *pctx = EVP_MD_CTX_pkey_ctx(md_ctx); + EVP_PKEY *p_key = EVP_PKEY_CTX_get0_pkey(pctx); + + if (g_config.rand_type == RAND_PARAM) { + ret = hpre_get_rand(buff, 32, NULL); + if (ret) { + printf("hpre_get_rand failed\n"); + goto del_ecc_out; + } + k.data = buff; + k.dsize = setup.k_size; + kptr = &k; + + /* openssl set rand */ + hex_str = OPENSSL_buf2hexstr((void *)buff, 32); + start_fake_rand(hex_str); + OPENSSL_free(hex_str); + } + + test_ctx->cp_sign_size = MAX_SIGN_LEN; + if (g_config.msg_type == MSG_DIGEST) { + ret = EVP_PKEY_sign_init(pctx); + if (ret != 1) { + printf("EVP_PKEY_sign_init fail, ret %d\n", ret); + goto del_ecc_out; + } + + ret = EVP_PKEY_sign(pctx, test_ctx->cp_sign, &test_ctx->cp_sign_size, + setup.msg, setup.msg_size); + if (ret != 1) { + printf("EVP_PKEY_sign fail, ret %d\n", ret); + goto del_ecc_out; + } + } else { + id.data = (void *)setup.userid; + id.dsize = setup.userid_size; + idptr = &id; + + EVP_PKEY_CTX_set1_id(pctx, setup.userid, setup.userid_size); + p_key = EVP_PKEY_CTX_get0_pkey(pctx); + EVP_DigestSignInit(md_ctx, NULL, get_digest_handle(), NULL, p_key); + EVP_DigestSignUpdate(md_ctx, setup.msg, setup.msg_size); + ret = EVP_DigestSignFinal(md_ctx, test_ctx->cp_sign, &test_ctx->cp_sign_size); + if (ret != 1) { + printf("EVP_DigestSignFinal fail, ret %d\n", ret); + goto del_ecc_out; + } + } + + evp_sign_to_hpre_bin((void *)test_ctx->cp_sign, &test_ctx->cp_sign_size, 32); + ecc_in = wd_sm2_new_sign_in(sess, &e, kptr, idptr, is_dgst); + if (!ecc_in) { + HPRE_TST_PRT("%s: new ecc in fail!\n", __func__); + goto del_ecc_out; + } + } + +#ifdef DEBUG + struct wd_ecc_key *ecc_key = wd_ecc_get_key(sess); + struct wd_dtb *p; + + wd_ecc_get_prikey_params(ecc_key, &p, NULL, NULL, NULL, NULL, NULL); + print_data(p->data, ECC_PRIKEY_SZ(p->bsize), "prikey"); + print_data(test_ctx->cp_sign, test_ctx->cp_sign_size, "cp_sign"); +#endif + + req->op_type = WD_SM2_SIGN; + req->dst = ecc_out; + req->src = ecc_in; + test_ctx->req = req; + test_ctx->key_size = key_size; + + return test_ctx; + +del_ecc_out: + (void)wd_ecc_del_out(sess, ecc_out); +free_ctx: + free(test_ctx); +free_req: + free(req); + + return NULL; +} + +static struct ecc_test_ctx *sm2_create_sw_sign_test_ctx(struct ecc_test_ctx_setup setup, u32 opType) +{ + return NULL; +} + +static struct ecc_test_ctx *sm2_create_hw_verf_test_ctx(struct ecc_test_ctx_setup setup, u32 op_type) +{ + struct wd_ecc_req *req; + struct wd_ecc_out *ecc_out; + struct ecc_test_ctx *test_ctx; + struct wd_ecc_in *ecc_in = NULL; + handle_t sess = setup.sess; + struct wd_dtb e, r, s, id; + u32 key_size; + int ret; + + req = malloc(sizeof(struct wd_ecc_req)); + if (!req) + return NULL; + memset(req, 0, sizeof(struct wd_ecc_req)); + + test_ctx = malloc(sizeof(struct ecc_test_ctx)); + if (!test_ctx) { + HPRE_TST_PRT("%s: malloc fail!\n", __func__); + goto free_req; + } + memset(test_ctx, 0, sizeof(struct ecc_test_ctx)); + + key_size = (wd_ecc_get_key_bits(sess) + 7) / 8; + ecc_out = wd_sm2_new_sign_out(sess); + if (!ecc_out) { + HPRE_TST_PRT("%s: new ecc out fail!\n", __func__); + goto free_ctx; + } + + + e.data = setup.msg; + e.dsize = setup.msg_size; + e.bsize = key_size; + if (setup.key_from) { + r.data = (void *)setup.sign; + r.dsize = key_size; + r.bsize = key_size; + s.data = r.data + key_size; + s.dsize = key_size; + s.bsize = key_size; + ecc_in = wd_sm2_new_verf_in(sess, &e, &r, &s, NULL, 1); + if (!ecc_in) { + HPRE_TST_PRT("%s: new ecc in fail!\n", __func__); + goto del_ecc_out; + } + } else { + EVP_MD_CTX *md_ctx = setup.openssl_handle; + EVP_PKEY_CTX *pctx = EVP_MD_CTX_pkey_ctx(md_ctx); + EVP_PKEY *p_key = EVP_PKEY_CTX_get0_pkey(pctx); + + test_ctx->cp_sign_size = MAX_SIGN_LEN; + id.data = (void *)setup.userid; + id.dsize = setup.userid_size; + EVP_PKEY_CTX_set1_id(pctx, setup.userid, setup.userid_size); + p_key = EVP_PKEY_CTX_get0_pkey(pctx); + EVP_DigestSignInit(md_ctx, NULL, get_digest_handle(), NULL, p_key); + ret = EVP_DigestSign(md_ctx, test_ctx->cp_sign, &test_ctx->cp_sign_size, + setup.msg, setup.msg_size); + if (ret != 1) { + printf("EVP_DigestSign fail, ret %d\n", ret); + goto del_ecc_out; + } + + evp_sign_to_hpre_bin((void *)test_ctx->cp_sign, &test_ctx->cp_sign_size, key_size); + r.data = (void *)test_ctx->cp_sign; + r.dsize = key_size; + r.bsize = key_size; + s.data = r.data + key_size; + s.dsize = key_size; + s.bsize = key_size; + ecc_in = wd_sm2_new_verf_in(sess, &e, &r, &s, &id, 0); + if (!ecc_in) { + HPRE_TST_PRT("%s: new ecc in fail!\n", __func__); + goto del_ecc_out; + } + } + +#ifdef DEBUG + struct wd_ecc_key *ecc_key = wd_ecc_get_key(sess); + struct wd_dtb *p; + + wd_ecc_get_pubkey_params(ecc_key, &p, NULL, NULL, NULL, NULL, NULL); + print_data(p->data, ECC_PRIKEY_SZ(p->bsize), "pubkey"); + print_data((void *)setup.userid, setup.userid_size, "userid"); + print_data(test_ctx->cp_sign, test_ctx->cp_sign_size, "openssl sign"); +#endif + + req->op_type = WD_SM2_VERIFY; + req->src = ecc_in; + test_ctx->req = req; + test_ctx->key_size = key_size; + + return test_ctx; + +del_ecc_out: + (void)wd_ecc_del_out(sess, ecc_out); +free_ctx: + free(test_ctx); +free_req: + free(req); + + return NULL; +} + +static struct ecc_test_ctx *sm2_create_sw_verf_test_ctx(struct ecc_test_ctx_setup setup, u32 op_type) +{ + return NULL; +} + +static struct ecc_test_ctx *sm2_create_hw_enc_test_ctx(struct ecc_test_ctx_setup setup, u32 op_type) +{ + struct wd_ecc_req *req; + struct ecc_test_ctx *test_ctx; + struct wd_ecc_out *ecc_out; + struct wd_ecc_in *ecc_in = NULL; + handle_t sess = setup.sess; + struct wd_dtb e, k; + struct wd_dtb *kptr = NULL; + char buff[32] = {0}; + char *hex_str; + u32 key_size; + int ret; + + req = malloc(sizeof(struct wd_ecc_req)); + if (!req) + return NULL; + memset(req, 0, sizeof(struct wd_ecc_req)); + + test_ctx = malloc(sizeof(struct ecc_test_ctx)); + if (!test_ctx) { + HPRE_TST_PRT("%s: malloc fail!\n", __func__); + goto free_req; + } + memset(test_ctx, 0, sizeof(struct ecc_test_ctx)); + + key_size = (wd_ecc_get_key_bits(sess) + 7) / 8; + ecc_out = wd_sm2_new_enc_out(sess, setup.msg_size); + if (!ecc_out) { + HPRE_TST_PRT("%s: new ecc out fail!\n", __func__); + goto free_ctx; + } + + e.data = (void *)setup.msg; + e.dsize = setup.msg_size; + e.bsize = setup.msg_size; + if (setup.key_from) { + e.data = (void *)setup.plaintext; + e.dsize = setup.plaintext_size; + e.bsize = setup.plaintext_size; + k.data = (void *)setup.k; + k.dsize = setup.k_size; + k.bsize = key_size; + kptr = &k; + memcpy(test_ctx->cp_enc, (void *)setup.ciphertext, setup.ciphertext_size); + test_ctx->cp_enc_size = setup.ciphertext_size; + } else if (g_config.rand_type == RAND_PARAM) { + EVP_MD_CTX *md_ctx = setup.openssl_handle; + EVP_PKEY_CTX *pctx = EVP_MD_CTX_pkey_ctx(md_ctx); + + ret = hpre_get_rand(buff, 32, NULL); + if (ret) { + printf("hpre_get_rand failed\n"); + goto del_ecc_out; + } + k.data = buff; + k.dsize = setup.k_size; + kptr = &k; + + /* openssl set rand */ + hex_str = OPENSSL_buf2hexstr((void *)buff, k.dsize); + start_fake_rand(hex_str); + OPENSSL_free(hex_str); + + EVP_PKEY_encrypt_init(pctx); + EVP_PKEY_CTX_ctrl(pctx, -1, -1, EVP_PKEY_CTRL_MD, -1, (void *)get_digest_handle()); + test_ctx->cp_sign_size = MAX_SIGN_LEN; + ret = EVP_PKEY_encrypt(pctx, test_ctx->cp_enc, &test_ctx->cp_enc_size, + setup.msg, setup.msg_size); + if (ret != 1) { + printf("EVP_PKEY_encrypt fail, ret %d\n", ret); + goto del_ecc_out; + } + + #ifdef DEBUG + struct wd_ecc_key *ecc_key = wd_ecc_get_key(sess); + struct wd_dtb *p; + + wd_ecc_get_prikey_params(ecc_key, &p, NULL, NULL, NULL, NULL, NULL); + print_data(p->data, ECC_PRIKEY_SZ(p->bsize), "pubkey"); + print_data(test_ctx->cp_enc, test_ctx->cp_enc_size, "cp_enc"); + #endif + + evp_to_wd_crypto((void *)test_ctx->cp_enc, &test_ctx->cp_enc_size, 32, setup.op_type); + + #ifdef DEBUG + print_data(test_ctx->cp_enc, test_ctx->cp_enc_size, "cp_enc"); + #endif + } + + ecc_in = wd_sm2_new_enc_in(sess, kptr, &e); + if (!ecc_in) { + HPRE_TST_PRT("%s: new ecc in fail!\n", __func__); + goto del_ecc_out; + } + + req->op_type = WD_SM2_ENCRYPT; + req->dst = ecc_out; + req->src = ecc_in; + test_ctx->req = req; + test_ctx->key_size = key_size; + + return test_ctx; + +del_ecc_out: + (void)wd_ecc_del_out(sess, ecc_out); +free_ctx: + free(test_ctx); +free_req: + free(req); + + return NULL; +} + +static struct ecc_test_ctx *sm2_create_sw_enc_test_ctx(struct ecc_test_ctx_setup setup, u32 op_type) +{ + return NULL; +} + +static struct ecc_test_ctx *sm2_create_hw_dec_test_ctx(struct ecc_test_ctx_setup setup, u32 op_type) +{ + struct wd_ecc_req *req; + struct ecc_test_ctx *test_ctx; + struct wd_ecc_out *ecc_out; + struct wd_ecc_in *ecc_in = NULL; + struct wd_ecc_point c1; + struct wd_dtb c2, c3; + handle_t sess = setup.sess; + u32 key_size; + int ret; + + req = malloc(sizeof(struct wd_ecc_req)); + if (!req) + return NULL; + memset(req, 0, sizeof(struct wd_ecc_req)); + + test_ctx = malloc(sizeof(struct ecc_test_ctx)); + if (!test_ctx) { + HPRE_TST_PRT("%s: malloc fail!\n", __func__); + goto free_req; + } + memset(test_ctx, 0, sizeof(struct ecc_test_ctx)); + + key_size = (wd_ecc_get_key_bits(sess) + 7) / 8; + + + if (setup.key_from) { + c1.x.data = (void *)setup.ciphertext; + c1.x.dsize = 32; + c1.y.data = c1.x.data + 32; + c1.y.dsize = 32; + c3.data = c1.y.data + 32; + c3.dsize = 32; + c2.data = c3.data + 32; + c2.dsize = setup.ciphertext_size - 32 * 3; + ecc_in = wd_sm2_new_dec_in(sess, &c1, &c2, &c3); + if (!ecc_in) { + HPRE_TST_PRT("%s: new ecc in fail!\n", __func__); + goto free_ctx; + } + memcpy(test_ctx->cp_enc, setup.plaintext, setup.plaintext_size); + test_ctx->cp_enc_size = setup.plaintext_size; + } else { + EVP_MD_CTX *md_ctx = setup.openssl_handle; + EVP_PKEY_CTX *pctx = EVP_MD_CTX_pkey_ctx(md_ctx); + + EVP_PKEY_encrypt_init(pctx); + EVP_PKEY_CTX_ctrl(pctx, -1, -1, EVP_PKEY_CTRL_MD, -1, (void *)get_digest_handle()); + test_ctx->cp_enc_size = MAX_ENC_LEN; + ret = EVP_PKEY_encrypt(pctx, (void *)test_ctx->cp_enc, &test_ctx->cp_enc_size, + setup.msg, setup.msg_size); + if (ret != 1) { + printf("EVP_PKEY_encrypt fail, ret %d\n", ret); + goto free_ctx; + } + + #ifdef DEBUG + print_data((void *)setup.msg, setup.msg_size, "msg"); + print_data(test_ctx->cp_enc, test_ctx->cp_enc_size, "cp_enc"); + #endif + evp_to_wd_crypto((void *)test_ctx->cp_enc, &test_ctx->cp_enc_size, 32, SM2_HW_ENC); + + c1.x.data = (char *)test_ctx->cp_enc; + c1.x.dsize = 32; + c1.y.data = c1.x.data + 32; + c1.y.dsize = 32; + c3.data = c1.y.data + 32; + c3.dsize = get_hash_bytes(); + c2.data = c3.data + c3.dsize; + c2.dsize = setup.plaintext_size; + ecc_in = wd_sm2_new_dec_in(sess, &c1, &c2, &c3); + if (!ecc_in) { + HPRE_TST_PRT("%s: new ecc in fail!\n", __func__); + goto free_ctx; + } + + memcpy(test_ctx->cp_enc, setup.msg, setup.msg_size); + test_ctx->cp_enc_size = setup.msg_size; + } + + ecc_out = wd_sm2_new_dec_out(sess, c2.dsize); + if (!ecc_out) { + HPRE_TST_PRT("%s: new ecc out fail!\n", __func__); + goto free_ctx; + } + + #ifdef DEBUG + struct wd_ecc_key *ecc_key = wd_ecc_get_key(sess); + struct wd_dtb *p; + + wd_ecc_get_prikey_params(ecc_key, &p, NULL, NULL, NULL, NULL, NULL); + print_data(p->data, ECC_PRIKEY_SZ(p->bsize), "prikey"); + print_data(test_ctx->cp_enc, test_ctx->cp_enc_size, "cp_enc"); + #endif + + req->op_type = WD_SM2_DECRYPT; + req->dst = ecc_out; + req->src = ecc_in; + test_ctx->req = req; + test_ctx->key_size = key_size; + + return test_ctx; + +free_ctx: + free(test_ctx); +free_req: + free(req); + + return NULL; +} + +static struct ecc_test_ctx *sm2_create_sw_dec_test_ctx(struct ecc_test_ctx_setup setup, u32 op_type) +{ + return NULL; +} + +static struct ecc_test_ctx *sm2_create_hw_kg_test_ctx(struct ecc_test_ctx_setup setup, u32 op_type) +{ + struct wd_ecc_req *req; + struct ecc_test_ctx *test_ctx; + struct wd_ecc_out *ecc_out; + handle_t sess = setup.sess; + u32 key_size; + + req = malloc(sizeof(struct wd_ecc_req)); + if (!req) + return NULL; + memset(req, 0, sizeof(struct wd_ecc_req)); + + test_ctx = malloc(sizeof(struct ecc_test_ctx)); + if (!test_ctx) { + HPRE_TST_PRT("%s: malloc fail!\n", __func__); + goto free_req; + } + memset(test_ctx, 0, sizeof(struct ecc_test_ctx)); + + key_size = (wd_ecc_get_key_bits(sess) + 7) / 8; + ecc_out = wd_sm2_new_kg_out(sess); + if (!ecc_out) { + HPRE_TST_PRT("%s: new ecc out fail!\n", __func__); + goto free_ctx; + } + + if (setup.key_from) { + } else {} + + + req->op_type = WD_SM2_KG; + req->dst = ecc_out; + test_ctx->req = req; + test_ctx->key_size = key_size; + + return test_ctx; + +free_ctx: + free(test_ctx); +free_req: + free(req); + + return NULL; +} + +static struct ecc_test_ctx *sm2_create_sw_kg_test_ctx(struct ecc_test_ctx_setup setup, u32 op_type) +{ + return NULL; +} + +static struct ecc_test_ctx *ecc_create_sw_sign_test_ctx(struct ecc_test_ctx_setup setup, u32 optype) +{ + struct ecc_test_ctx *test_ctx; + struct ecdh_sw_opdata *opdata; + EC_KEY *key_a = NULL; + EC_GROUP *group_a; + BIGNUM *kinv, *privKey, *rp; + int size; + int ret; + + if (ECC_SW_SIGN != setup.op_type) { + HPRE_TST_PRT("%s: err op type %d\n", __func__, setup.op_type); + return NULL; + } + + key_a = EC_KEY_new(); + if (!key_a) { + printf("EC_KEY_new err!\n"); + return NULL; + } + + group_a = EC_GROUP_new_by_curve_name(setup.nid); + if(!group_a) { + printf("EC_GROUP_new_by_curve_name err!\n"); + goto free_ec_key_a; + } + + ret = EC_KEY_set_group(key_a, group_a); + if(ret != 1) { + printf("EC_KEY_set_group err.\n"); + goto free_ec_key_a; + } + EC_GROUP_free(group_a); + + test_ctx = malloc(sizeof(struct ecc_test_ctx)); + if (!test_ctx) { + printf("malloc failed.\n"); + goto free_ec_key_a; + } + + opdata = malloc(sizeof(struct ecdh_sw_opdata)); + if (!opdata) { + EC_KEY_free(key_a); + free(test_ctx); + goto free_ctx; + } + + memset(opdata, 0, sizeof(struct ecdh_sw_opdata)); + test_ctx->req = opdata; + size = ECDSA_size(key_a); + opdata->sign = malloc(size); + memset(opdata->sign, 0, size); + if (!opdata->sign) { + goto free_opdata; + } + + if (setup.key_from) { + opdata->except_e = setup.msg; + opdata->except_e_size = setup.msg_size; + kinv = BN_bin2bn((void *)setup.k, setup.k_size, NULL); // kinv invalid, actual should 1/kinv + opdata->except_kinv = kinv; + rp = BN_bin2bn(setup.rp, setup.rp_size, NULL); + opdata->except_rp = rp; + privKey = BN_bin2bn((void *)setup.priv_key, setup.priv_key_size, NULL); + ret = EC_KEY_set_private_key(key_a, privKey); + if (ret != 1) { + printf("EC_KEY_set_private_key failed\n"); + goto free_sign; + } + BN_free(privKey); + } else {} + + test_ctx->priv = key_a; + test_ctx->key_size = setup.key_bits >> 3; +#ifdef DEBUG + ECParameters_print_fp(stdout, key_a); + EC_KEY_print_fp(stdout, key_a, 0); +#endif + return test_ctx; + +free_sign: + free(opdata->sign); +free_opdata: + free(test_ctx->req); +free_ctx: + free(test_ctx); +free_ec_key_a: + EC_KEY_free(key_a); + + return NULL; +} + +static struct ecc_test_ctx *ecc_create_sw_verf_test_ctx(struct ecc_test_ctx_setup setup, u32 optype) +{ + struct ecc_test_ctx *test_ctx; + struct ecdh_sw_opdata *opdata; + EC_KEY *key_a = NULL; + EC_GROUP *group_a; + BIGNUM *pubkey; + EC_POINT *point_tmp, *ptr; + int ret; + + if (ECC_SW_VERF != setup.op_type) { + HPRE_TST_PRT("%s: err op type %d\n", __func__, setup.op_type); + return NULL; + } + + key_a = EC_KEY_new(); + if (!key_a) { + printf("EC_KEY_new err!\n"); + return NULL; + } + + group_a = EC_GROUP_new_by_curve_name(setup.nid); + if(!group_a) { + printf("EC_GROUP_new_by_curve_name err!\n"); + goto free_ec_key_a; + } + + ret = EC_KEY_set_group(key_a, group_a); + if(ret != 1) { + printf("EC_KEY_set_group err.\n"); + goto free_ec_key_a; + } + + test_ctx = malloc(sizeof(struct ecc_test_ctx)); + if (!test_ctx) { + printf("malloc failed.\n"); + goto free_ec_key_a; + } + + opdata = malloc(sizeof(struct ecdh_sw_opdata)); + if (!opdata) { + EC_KEY_free(key_a); + free(test_ctx); + goto free_ctx; + } + + memset(opdata, 0, sizeof(struct ecdh_sw_opdata)); + test_ctx->req = opdata; + + if (setup.key_from) { + opdata->except_e = (void *)setup.msg; + opdata->except_e_size = setup.msg_size; + opdata->sign = (void *)setup.sign; + opdata->sign_size = setup.sign_size; + + point_tmp = EC_GROUP_get0_generator(group_a); + pubkey = BN_bin2bn((void *)setup.pub_key, setup.pub_key_size, NULL); + ptr = EC_POINT_bn2point(group_a, pubkey, point_tmp, NULL); + if (!ptr) { + printf("EC_POINT_bn2point failed\n"); + BN_free(pubkey); + goto free_opdata; + } + + ret = EC_KEY_set_public_key(key_a, point_tmp); + if (ret != 1) { + printf("EC_KEY_set_public_key failed\n"); + BN_free(pubkey); + goto free_opdata; + } + BN_free(pubkey); + } else {} + + EC_GROUP_free(group_a); + test_ctx->priv = key_a; + test_ctx->key_size = setup.key_bits >> 3; +#ifdef DEBUG + ECParameters_print_fp(stdout, key_a); + EC_KEY_print_fp(stdout, key_a, 0); +#endif + return test_ctx; + +free_opdata: + free(test_ctx->req); +free_ctx: + free(test_ctx); +free_ec_key_a: + EC_KEY_free(key_a); + + return NULL; +} + +static struct ecc_test_ctx *ecc_create_hw_sign_test_ctx(struct ecc_test_ctx_setup setup, u32 op_type) +{ + + struct wd_ecc_req *opdata; + struct ecc_test_ctx *test_ctx; + struct wd_ecc_key *ecc_key; + struct wd_ecc_out *ecc_out; + struct wd_ecc_in *ecc_in = NULL; + struct wd_ecc_point pub; + EC_POINT *point_tmp, *ptr; + EC_KEY *key_a = NULL; + EC_GROUP *group_a; + BIGNUM *pubKey; + struct wd_dtb d, e, k; + int ret; + u32 key_size; + + opdata = malloc(sizeof(struct wd_ecc_req)); + if (!opdata) + return NULL; + memset(opdata, 0, sizeof(struct wd_ecc_req)); + + test_ctx = malloc(sizeof(struct ecc_test_ctx)); + if (!test_ctx) { + HPRE_TST_PRT("%s: malloc fail!\n", __func__); + goto free_opdata; + } + memset(test_ctx, 0, sizeof(struct ecc_test_ctx)); + + key_size = (wd_ecc_get_key_bits(setup.sess) + 7) / 8; + ecc_out = wd_ecdsa_new_sign_out(setup.sess); + if (!ecc_out) { + HPRE_TST_PRT("%s: new ecc out fail!\n", __func__); + goto free_ctx; + } + ecc_key = wd_ecc_get_key(setup.sess); + if (!g_is_set_prikey || !is_async_test(op_type)) { + d.data = (void *)setup.priv_key; + d.dsize = setup.priv_key_size; + d.bsize = setup.priv_key_size; + ret = wd_ecc_set_prikey(ecc_key, &d); + if (ret) { + HPRE_TST_PRT("%s: set prikey err\n", __func__); + goto del_ecc_out; + } + g_is_set_prikey = true; + } + + if (!g_is_set_pubkey || !is_async_test(op_type)) { + pub.x.data = (void *)setup.pub_key + 1; + pub.x.dsize = key_size; + pub.x.bsize = key_size; + pub.y.data = pub.x.data + key_size; + pub.y.dsize = key_size; + pub.y.bsize = key_size; + ret = wd_ecc_set_pubkey(ecc_key, &pub); + if (ret) { + HPRE_TST_PRT("%s: set pubkey err\n", __func__); + goto del_ecc_out; + } + g_is_set_pubkey = true; + } + + e.data = (void *)setup.msg; + e.dsize = setup.msg_size; + e.bsize = key_size; + + if (setup.key_from) { + k.data = (void *)setup.k; + k.dsize = setup.k_size; + k.bsize = key_size; + ecc_in = wd_ecdsa_new_sign_in(setup.sess, &e, &k); + if (!ecc_in) { + HPRE_TST_PRT("%s: new ecc in fail!\n", __func__); + goto del_ecc_out; + } + } else { + key_a = EC_KEY_new(); + if (!key_a) { + printf("EC_KEY_new err!\n"); + goto del_ecc_out; + } + + group_a = EC_GROUP_new_by_curve_name(setup.nid); + if(!group_a) { + printf("EC_GROUP_new_by_curve_name err!\n"); + EC_KEY_free(key_a); + goto del_ecc_out; + } + + ret = EC_KEY_set_group(key_a, group_a); + if(ret != 1) { + printf("EC_KEY_set_group err.\n"); + EC_KEY_free(key_a); + EC_GROUP_free(group_a); + goto del_ecc_out; + } + + /* set pubkey */ + point_tmp = EC_GROUP_get0_generator(group_a); + pubKey = BN_bin2bn((void *)setup.pub_key, setup.pub_key_size, NULL); + ptr = EC_POINT_bn2point(group_a, pubKey, point_tmp, NULL); + if (!ptr) { + printf("EC_POINT_bn2point failed\n"); + BN_free(pubKey); + EC_KEY_free(key_a); + EC_GROUP_free(group_a); + goto del_ecc_out; + } + + ret = EC_KEY_set_public_key(key_a, point_tmp); + if (ret != 1) { + printf("EC_KEY_set_public_key failed\n"); + BN_free(pubKey); + EC_KEY_free(key_a); + EC_GROUP_free(group_a); + goto del_ecc_out; + } + BN_free(pubKey); + EC_GROUP_free(group_a); + + ecc_in = wd_ecdsa_new_sign_in(setup.sess, &e, NULL); + if (!ecc_in) { + HPRE_TST_PRT("%s: new ecc in fail!\n", __func__); + goto del_ecc_out; + } + } + +#ifdef DEBUG + //struct wd_dtb *p; + + //wd_ecc_get_prikey_params(ecc_key, &p, NULL, NULL, NULL, NULL, NULL); + //print_data(p->data, ECC_PRIKEY_SZ(p->bsize), "prikey"); + //print_data(test_ctx->cp_pub_key, test_ctx->cp_pub_key_size, "cp_pub_key"); +#endif + + opdata->op_type = WD_ECDSA_SIGN; + opdata->dst = ecc_out; + opdata->src = ecc_in; + test_ctx->req = opdata; + test_ctx->priv = (void *)(setup.sess); //init ctx + test_ctx->key_size = key_size; + test_ctx->priv1 = key_a; + + return test_ctx; + +del_ecc_out: + (void)wd_ecc_del_out(setup.sess, ecc_out); +free_ctx: + free(test_ctx); +free_opdata: + free(opdata); + + return NULL; +} + +static struct ecc_test_ctx *ecc_create_hw_verf_test_ctx(struct ecc_test_ctx_setup setup, u32 op_type) +{ + struct wd_ecc_req *opdata; + struct ecc_test_ctx *test_ctx; + struct wd_ecc_key *ecc_key; + struct wd_ecc_in *ecc_in; + EC_KEY *key_a = NULL; + EC_GROUP *group_a; + BIGNUM *privKey; + ECDSA_SIG *sig; + BIGNUM *b_r, *b_s; + unsigned char buf1[100]; + unsigned char buf2[100]; + struct wd_dtb e, r, s; + struct wd_ecc_point pub; + int ret; + u32 key_size; + + opdata = malloc(sizeof(struct wd_ecc_req)); + if (!opdata) + return NULL; + memset(opdata, 0, sizeof(struct wd_ecc_req)); + + test_ctx = malloc(sizeof(struct ecc_test_ctx)); + if (!test_ctx) { + HPRE_TST_PRT("%s: malloc fail!\n", __func__); + goto free_opdata; + } + memset(test_ctx, 0, sizeof(struct ecc_test_ctx)); + + key_size = (wd_ecc_get_key_bits(setup.sess) + 7) / 8; + ecc_key = wd_ecc_get_key(setup.sess); + if (!g_is_set_pubkey || !is_async_test(op_type)) { + pub.x.data = (void *)setup.pub_key + 1; + pub.x.dsize = key_size; + pub.x.bsize = key_size; + pub.y.data = pub.x.data + key_size; + pub.y.dsize = key_size; + pub.y.bsize = key_size; + ret = wd_ecc_set_pubkey(ecc_key, &pub); + if (ret) { + HPRE_TST_PRT("%s: set pubkey err\n", __func__); + goto free_ctx; + } + g_is_set_pubkey = true; + } + + e.data = (void *)setup.msg; + e.dsize = setup.msg_size; + e.bsize = key_size; + + if (setup.key_from) { + r.data = (void *)setup.sign; + r.dsize = key_size; + r.bsize = key_size; + s.data = r.data + key_size; + s.dsize = key_size; + s.bsize = key_size; + ecc_in = wd_ecdsa_new_verf_in(setup.sess, &e, &r, &s); + if (!ecc_in) { + HPRE_TST_PRT("%s: new ecc in fail!\n", __func__); + goto free_ctx; + } + } else { + key_a = EC_KEY_new(); + if (!key_a) { + printf("EC_KEY_new err!\n"); + goto free_ctx; + } + + group_a = EC_GROUP_new_by_curve_name(setup.nid); + if(!group_a) { + printf("EC_GROUP_new_by_curve_name err!\n"); + EC_KEY_free(key_a); + goto free_ctx; + } + + ret = EC_KEY_set_group(key_a, group_a); + if(ret != 1) { + printf("EC_KEY_set_group err.\n"); + EC_KEY_free(key_a); + EC_GROUP_free(group_a); + goto free_ctx; + } + + /* set prikey */ + privKey = BN_bin2bn((void *)setup.priv_key, setup.priv_key_size, NULL); + ret = EC_KEY_set_private_key(key_a, privKey); + if (ret != 1) { + printf("EC_KEY_set_private_key failed\n"); + EC_KEY_free(key_a); + EC_GROUP_free(group_a); + goto free_ctx; + } + BN_free(privKey); + + EC_GROUP_free(group_a); + + sig = ECDSA_SIG_new(); + if (!sig) { + HPRE_TST_PRT("ECDSA_SIG_new fail!\n"); + EC_KEY_free(key_a); + goto free_ctx; + } + + /* openssl sign */ + sig = ECDSA_do_sign(setup.degist, setup.degist_size, key_a); + if (!sig) { + printf("ECDSA_do_sign failed\n"); + EC_KEY_free(key_a); + ECDSA_SIG_free(sig); + goto free_ctx; + } + + /* get r s */ + b_r = (void *)ECDSA_SIG_get0_r((const ECDSA_SIG *)sig); + ret = BN_bn2bin(b_r, buf1); + r.data = (void *)buf1; + r.dsize = ret; + r.bsize = key_size; + b_s = (void *)ECDSA_SIG_get0_s((const ECDSA_SIG *)sig); + ret = BN_bn2bin(b_s, buf2); + s.data = (void *)buf2; + s.dsize = ret; + s.bsize = key_size; + ECDSA_SIG_free(sig); + ecc_in = wd_ecdsa_new_verf_in(setup.sess, &e, &r, &s); + if (!ecc_in) { + HPRE_TST_PRT("%s: new ecc in fail!\n", __func__); + EC_KEY_free(key_a); + goto free_ctx; + } + EC_KEY_free(key_a); + } + +#ifdef DEBUG + //struct wd_dtb *p; + + //wd_get_ecc_prikey_params(ecc_key, &p, NULL, NULL, NULL, NULL, NULL); + //print_data(p->data, ECC_PRIKEY_SZ(p->bsize), "prikey"); + //print_data(test_ctx->cp_pub_key, test_ctx->cp_pub_key_size, "cp_pub_key"); +#endif + + opdata->op_type = WD_ECDSA_VERIFY; + opdata->src = ecc_in; + test_ctx->req = opdata; + test_ctx->priv = (void *)(setup.sess); //init ctx + test_ctx->key_size = key_size; + + return test_ctx; + +free_ctx: + free(test_ctx); +free_opdata: + free(opdata); + + return NULL; +} + +struct ecc_test_ctx *ecc_create_test_ctx(struct ecc_test_ctx_setup setup, u32 optype) +{ + struct ecc_test_ctx *test_ctx = NULL; + + switch (setup.op_type) { + case ECDH_SW_GENERATE: + { + if (optype == ECDH_GEN || optype == ECDH_ASYNC_GEN) { + test_ctx = ecdh_create_sw_gen_test_ctx(setup, optype); + } else if (optype == X25519_GEN || optype == X25519_ASYNC_GEN || + optype == X448_GEN || optype == X448_ASYNC_GEN) { + //test_ctx = x_create_sw_gen_test_ctx(setup, optype); + } + } + break; + case ECDH_HW_GENERATE: + { + test_ctx = ecxdh_create_hw_gen_test_ctx(setup, optype); + } + break; + case ECDH_SW_COMPUTE: + { + if (optype == ECDH_COMPUTE || optype == ECDH_ASYNC_COMPUTE) { + test_ctx = ecdh_create_sw_compute_test_ctx(setup, optype); + } else if (optype == X25519_COMPUTE || optype == X25519_ASYNC_COMPUTE || + optype == X448_COMPUTE || optype == X448_ASYNC_COMPUTE) { + //test_ctx = x_create_sw_compute_test_ctx(setup, optype); + } + } + break; + case ECDH_HW_COMPUTE: + { + test_ctx = ecxdh_create_hw_compute_test_ctx(setup, optype); + } + break; + case ECC_HW_SIGN: + { + test_ctx = ecc_create_hw_sign_test_ctx(setup, optype); + } + break; + case ECC_HW_VERF: + { + test_ctx = ecc_create_hw_verf_test_ctx(setup, optype); + } + break; + case ECC_SW_SIGN: + { + test_ctx = ecc_create_sw_sign_test_ctx(setup, optype); + } + break; + case ECC_SW_VERF: + { + test_ctx = ecc_create_sw_verf_test_ctx(setup, optype); + } + break; + case SM2_HW_SIGN: + { + test_ctx = sm2_create_hw_sign_test_ctx(setup, optype); + } + break; + case SM2_HW_VERF: + { + test_ctx = sm2_create_hw_verf_test_ctx(setup, optype); + } + break; + case SM2_SW_SIGN: + { + test_ctx = sm2_create_sw_sign_test_ctx(setup, optype); + } + break; + case SM2_SW_VERF: + { + test_ctx = sm2_create_sw_verf_test_ctx(setup, optype); + } + break; + + case SM2_HW_ENC: + { + test_ctx = sm2_create_hw_enc_test_ctx(setup, optype); + } + break; + case SM2_HW_DEC: + { + test_ctx = sm2_create_hw_dec_test_ctx(setup, optype); + } + break; + case SM2_SW_ENC: + { + test_ctx = sm2_create_sw_enc_test_ctx(setup, optype); + } + break; + case SM2_SW_DEC: + { + test_ctx = sm2_create_sw_dec_test_ctx(setup, optype); + } + break; + case SM2_HW_KG: + { + test_ctx = sm2_create_hw_kg_test_ctx(setup, optype); + } + break; + case SM2_SW_KG: + { + test_ctx = sm2_create_sw_kg_test_ctx(setup, optype); + } + break; + default: + break; + } + + if (test_ctx) + test_ctx->setup = setup; + + return test_ctx; +} + +static int ecc_init_test_ctx_setup(struct ecc_test_ctx_setup *setup, __u32 op_type) +{ + u32 key_bits = g_config.key_bits; + int key_size = (key_bits + 7) / 8; + u32 len; + + if (op_type == ECDH_ASYNC_GEN || op_type == ECDH_ASYNC_COMPUTE) { + setup->key_from = 1; // Designed + } else { + setup->key_from = g_config.data_from; + } + + if (setup->key_from) + HPRE_TST_PRT("Input data comes from fixed sample data\n"); + + setup->key_bits = key_bits; + + if (setup->nid == 714 || key_bits == 256) { // NID_secp256k1 + /* sm2 */ + if (op_type == SM2_SIGN || op_type == SM2_VERF || + op_type == SM2_ENC || op_type == SM2_DEC || op_type == SM2_KG || + op_type == SM2_ASYNC_SIGN || op_type == SM2_ASYNC_VERF || + op_type == SM2_ASYNC_ENC || op_type == SM2_ASYNC_DEC || op_type == SM2_ASYNC_KG) { + + setup->priv_key = sm2_priv; + setup->priv_key_size = sizeof(sm2_priv); + setup->pub_key = sm2_pubkey; + setup->pub_key_size = sizeof(sm2_pubkey); + + len = (g_config.msg_len == INVALID_LEN) ? MAX_ENC_LEN : g_config.msg_len; + setup->msg = malloc(len); + if (!setup->msg) + return -1; + memset(setup->msg, 0xFF, len); + + if (g_config.msg_type == MSG_DIGEST) { + memcpy(setup->msg, sm2_digest, sizeof(sm2_digest)); + setup->msg_size = (g_config.msg_len == INVALID_LEN) ? sizeof(sm2_digest) : g_config.msg_len; + } else { + memcpy(setup->msg, sm2_plaintext, sizeof(sm2_plaintext)); + setup->msg_size = (g_config.msg_len == INVALID_LEN) ? sizeof(sm2_plaintext) : g_config.msg_len; + } + + if (setup->msg_size > 512) { + if (setup->msg_size != 513 && setup->key_from == 1) + HPRE_TST_PRT("Sample data is fixed as 513 bytes\n"); + setup->ciphertext = sm2_ciphertext_l; + setup->ciphertext_size = sizeof(sm2_ciphertext_l); + setup->plaintext = sm2_plaintext_l; + setup->plaintext_size = sizeof(sm2_plaintext_l); + } else { + setup->ciphertext = sm2_ciphertext; + setup->ciphertext_size = sizeof(sm2_ciphertext); + setup->plaintext = sm2_plaintext; + setup->plaintext_size = sizeof(sm2_plaintext); + } + + setup->k = sm2_k; + setup->k_size = (g_config.k_len == INVALID_LEN) ? sizeof(sm2_k) : g_config.k_len; + setup->userid = sm2_id; + setup->userid_size = (g_config.id_len == INVALID_LEN) ? sizeof(sm2_id) : g_config.id_len; + setup->sign = sm2_sign_data; + setup->sign_size = sizeof(sm2_sign_data); + + } else { + setup->priv_key = ecdh_da_secp256k1; + setup->except_pub_key = ecdh_except_b_pubkey_secp256k1; + setup->pub_key = ecdh_cp_pubkey_secp256k1; + setup->share_key = ecdh_cp_sharekey_secp256k1; + setup->priv_key_size = sizeof(ecdh_da_secp256k1); + setup->except_pub_key_size = sizeof(ecdh_except_b_pubkey_secp256k1); + setup->pub_key_size = sizeof(ecdh_cp_pubkey_secp256k1); + setup->share_key_size = sizeof(ecdh_cp_sharekey_secp256k1); + + /* ecc sign */ + setup->msg = ecc_except_e_secp256k1; + setup->msg_size = sizeof(ecc_except_e_secp256k1); + setup->k = ecc_except_kinv_secp256k1; + setup->k_size = sizeof(ecc_except_kinv_secp256k1); + setup->rp = ecdh_cp_pubkey_secp256k1 + 1; + setup->rp_size = key_size; + + /* ecc verf */ + setup->sign = ecc_cp_sign_secp256k1; + setup->sign_size = sizeof(ecc_cp_sign_secp256k1); + } + } else if (setup->nid == 706 || key_bits == 128) { + setup->priv_key = ecdh_da_secp128r1; + setup->except_pub_key = ecdh_except_b_pubkey_secp128r1; + setup->pub_key = ecdh_cp_pubkey_secp128r1; + setup->share_key = ecdh_cp_sharekey_secp128r1; + setup->priv_key_size = sizeof(ecdh_da_secp128r1); + setup->except_pub_key_size = sizeof(ecdh_except_b_pubkey_secp128r1); + setup->pub_key_size = sizeof(ecdh_cp_pubkey_secp128r1); + setup->share_key_size = sizeof(ecdh_cp_sharekey_secp128r1); + + /* ecc sign */ + setup->msg = ecc_except_e_secp128r1; + setup->msg_size = sizeof(ecc_except_e_secp128r1); + setup->k = ecc_except_kinv_secp128r1; + setup->k_size = sizeof(ecc_except_kinv_secp128r1); + setup->rp = ecdh_cp_pubkey_secp128r1 + 1; + setup->rp_size = key_size; + + /* ecc verf */ + setup->sign = ecc_cp_sign_secp128r1; + setup->sign_size = sizeof(ecc_cp_sign_secp128r1); + + } else if (setup->nid == 711 || key_bits == 192) { + setup->priv_key = ecdh_da_secp192k1; + setup->except_pub_key = ecdh_except_b_pubkey_secp192k1; + setup->pub_key = ecdh_cp_pubkey_secp192k1; + setup->share_key = ecdh_cp_sharekey_secp192k1; + setup->priv_key_size = sizeof(ecdh_da_secp192k1); + setup->except_pub_key_size = sizeof(ecdh_except_b_pubkey_secp192k1); + setup->pub_key_size = sizeof(ecdh_cp_pubkey_secp192k1); + setup->share_key_size = sizeof(ecdh_cp_sharekey_secp192k1); + + /* ecc sign */ + setup->msg = ecc_except_e_secp192k1; + setup->msg_size = sizeof(ecc_except_e_secp192k1); + setup->k = ecc_except_kinv_secp192k1; + setup->k_size = sizeof(ecc_except_kinv_secp192k1); + setup->rp = ecdh_cp_pubkey_secp192k1 + 1; + setup->rp_size = key_size; + + /* ecc verf */ + setup->sign = ecc_cp_sign_secp256k1; + setup->sign_size = sizeof(ecc_cp_sign_secp256k1); + } else if (setup->nid == 712 || g_config.key_bits == 224) { + setup->priv_key = ecdh_da_secp224r1; + setup->except_pub_key = ecdh_except_b_pubkey_secp224r1; + setup->pub_key = ecdh_cp_pubkey_secp224r1; + setup->share_key = ecdh_cp_sharekey_secp224r1; + setup->priv_key_size = sizeof(ecdh_da_secp224r1); + setup->except_pub_key_size = sizeof(ecdh_except_b_pubkey_secp224r1); + setup->pub_key_size = sizeof(ecdh_cp_pubkey_secp224r1); + setup->share_key_size = sizeof(ecdh_cp_sharekey_secp224r1); + } else if (setup->nid == 929 || key_bits == 320) { + setup->priv_key = ecdh_da_secp320k1; + setup->except_pub_key = ecdh_except_b_pubkey_secp320k1; + setup->pub_key = ecdh_cp_pubkey_secp320k1; + setup->share_key = ecdh_cp_sharekey_secp320k1; + setup->priv_key_size = sizeof(ecdh_da_secp320k1); + setup->except_pub_key_size = sizeof(ecdh_except_b_pubkey_secp320k1); + setup->pub_key_size = sizeof(ecdh_cp_pubkey_secp320k1); + setup->share_key_size = sizeof(ecdh_cp_sharekey_secp320k1); + + /* ecc sign */ + setup->msg = ecc_except_e_secp320k1; + setup->msg_size = sizeof(ecc_except_e_secp320k1); + setup->k = ecc_except_kinv_secp320k1; + setup->k_size = sizeof(ecc_except_kinv_secp320k1); + setup->rp = ecdh_cp_pubkey_secp192k1 + 1; + setup->rp_size = key_size; + + /* ecc verf */ + setup->sign = ecc_cp_sign_secp256k1; + setup->sign_size = sizeof(ecc_cp_sign_secp256k1); + + } else if (setup->nid == 931 || key_bits == 384) { + setup->priv_key = ecdh_da_secp384r1; + setup->except_pub_key = ecdh_except_b_pubkey_secp384r1; + setup->pub_key = ecdh_cp_pubkey_secp384r1; + setup->share_key = ecdh_cp_sharekey_secp384r1; + setup->priv_key_size = sizeof(ecdh_da_secp384r1); + setup->except_pub_key_size = sizeof(ecdh_except_b_pubkey_secp384r1); + setup->pub_key_size = sizeof(ecdh_cp_pubkey_secp384r1); + setup->share_key_size = sizeof(ecdh_cp_sharekey_secp384r1); + + /* ecc sign */ + setup->msg = ecc_except_e_secp384r1; + setup->msg_size = sizeof(ecc_except_e_secp384r1); + setup->k = ecc_except_kinv_secp384r1; + setup->k_size = sizeof(ecc_except_kinv_secp384r1); + setup->rp = ecdh_cp_pubkey_secp384r1 + 1; + setup->rp_size = key_size; + + /* ecc verf */ + setup->sign = ecc_cp_sign_secp256k1; + setup->sign_size = sizeof(ecc_cp_sign_secp256k1); + } else if (setup->nid == 716 || key_bits == 521) { + setup->priv_key = ecdh_da_secp521r1; + setup->except_pub_key = ecdh_except_b_pubkey_secp521r1; + setup->pub_key = ecdh_cp_pubkey_secp521r1; + setup->share_key = ecdh_cp_sharekey_secp521r1; + setup->priv_key_size = sizeof(ecdh_da_secp521r1); + setup->except_pub_key_size = sizeof(ecdh_except_b_pubkey_secp521r1); + setup->pub_key_size = sizeof(ecdh_cp_pubkey_secp521r1); + setup->share_key_size = sizeof(ecdh_cp_sharekey_secp521r1); + + /* ecc sign */ + setup->msg = ecc_except_e_secp521r1; + setup->msg_size = sizeof(ecc_except_e_secp521r1); + setup->k = ecc_except_kinv_secp521r1; + setup->k_size = sizeof(ecc_except_kinv_secp521r1); + setup->rp = ecdh_cp_pubkey_secp521r1 + 1; + setup->rp_size = key_size; + + /* ecc verf */ + setup->sign = ecc_cp_sign_secp256k1; + setup->sign_size = sizeof(ecc_cp_sign_secp256k1); + + } else { + HPRE_TST_PRT("init test sess setup not find this bits %d or nid %d\n", + key_bits, setup->nid); + return -1; + } + + return 0; +} + + +static int ecxdh_generate_key(void *test_ctx, void *tag) +{ + struct ecc_test_ctx *t_c = test_ctx; + int ret = 0; + + if (t_c->setup.op_type == ECDH_SW_GENERATE) { +#if 0 // x25519/x448, add later + if (t_c->is_x25519_x448){ + EVP_PKEY_METHOD *pmeth; + EVP_PKEY_CTX pkey_ctx; + size_t key_sz; + EVP_PKEY pkey; + ECX_KEY ecx; + + memset(&pkey_ctx, 0, sizeof(EVP_PKEY_CTX)); + memset(&pkey, 0, sizeof(EVP_PKEY)); + memset(&ecx, 0, sizeof(ECX_KEY)); + + if (t_c->key_size == 32) { // x25519 + pmeth = EVP_PKEY_meth_find(EVP_PKEY_X25519); + ecx.privkey = x25519_aprikey; + memcpy(ecx.pubkey, x25519_x_param, 32); + } else { // if (t_c->key_size == 56) { // x448 + pmeth = EVP_PKEY_meth_find(EVP_PKEY_X448); + ecx.privkey = x448_aprikey; + memcpy(ecx.pubkey, x448_x_param, 56); + } + pkey.pkey.ecx = &ecx; + pkey_ctx.pkey = &pkey; + pkey_ctx.peerkey = &pkey; + + uint8_t *out_pub_key = calloc(t_c->key_size, sizeof(char)); + + ret = pmeth->derive(&pkey_ctx, out_pub_key, &key_sz); + if (ret == 0) { + HPRE_TST_PRT("%s: pmeth->derive err.\n", __func__); + return -1; + } + #if 0 + int i; + for (i = 0; i < t_c->key_size; i++) { + if (i % 12 == 0) + printf("\n"); + printf("0x%x, ", out_pub_key[i]); + }printf("\n"); + #endif + free(out_pub_key); + } else +#endif + { + EC_KEY *ec_key = t_c->priv; + + if (!EC_KEY_generate_key(ec_key)) { + HPRE_TST_PRT("EC_KEY_generate_key fail!\n"); + return -1; + } + //#ifdef DEBUG + ECParameters_print_fp(stdout, ec_key); + EC_KEY_print_fp(stdout, ec_key, 0); + //#endif + } + } else { + struct wd_ecc_req *req = t_c->req; + handle_t sess = (handle_t)t_c->priv; +try_again: + if (tag) + ret = wd_do_ecc_async(sess, req); + else + ret = wd_do_ecc_sync(sess, req); + if (ret == -WD_EBUSY) { + usleep(100); + goto try_again; + } else if (ret) { + HPRE_TST_PRT("wd_do_ecc fail!\n"); + return -1; + } + } + + return 0; +} + + +static int ecxdh_compute_key(void *test_ctx, void *tag) +{ + struct ecc_test_ctx *t_c = test_ctx; + int ret = 0; + + if (t_c->setup.op_type == ECDH_SW_COMPUTE) { +#if 0 + if (t_c->is_x25519_x448){ + EVP_PKEY_METHOD *pmeth; + EVP_PKEY_CTX pkey_ctx; + EVP_PKEY pkey; + ECX_KEY ecx; + size_t key_sz; + int ret; + + memset(&pkey_ctx, 0, sizeof(EVP_PKEY_CTX)); + memset(&pkey, 0, sizeof(EVP_PKEY)); + memset(&ecx, 0, sizeof(ECX_KEY)); + + if (t_c->key_size == 32) { // x25519 + pmeth = EVP_PKEY_meth_find(EVP_PKEY_X25519); + ecx.privkey = x25519_aprikey; + memcpy(ecx.pubkey, x25519_bpubkey, 32); + } else { // if (t_c->key_size == 56) { // x448 + pmeth = EVP_PKEY_meth_find(EVP_PKEY_X448); + ecx.privkey = x448_aprikey; + memcpy(ecx.pubkey, x448_bpubkey, 56); + } + pkey.pkey.ecx = &ecx; + pkey_ctx.pkey = &pkey; + pkey_ctx.peerkey = &pkey; + + uint8_t *out_shared_key = calloc(t_c->key_size, sizeof(char)); + + ret = pmeth->derive(&pkey_ctx, out_shared_key, &key_sz); + if (ret <= 0) { + HPRE_TST_PRT("%s: pmeth->derive err.\n", __func__); + return -1; + } + #if 0 + int i; + for (i = 0; i < t_c->key_size; i++) { + if (i % 12 == 0) + printf("\n"); + printf("0x%x, ", out_shared_key[i]); + }printf("\n"); + #endif + free(out_shared_key); + } else { +#endif + struct ecdh_sw_opdata *req = t_c->req; + EC_KEY *ec_key = t_c->priv; + ret = ECDH_compute_key(req->share_key, req->share_key_size, + req->except_pub_key, ec_key, NULL); + if (ret <= 0) { + HPRE_TST_PRT("ECDH_compute_key fail!\n"); + return -1; + } + req->share_key_size = ret; + //} +#ifdef DEBUG + //ECParameters_print_fp(stdout, ec_key); + //print_data(req->share_key, ret, "openssl share key"); + +#endif + } else { + struct wd_ecc_req *req = t_c->req; + handle_t sess = (handle_t)t_c->priv; +try_again: + + if (tag) + ret = wd_do_ecc_async(sess, req); + else + ret = wd_do_ecc_sync(sess, req); + + if (ret == -WD_EBUSY) { + usleep(100); + goto try_again; + } else if (ret) { + HPRE_TST_PRT("wd_do_ecc fail!\n"); + return -1; + } +#ifdef DEBUG + //print_data(req->pri, req->pri_bytes,"hpre share key"); +#endif + } + + return 0; +} + +int ecdsa_sign(void *test_ctx, void *tag) +{ + struct ecc_test_ctx *t_c = test_ctx; + int ret = 0; + + if (t_c->setup.op_type == ECC_SW_SIGN) { + EC_KEY *ec_key = t_c->priv; + struct ecdh_sw_opdata *opdata = t_c->req; + + if (!ECDSA_sign_ex(0, opdata->except_e, opdata->except_e_size, + opdata->sign, &opdata->sign_size, opdata->except_kinv, + opdata->except_rp, ec_key)) { + HPRE_TST_PRT("ECDSA_sign_ex fail!\n"); + return -1; + } + +#ifdef DEBUG + print_data(opdata->sign, opdata->sign_size, "openssl sign"); + ECParameters_print_fp(stdout, ec_key); + EC_KEY_print_fp(stdout, ec_key, 0); +#endif + + } else { + struct wd_ecc_req *opdata = t_c->req; + handle_t sess = (handle_t)t_c->priv; +try_again: + if (tag) + ret = wd_do_ecc_async(sess, opdata); + else + ret = wd_do_ecc_sync(sess, opdata); + if (ret == -WD_EBUSY) { + usleep(100); + goto try_again; + } else if (ret) { + HPRE_TST_PRT("wd_do_ecc fail!\n"); + return -1; + } + + if (tag) + return 0; +#ifdef DEBUG + struct wd_dtb *r, *s; + wd_ecdsa_get_sign_out_params(opdata->dst, &r, &s); + print_data(r->data, r->dsize, "hpre r"); + print_data(s->data, s->dsize, "hpre s"); +#endif + } + + return 0; +} + +int ecdsa_verf(void *test_ctx, void *tag) +{ + struct ecc_test_ctx *t_c = test_ctx; + int ret = 0; + + if (t_c->setup.op_type == ECC_SW_VERF) { + EC_KEY *ec_key = t_c->priv; + struct ecdh_sw_opdata *opdata = t_c->req; + + ret = ECDSA_verify(0, opdata->except_e, opdata->except_e_size, + opdata->sign, opdata->sign_size, ec_key); + if (ret != 1) { + HPRE_TST_PRT("ECDSA_verify fail = %d!\n", ret); + return -1; + } + +#ifdef DEBUG + ECParameters_print_fp(stdout, ec_key); + EC_KEY_print_fp(stdout, ec_key, 0); +#endif + + } else { + struct wd_ecc_req *opdata = t_c->req; + handle_t sess = (handle_t)t_c->priv; +try_again: + if (tag) + ret = wd_do_ecc_async(sess, opdata); + else + ret = wd_do_ecc_sync(sess, opdata); + if (ret == -WD_EBUSY) { + usleep(100); + goto try_again; + } else if (ret) { + //HPRE_TST_PRT("wd_do_ecc fail!\n"); + //return -1; + } + +#ifdef DEBUG + printf("hpre verf = %d\n", opdata->status); +#endif + } + + return 0; +} + +static int sm2_sign(void *test_ctx, void *pTag) +{ + struct ecc_test_ctx *t_c = test_ctx; + int ret = 0; + + if (t_c->setup.op_type == ECC_SW_SIGN) { + EC_KEY *ec_key = t_c->priv; + struct ecdh_sw_opdata *opdata = t_c->req; + + if (!ECDSA_sign_ex(1, opdata->except_e, opdata->except_e_size, + opdata->sign, &opdata->sign_size, opdata->except_kinv, + opdata->except_rp, ec_key)) { + HPRE_TST_PRT("ECDSA_sign_ex fail!\n"); + return -1; + } + +#ifdef DEBUG + print_data(opdata->sign, opdata->sign_size, "openssl sign"); + ECParameters_print_fp(stdout, ec_key); + EC_KEY_print_fp(stdout, ec_key, 0); +#endif + + } else { + struct wd_ecc_req *req = t_c->req; + handle_t sess = t_c->setup.sess; +try_again: + if (pTag) + ret = wd_do_ecc_async(sess, req); + else + ret = wd_do_ecc_sync(sess, req); + if (ret == -WD_EBUSY) { + usleep(100); + goto try_again; + } else if (ret) { + HPRE_TST_PRT("wd_do_ecc fail, ret = %d!\n", ret); + return -1; + } + +#ifdef DEBUG + struct wd_dtb *r, *s; + wd_sm2_get_sign_out_params(req->dst, &r, &s); + print_data(r->data, r->dsize, "hpre r"); + print_data(s->data, s->dsize, "hpre s"); +#endif + } + + return 0; +} + +static int sm2_verf(void *test_ctx, void *pTag) +{ + struct ecc_test_ctx *t_c = test_ctx; + int ret = 0; + + if (t_c->setup.op_type == ECC_SW_VERF) { + } else { + struct wd_ecc_req *req = t_c->req; + handle_t sess = t_c->setup.sess; +try_again: + if (pTag) + ret = wd_do_ecc_async(sess, req); + else + ret = wd_do_ecc_sync(sess, req); + if (ret == -WD_EBUSY) { + usleep(100); + goto try_again; + } else if (ret) { + HPRE_TST_PRT("wd_do_ecc fail, ret = %d!\n", ret); + return -1; + } + +#ifdef DEBUG + printf("hpre verf = %d\n", req->status); +#endif + } + + return 0; +} + +static int sm2_enc(void *test_ctx, void *pTag) +{ + struct ecc_test_ctx *t_c = test_ctx; + int ret = 0; + + if (t_c->setup.op_type == SM2_SW_ENC) { + } else { + struct wd_ecc_req *req = t_c->req; + handle_t sess = t_c->setup.sess; +try_again: + if (pTag) + ret = wd_do_ecc_async(sess, req); + else + ret = wd_do_ecc_sync(sess, req); + if (ret == -WD_EBUSY) { + usleep(100); + goto try_again; + } else if (ret) { + HPRE_TST_PRT("wd_do_ecc fail, ret = %d!\n", ret); + return -1; + } + +#ifdef DEBUG + printf("hpre enc = %d\n", req->status); +#endif + } + + return 0; +} + +static int sm2_dec(void *test_ctx, void *pTag) +{ + struct ecc_test_ctx *t_c = test_ctx; + int ret = 0; + + if (t_c->setup.op_type == SM2_SW_ENC) { + } else { + struct wd_ecc_req *req = t_c->req; + handle_t sess = t_c->setup.sess; +try_again: + if (pTag) + ret = wd_do_ecc_async(sess, req); + else + ret = wd_do_ecc_sync(sess, req); + if (ret == -WD_EBUSY) { + usleep(100); + goto try_again; + } else if (ret) { + HPRE_TST_PRT("wd_do_ecc fail, ret = %d!\n", ret); + return -1; + } + +#ifdef DEBUG + printf("hpre dec = %d\n", req->status); +#endif + } + + return 0; +} + +static int sm2_kg(void *test_ctx, void *pTag) +{ + struct ecc_test_ctx *t_c = test_ctx; + int ret = 0; + + if (t_c->setup.op_type == SM2_SW_ENC) { + } else { + struct wd_ecc_req *req = t_c->req; + handle_t sess = t_c->setup.sess; +try_again: + if (pTag) + ret = wd_do_ecc_async(sess, req); + else + ret = wd_do_ecc_sync(sess, req); + if (ret == -WD_EBUSY) { + usleep(100); + goto try_again; + } else if (ret) { + HPRE_TST_PRT("wd_do_ecc fail, ret = %d!\n", ret); + return -1; + } + +#ifdef DEBUG + printf("hpre kg = %d\n", req->status); +#endif + } + + return 0; +} + +int ecc_point1buf(struct wd_ecc_point *in, int ksz, void *buf, int bsz) +{ + struct wd_dtb *x; + int ret = 0; + + if (!buf || !in) + return -1; + + x = &in->x; + + ret = x->dsize; + if (ret > bsz) + return -1; + + memcpy(buf, x->data, x->dsize); + + return ret; +} + +int ecc_point2buf(struct wd_ecc_point *in, int ksz, void *buf, int bsz) +{ + struct wd_dtb *x, *y; + int ret = 0; + + if (!buf || !in) + return -1; + + x = &in->x; + y = &in->y; + + ret = x->dsize + y->dsize; + if (ret > bsz) + return -1; +#ifdef DEBUG + //print_data(x->data, x->dsize, "x"); + //print_data(y->data, y->dsize, "y"); +#endif + memcpy(buf, x->data, x->dsize); + memcpy(buf + x->dsize, y->data, y->dsize); + + return ret; +} + +static int ecdsa_sign_result_check(struct ecc_test_ctx *test_ctx, __u8 is_async) +{ + return 0; +} + +static int sm2_sign_result_check(struct ecc_test_ctx *test_ctx, __u8 is_async) +{ + struct wd_ecc_req *req = test_ctx->req; + struct wd_dtb prk, pbk; + EVP_MD_CTX *md_ctx; + EVP_PKEY_CTX *pctx; + EVP_PKEY *p_key; + EC_KEY *ec_key; + struct wd_dtb *r, *s; + char buff[MAX_SIGN_LEN] = {0}; + size_t len; + int ret; + + wd_sm2_get_sign_out_params(req->dst, &r, &s); + memcpy(buff, r->data, s->dsize); + crypto_bin_to_hpre_bin(buff, r->data, r->bsize, r->dsize); + memcpy(buff + 32, s->data, s->dsize); + crypto_bin_to_hpre_bin(buff + 32, s->data, s->bsize, s->dsize); + + if (g_config.rand_type != RAND_PARAM && !test_ctx->setup.key_from) { + pbk.data = (void *)test_ctx->setup.pub_key; + pbk.dsize = test_ctx->setup.pub_key_size; + prk.data = (void *)test_ctx->setup.priv_key; + prk.dsize = test_ctx->setup.priv_key_size; + md_ctx = ecc_create_openssl_handle(&prk, &pbk); + if (!md_ctx) + return -1; + pctx = EVP_MD_CTX_pkey_ctx(md_ctx); + p_key = EVP_PKEY_CTX_get0_pkey(pctx); + ec_key = EVP_PKEY_get0(p_key); + + /* openssl verf check */ + len = hpre_bin_sign_to_evp(buff, buff, 32); + if (g_config.msg_type == MSG_DIGEST) { + ret = EVP_PKEY_verify_init(pctx); + if (ret != 1) { + HPRE_TST_PRT("EVP_PKEY_verify_init fail, ret = %d!\n", ret); + return -1; + } + + ret = EVP_PKEY_verify(pctx, (void *)buff, len, + test_ctx->setup.msg, test_ctx->setup.msg_size); + } else { + EVP_PKEY_CTX_set1_id(pctx, test_ctx->setup.userid, + test_ctx->setup.userid_size); + EVP_DigestVerifyInit(md_ctx, NULL, get_digest_handle(), NULL, p_key); + EVP_DigestVerifyUpdate(md_ctx, test_ctx->setup.msg, test_ctx->setup.msg_size); + ret = EVP_DigestVerifyFinal(md_ctx, (void *)buff, len); + } + if (ret != 1) { + HPRE_TST_PRT("openssl verf fail, ret = %d!\n", ret); + print_data(buff, len, "hpre sign"); + print_data((void *)test_ctx->setup.msg, test_ctx->setup.msg_size, "msg"); + ECParameters_print_fp(stdout, ec_key); + EC_KEY_print_fp(stdout, ec_key, 0); + return -1; + } + + ecc_del_openssl_handle(md_ctx); + #ifdef DEBUG + HPRE_TST_PRT("sm2 verf pass!\n"); + #endif + + } else { + if (memcmp(test_ctx->cp_sign, buff, test_ctx->cp_sign_size)) { + HPRE_TST_PRT("sm2 op %d mismatch!\n", test_ctx->setup.op_type); + print_data(buff, 64, "hpre out"); + print_data(test_ctx->cp_sign, test_ctx->cp_sign_size, "openssl out"); + return -1; + } + } + + return 0; +} + +static int sm2_enc_result_check(struct ecc_test_ctx *test_ctx, __u8 is_async) +{ + struct wd_ecc_req *req = test_ctx->req; + EVP_MD_CTX *md_ctx; + EVP_PKEY_CTX *pctx; + struct wd_ecc_point *c1 = NULL; + struct wd_dtb *c2 = NULL, *c3 = NULL; + struct wd_dtb pbk, prk; + char *buf, *ptext; + size_t lens = 0; + __u32 evp_len; + int ret; + + buf = malloc(MAX_ENC_LEN); + if (!buf) { + HPRE_TST_PRT("malloc buf failed\n"); + return -1; + } + + ptext = malloc(MAX_ENC_LEN); + if (!buf) { + HPRE_TST_PRT("malloc ptext failed\n"); + return -1; + } + + memset(buf, 0, MAX_ENC_LEN); + memset(ptext, 0, MAX_ENC_LEN); + lens = MAX_ENC_LEN; + wd_sm2_get_enc_out_params(req->dst, &c1, &c2, &c3); + if (g_config.rand_type != RAND_PARAM && !test_ctx->setup.key_from) { + pbk.data = (void *)test_ctx->setup.pub_key; + pbk.dsize = test_ctx->setup.pub_key_size; + prk.data = (void *)test_ctx->setup.priv_key; + prk.dsize = test_ctx->setup.priv_key_size; + md_ctx = ecc_create_openssl_handle(&prk, &pbk); + if (!md_ctx) + return -1; + pctx = EVP_MD_CTX_pkey_ctx(md_ctx); + EVP_PKEY_decrypt_init(pctx); + EVP_PKEY_CTX_ctrl(pctx, -1, -1, EVP_PKEY_CTRL_MD, -1, (void *)get_digest_handle()); + + /* openssl check */ + crypto_bin_to_hpre_bin(c1->x.data, c1->x.data, c1->x.bsize, c1->x.dsize); + crypto_bin_to_hpre_bin(c1->y.data, c1->y.data, c1->y.bsize, c1->y.dsize); + evp_len = sm2_enc_in_bin_to_evp(buf, c1->x.data, c2->dsize, 32, c3->dsize); + ret = EVP_PKEY_decrypt(pctx, (void *)ptext, &lens, (void *)buf, evp_len); + if (ret != 1) { + HPRE_TST_PRT("EVP_PKEY_decrypt failed, ret = %d\n", ret); + return -1; + } + + ecc_del_openssl_handle(md_ctx); + + if (lens != test_ctx->setup.msg_size || + memcmp(test_ctx->setup.msg, ptext, lens)){ + HPRE_TST_PRT("openssl decrypt mismatch\n"); + print_data(ptext, lens, "openssl dec out"); + return -1; + } + } else { + memcpy(buf, c1->x.data, c1->x.dsize); + crypto_bin_to_hpre_bin(buf, c1->x.data, c1->x.bsize, c1->x.dsize); + memcpy(buf + 32, c1->y.data, c1->y.dsize); + crypto_bin_to_hpre_bin(buf + 32, c1->y.data, c1->y.bsize, c1->y.dsize); + memcpy(buf + 32 * 2, c3->data, c3->dsize); + memcpy(buf + 32 * 2 + c3->dsize, c2->data, c2->dsize); + lens = 32 * 2 + c2->dsize + c3->dsize; + if (lens != test_ctx->cp_enc_size || + memcmp(test_ctx->cp_enc, buf, test_ctx->cp_enc_size)){ + HPRE_TST_PRT("sm2 op %d mismatch\n", test_ctx->setup.op_type); + print_data(c1->x.data, c1->x.dsize, "c1 x"); + print_data(c1->y.data, c1->y.dsize, "c1 y"); + print_data(c3->data, c3->dsize, "c3"); + print_data(c2->data, c2->dsize, "c2"); + print_data(buf, lens, "hpre out"); + print_data(test_ctx->cp_enc, test_ctx->cp_enc_size, "openssl out"); + return -1; + } + } + + free(buf); + free(ptext); + + return 0; +} + +static int sm2_dec_result_check(struct ecc_test_ctx *test_ctx, __u8 is_async) +{ + struct wd_ecc_req *req = test_ctx->req; + struct wd_dtb *m = NULL; + + wd_sm2_get_dec_out_params(req->dst, &m); + + if (m->dsize != test_ctx->cp_enc_size || + memcmp(test_ctx->cp_enc, m->data, m->dsize)){ + HPRE_TST_PRT("sm2 op %d mismatch\n", test_ctx->setup.op_type); + print_data(m->data, m->dsize, "hpre out"); + print_data((void *)test_ctx->cp_enc, + test_ctx->cp_enc_size, "openssl out"); + return -1; + } + + return 0; +} + +static int sm2_kg_result_check(struct ecc_test_ctx *test_ctx, __u8 is_async) +{ + struct ecc_test_ctx_setup *setup = &test_ctx->setup; + EVP_MD_CTX *md_ctx; + struct wd_ecc_req *req = test_ctx->req; + struct wd_dtb *privkey = NULL; + struct wd_ecc_point *pubkey = NULL; + struct wd_dtb pbk, prk; + EVP_PKEY_CTX *pctx; + char buff[100] = {0x4}; + size_t sig_len = 100; + int ret; + + wd_sm2_get_kg_out_params(req->dst, &privkey, &pubkey); + + crypto_bin_to_hpre_bin(pubkey->x.data, pubkey->x.data, + pubkey->x.bsize, pubkey->x.dsize); + crypto_bin_to_hpre_bin(pubkey->y.data, pubkey->y.data, + pubkey->y.bsize, pubkey->y.dsize); + memcpy(&buff[1], pubkey->x.data, 64); + pbk.data = buff; + pbk.dsize = 65; + prk.data = privkey->data; + prk.dsize = privkey->dsize; + + md_ctx = ecc_create_openssl_handle(&prk, &pbk); + if (!md_ctx) + return -1; + pctx = EVP_MD_CTX_pkey_ctx(md_ctx); + ret = EVP_PKEY_sign_init(pctx); + if (ret != 1) { + HPRE_TST_PRT("EVP_PKEY_sign_init failed, ret = %d\n", ret); + ret = -1; + goto del_openssl_handle; + } + + ret = EVP_PKEY_sign(pctx, (void *)buff, &sig_len, setup->msg, + (size_t)setup->msg_size); + if (ret != 1) { + HPRE_TST_PRT("EVP_PKEY_sign failed, ret = %d\n", ret); + ret = -1; + goto del_openssl_handle; + } + + ret = EVP_PKEY_verify_init(pctx); + if (ret != 1) { + HPRE_TST_PRT("EVP_PKEY_verify_init failed, ret = %d\n", ret); + ret = -1; + goto del_openssl_handle; + } + + ret = EVP_PKEY_verify(pctx, (void *)buff, sig_len, (void *)setup->msg, + (size_t)setup->msg_size); + if (ret != 1) { + HPRE_TST_PRT("EVP_PKEY_verify failed, ret = %d\n", ret); + ret = -1; + goto del_openssl_handle; + } + + ret = 0; + +del_openssl_handle: + ecc_del_openssl_handle(md_ctx); + + return ret; +} + +static int ecxdh_result_check(struct ecc_test_ctx *test_ctx, __u8 is_async) +{ + struct wd_ecc_req *req = test_ctx->req; + unsigned char *cp_key; + u32 cp_size; + u32 key_size = (wd_ecc_get_key_bits(test_ctx->setup.sess) + 7) / 8; + void *o_buf; + int ret; + struct wd_ecc_point *key = NULL; + BIGNUM *tmp; + __u32 out_sz; + + if (test_ctx->setup.op_type == ECDH_HW_GENERATE) { + cp_key = test_ctx->cp_pub_key; + cp_size = test_ctx->cp_pub_key_size; + } else { + cp_key = test_ctx->cp_share_key; + cp_size = test_ctx->cp_share_key_size; + } + + wd_ecxdh_get_out_params(req->dst, &key); + if (test_ctx->is_x25519_x448) + o_buf = malloc(key_size); + else + o_buf = malloc(key_size * 2); + + if (!o_buf) { + HPRE_TST_PRT("malloc fail!\n"); + return -1; + } + + if (test_ctx->setup.op_type == ECDH_HW_GENERATE) { + if (test_ctx->is_x25519_x448) { + ret = ecc_point1buf(key, key_size, o_buf, key_size); + if (ret < 0) { + HPRE_TST_PRT("ecc_point1buf fail!\n"); + free(o_buf); + return -1; + } + } else { + ret = ecc_point2buf(key, key_size, o_buf, key_size * 2); + if (ret < 0) { + HPRE_TST_PRT("ecc_point2buf fail!\n"); + free(o_buf); + return -1; + } + } + out_sz = ret; + tmp = BN_bin2bn(cp_key, key_size, NULL); + ret = BN_bn2bin(tmp, cp_key); + cp_size = ret; + BN_free(tmp); + if (!test_ctx->is_x25519_x448) { + tmp = BN_bin2bn(cp_key + key_size, key_size, NULL); + ret = BN_bn2bin(tmp, cp_key + ret); + cp_size += ret; + BN_free(tmp); + } + + } else { + ret = key->x.dsize; + out_sz = ret; + memcpy(o_buf, key->x.data, ret); + tmp = BN_bin2bn(cp_key, key_size, NULL); + ret = BN_bn2bin(tmp, cp_key); + cp_size = ret; + BN_free(tmp); + } + + if (out_sz != cp_size || memcmp(cp_key, o_buf, cp_size)) { + HPRE_TST_PRT("ecdh op %d mismatch!\n", test_ctx->setup.op_type); + +//#ifdef DEBUG + struct wd_ecc_key *ecc_key; + struct wd_dtb *p = NULL; + + ecc_key = wd_ecc_get_key(test_ctx->setup.sess); + wd_ecc_get_prikey_params(ecc_key, &p, NULL, NULL, NULL, NULL, NULL); + + print_data(p->data, ECC_PRIKEY_SZ(p->bsize), "prikey"); + if (test_ctx->setup.op_type == ECDH_HW_GENERATE) + print_data(test_ctx->cp_pub_key, test_ctx->cp_pub_key_size, "cp_pub_key"); + else + print_data(test_ctx->cp_share_key, test_ctx->cp_share_key_size, "cp_share_key"); + print_data(o_buf, out_sz, "hpre out"); + print_data(cp_key, cp_size, "openssl out"); +//#endif + free(o_buf); + return -1; + } + free(o_buf); + + return 0; +} + +static int ecc_result_check(struct ecc_test_ctx *test_ctx, __u8 is_async) +{ + struct wd_ecc_req *req = test_ctx->req; + int ret = 0; + + if (!g_config.check) + return 0; + + if (test_ctx->setup.op_type == ECDH_HW_GENERATE || + test_ctx->setup.op_type == ECDH_HW_COMPUTE) { + ret = ecxdh_result_check(test_ctx, is_async); + } else if (test_ctx->setup.op_type == ECC_HW_SIGN || test_ctx->setup.op_type == SM2_HW_VERF) { + ret = ecdsa_sign_result_check(test_ctx, is_async); + } else if (test_ctx->setup.op_type == ECC_HW_VERF) { + if (req->status != 0) { + HPRE_TST_PRT("hpre verf faild = %d!\n", req->status); + return -1; + } + } else if (test_ctx->setup.op_type == SM2_HW_SIGN) { + ret = sm2_sign_result_check(test_ctx, is_async); + } else if (test_ctx->setup.op_type == SM2_HW_ENC) { + ret = sm2_enc_result_check(test_ctx, is_async); + } else if (test_ctx->setup.op_type == SM2_HW_DEC) { + ret = sm2_dec_result_check(test_ctx, is_async); + } else if (test_ctx->setup.op_type == SM2_HW_KG) { + ret = sm2_kg_result_check(test_ctx, is_async); + } else {} + + return ret; +} + +static void _ecc_perf_cb(void *req_t) +{ + struct wd_ecc_req *req = req_t; + struct dh_user_tag_info* pSwData = (struct dh_user_tag_info*)req->cb_param; + struct test_hpre_pthread_dt *thread_data = pSwData->thread_data; + struct ecc_test_ctx *test_ctx = pSwData->test_ctx; + + thread_data->recv_task_num++; + ecc_del_test_ctx(test_ctx); + free(pSwData); +} + +static void _ecc_cb(void *req_t) +{ + struct wd_ecc_req *req = req_t; + struct dh_user_tag_info* pSwData = (struct dh_user_tag_info*)req->cb_param; + struct timeval start_tval, end_tval; + int pid, threadId; + float time, speed; + int ret; + static int failTimes = 0; + struct ecc_test_ctx *test_ctx = pSwData->test_ctx; + struct test_hpre_pthread_dt *thread_data = pSwData->thread_data; + + start_tval = thread_data->start_tval; + pid = pSwData->pid; + threadId = pSwData->thread_id; + + thread_data->recv_task_num++; + + if (req->status != WD_SUCCESS) { + HPRE_TST_PRT("Proc-%d, %d-TD %s %dtimes fail!, status 0x%02x\n", + pid, threadId, ecc_op_str[test_ctx->setup.op_type], + thread_data->send_task_num, req->status); + goto err; + } + + if (g_config.check) { + ret = ecc_result_check(test_ctx, 1); + if (ret) { + failTimes++; + HPRE_TST_PRT("TD-%d:%s result mismatching!\n", + threadId, ecc_op_str[test_ctx->setup.op_type]); + } + } + + gettimeofday(&end_tval, NULL); + if (is_allow_print(thread_data->send_task_num, DH_ASYNC_GEN, 1)) { + time = (end_tval.tv_sec - start_tval.tv_sec) * 1000000 + + (end_tval.tv_usec - start_tval.tv_usec); + speed = 1 / (time / thread_data->send_task_num) * 1000 * 1000; + HPRE_TST_PRT("Proc-%d, %d-TD %s %dtimes,%f us, %0.3fps, fail %dtimes(all TD)\n", + pid, threadId, ecc_op_str[test_ctx->setup.op_type], + thread_data->send_task_num, time, speed, failTimes); + } + +err: + ecc_del_test_ctx(test_ctx); + if (pSwData) + free(pSwData); +} + +void fill_ecc_param_of_curve(struct wd_ecc_curve *param) +{ + __u32 key_bits = g_config.key_bits; + __u32 key_size = (key_bits + 7) / 8; + + if (g_config.key_bits == 128) { + param->a.data = ecdh_a_secp128r1; + param->b.data = ecdh_b_secp128r1; + param->p.data = ecdh_p_secp128r1; + param->n.data = ecdh_n_secp128r1; + param->g.x.data = ecdh_g_secp128r1; + param->g.y.data = ecdh_g_secp128r1 + key_size; + } else if (key_bits == 192) { + param->a.data = ecdh_a_secp192k1; + param->b.data = ecdh_b_secp192k1; + param->p.data = ecdh_p_secp192k1; + param->n.data = ecdh_n_secp192k1; + param->g.x.data = ecdh_g_secp192k1; + param->g.y.data = ecdh_g_secp192k1 + key_size; + } else if (g_config.key_bits == 224) { + param->a.data = ecdh_a_secp224r1; + param->b.data = ecdh_b_secp224r1; + param->p.data = ecdh_p_secp224r1; + param->n.data = ecdh_n_secp224r1; + param->g.x.data = ecdh_g_secp224r1; + param->g.y.data = ecdh_g_secp224r1 + key_size; + } else if (key_bits == 256) { + param->a.data = ecdh_a_secp256k1; + param->b.data = ecdh_b_secp256k1; + param->p.data = ecdh_p_secp256k1; + param->n.data = ecdh_n_secp256k1; + param->g.x.data = ecdh_g_secp256k1; + param->g.y.data = ecdh_g_secp256k1 + key_size; + } else if (key_bits == 320) { + param->a.data = ecdh_a_secp320k1; + param->b.data = ecdh_b_secp320k1; + param->p.data = ecdh_p_secp320k1; + param->n.data = ecdh_n_secp320k1; + param->g.x.data = ecdh_g_secp320k1; + param->g.y.data = ecdh_g_secp320k1 + key_size; + } else if (g_config.key_bits == 384) { + param->a.data = ecdh_a_secp384r1; + param->b.data = ecdh_b_secp384r1; + param->p.data = ecdh_p_secp384r1; + param->n.data = ecdh_n_secp384r1; + param->g.x.data = ecdh_g_secp384r1; + param->g.y.data = ecdh_g_secp384r1 + key_size; + } else if (key_bits == 521) { + param->a.data = ecdh_a_secp521r1; + param->b.data = ecdh_b_secp521r1; + param->p.data = ecdh_p_secp521r1; + param->n.data = ecdh_n_secp521r1; + param->g.x.data = ecdh_g_secp521r1; + param->g.y.data = ecdh_g_secp521r1 + key_size; + } else { + HPRE_TST_PRT("key_bits %d not find\n", key_bits); + return; + } + + param->a.bsize = key_size; + param->a.dsize = key_size; + param->b.bsize = key_size; + param->b.dsize = key_size; + param->p.bsize = key_size; + param->p.dsize = key_size; + param->n.bsize = key_size; + param->n.dsize = key_size; + param->g.x.bsize = key_size; + param->g.x.dsize = key_size; + param->g.y.bsize = key_size; + param->g.y.dsize = key_size; +} + +static void *_ecc_sys_test_thread(void *data) +{ + struct test_hpre_pthread_dt *pdata = data; + struct dh_user_tag_info *pTag = NULL; + struct ecc_test_ctx *test_ctx; + struct ecc_test_ctx_setup setup; + struct timeval cur_tval; + enum alg_op_type opType; + float time_used, speed = 0.0; + int thread_num; + cpu_set_t mask; + int pid = getpid(); + int thread_id = (int)syscall(__NR_gettid); + int ret, cpuid; + handle_t sess = 0llu; + struct wd_ecc_sess_setup sess_setup; + struct wd_ecc_curve param; + struct wd_dtb prk, pbk_1; + struct wd_ecc_point pbk; + struct wd_ecc_req *req; + u32 key_size = (g_config.key_bits + 7) >> 3; + + CPU_ZERO(&mask); + cpuid = pdata->cpu_id; + opType = pdata->op_type; + thread_num = pdata->thread_num; + + memset(&setup, 0, sizeof(setup)); + if (g_config.perf_test && (!g_config.times && !g_config.seconds)) { + HPRE_TST_PRT("g_config.times or g_config.seconds err\n"); + return NULL; + } + + CPU_SET(cpuid, &mask); + if (cpuid) { + ret = pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask); + if (ret < 0) { + HPRE_TST_PRT("Proc-%d, thrd-%d:set affinity fail!\n", + pid, thread_id); + return NULL; + } + HPRE_TST_PRT("Proc-%d, thrd-%d bind to cpu-%d!\n", + pid, thread_id, cpuid); + } + + if (strcmp(g_config.curve, "") && !(!strncmp(g_config.op, "x448", 4) || !strncmp(g_config.op, "x25519", 5))) { + ret = get_ecc_nid(g_config.curve, &setup.nid, &setup.curve_id); + if (ret < 0) { + HPRE_TST_PRT("ecc sys test not find curve!\n"); + return NULL; + } + } + + if (!g_config.soft_test) { + memset(&sess_setup, 0, sizeof(sess_setup)); + if (!(!strncmp(g_config.op, "x448", 4) || + !strncmp(g_config.op, "x25519", 5) || + !strncmp(g_config.op, "sm2", 3))) { + if (!strcmp(g_config.curve, "")) { + sess_setup.cv.type = WD_CV_CFG_PARAM; + fill_ecc_param_of_curve(¶m); + sess_setup.cv.cfg.pparam = ¶m; + } else { + sess_setup.cv.type = WD_CV_CFG_ID; + sess_setup.cv.cfg.id = setup.curve_id; + } + } + + sess_setup.key_bits = g_config.key_bits; + + if (g_config.rand_type == RAND_CB) + sess_setup.rand.cb = hpre_get_rand; + if (!strncmp(g_config.op, "sm2", 3)) + sess_setup.alg = "sm2"; + else if (!strncmp(g_config.op, "ecdh", 4)) + sess_setup.alg = "ecdh"; + else if (!strncmp(g_config.op, "ecdsa", 5)) + sess_setup.alg = "ecdsa"; + + if (g_config.hash_type != HASH_NON) { + sess_setup.hash.cb = hpre_compute_hash; + if (g_config.hash_type == HASH_SHA1) + sess_setup.hash.type = WD_HASH_SHA1; + else if (g_config.hash_type == HASH_SHA224) + sess_setup.hash.type = WD_HASH_SHA224; + else if (g_config.hash_type == HASH_SHA256) + sess_setup.hash.type = WD_HASH_SHA256; + else if (g_config.hash_type == HASH_SHA384) + sess_setup.hash.type = WD_HASH_SHA384; + else if (g_config.hash_type == HASH_SHA512) + sess_setup.hash.type = WD_HASH_SHA512; + else if (g_config.hash_type == HASH_MD4) + sess_setup.hash.type = WD_HASH_MD4; + else if (g_config.hash_type == HASH_MD5) + sess_setup.hash.type = WD_HASH_MD5; + else + sess_setup.hash.type = WD_HASH_SM3; + } + } + +// if ((!strncmp(g_config.op, "x25519", 6)) || (!strncmp(g_config.op, "x448", 4))) { +// if (x_dh_init_test_ctx_setup(&setup, opType)) { +// return NULL; +// } +// } else if (ecc_init_test_ctx_setup(&setup, opType)) { +// return NULL; +// } + + if (ecc_init_test_ctx_setup(&setup, opType)) + return NULL; + + if (opType == ECDSA_SIGN || opType == ECDSA_ASYNC_SIGN) + setup.op_type = (g_config.soft_test) ? ECC_SW_SIGN: ECC_HW_SIGN; + else if (opType == ECDSA_VERF || opType == ECDSA_ASYNC_VERF) + setup.op_type = (g_config.soft_test) ? ECC_SW_VERF: ECC_HW_VERF; + else if (opType == SM2_SIGN || opType == SM2_ASYNC_SIGN) + setup.op_type = (g_config.soft_test) ? SM2_SW_SIGN: SM2_HW_SIGN; + else if (opType == SM2_VERF || opType == SM2_ASYNC_VERF) + setup.op_type = (g_config.soft_test) ? SM2_SW_VERF: SM2_HW_VERF; + else if (opType == SM2_ENC || opType == SM2_ASYNC_ENC) + setup.op_type = (g_config.soft_test) ? SM2_SW_ENC: SM2_HW_ENC; + else if (opType == SM2_DEC|| opType == SM2_ASYNC_DEC) + setup.op_type = (g_config.soft_test) ? SM2_SW_DEC: SM2_HW_DEC; + else if (opType == SM2_KG|| opType == SM2_ASYNC_KG) + setup.op_type = (g_config.soft_test) ? SM2_SW_KG: SM2_HW_KG; + else if (opType == ECDH_ASYNC_GEN || opType == ECDH_GEN || + opType == X25519_ASYNC_GEN || opType == X25519_GEN || + opType == X448_ASYNC_GEN || opType == X448_GEN) + setup.op_type = (g_config.soft_test) ? ECDH_SW_GENERATE: ECDH_HW_GENERATE; + else if (opType == ECDH_ASYNC_COMPUTE || opType == ECDH_COMPUTE || + opType == X25519_ASYNC_COMPUTE || opType == X25519_COMPUTE || + opType == X448_ASYNC_COMPUTE || opType == X448_COMPUTE) + setup.op_type = (g_config.soft_test) ? ECDH_SW_COMPUTE: ECDH_HW_COMPUTE; + +new_test_again: + + if (!g_config.soft_test) { + sess = wd_ecc_alloc_sess(&sess_setup); + if (!sess) { + HPRE_TST_PRT("wd_ecc_alloc_sess failed\n"); + return NULL; + } + + prk.data = (void *)setup.priv_key; + prk.dsize = setup.priv_key_size; + prk.bsize = setup.priv_key_size; + pbk.x.data = (char *)setup.pub_key + 1; + pbk.x.dsize = key_size; + pbk.x.bsize = key_size; + pbk.y.data = pbk.x.data + key_size; + pbk.y.dsize = key_size; + pbk.y.bsize = key_size; + ret = set_sess_key(sess, &prk, &pbk); + if (ret) { + wd_ecc_free_sess(sess); + return NULL; + } + setup.sess = sess; + + if (!g_config.perf_test && !strncmp(g_config.op, "sm2", 3)) { + pbk_1.data = (void *)setup.pub_key; + pbk_1.dsize = setup.pub_key_size; + prk.data = (void *)setup.priv_key; + prk.dsize = setup.priv_key_size; + setup.openssl_handle = ecc_create_openssl_handle(&prk, &pbk_1); + if (!setup.openssl_handle) { + wd_ecc_free_sess(sess); + return NULL; + } + } + + } + +new_test_with_no_req_ctx: // async test + + test_ctx = ecc_create_test_ctx(setup, opType); + if (!test_ctx) { + HPRE_TST_PRT("ecc_create_test_ctx failed\n"); + return NULL; + } + if (opType >= X25519_GEN && opType <= X448_ASYNC_COMPUTE) + test_ctx->is_x25519_x448 = 1; + + req = test_ctx->req; + do { + if (is_async_test(opType)) { + pTag = malloc(sizeof(struct dh_user_tag_info)); + if (!pTag) { + HPRE_TST_PRT("malloc pTag fail!\n"); + ret = -1; + goto fail_release; + } + + pTag->test_ctx = test_ctx; + pTag->thread_data = pdata; + pTag->pid = pid; + pTag->thread_id = thread_id; + req->cb_param = pTag; + if (g_config.perf_test) + req->cb = _ecc_perf_cb; + else + req->cb = _ecc_cb; + } + + if (opType == ECDSA_ASYNC_SIGN || opType == ECDSA_SIGN) { + if (ecdsa_sign(test_ctx, pTag)) { // todo + ret = -1; + goto fail_release; + } + } else if (opType == SM2_SIGN || opType == SM2_ASYNC_SIGN) { + if (sm2_sign(test_ctx, pTag)) { + ret = -1; + goto fail_release; + } + } else if (opType == ECDSA_VERF || opType == ECDSA_ASYNC_VERF) { + if (ecdsa_verf(test_ctx, pTag)) { // todo + ret = -1; + goto fail_release; + } + } else if (opType == SM2_VERF || opType == SM2_ASYNC_VERF) { + if (sm2_verf(test_ctx, pTag)) { + ret = -1; + goto fail_release; + } + } else if (opType == SM2_ENC || opType == SM2_ASYNC_ENC) { + if (sm2_enc(test_ctx, pTag)) { + ret = -1; + goto fail_release; + } + } else if (opType == SM2_DEC || opType == SM2_ASYNC_DEC) { + if (sm2_dec(test_ctx, pTag)) { + ret = -1; + goto fail_release; + } + } else if (opType == SM2_KG || opType == SM2_ASYNC_KG) { + if (sm2_kg(test_ctx, pTag)) { + ret = -1; + goto fail_release; + } + } else if (opType == ECDH_ASYNC_GEN || opType == ECDH_GEN || + opType == X25519_ASYNC_GEN || opType == X25519_GEN || + opType == X448_ASYNC_GEN || opType == X448_GEN) { + if (ecxdh_generate_key(test_ctx, pTag)) { + ret = -1; + goto fail_release; + } + } else if (opType == ECDH_ASYNC_COMPUTE || opType == ECDH_COMPUTE || + opType == X25519_ASYNC_COMPUTE || opType == X25519_COMPUTE || + opType == X448_ASYNC_COMPUTE || opType == X448_COMPUTE) { + if (ecxdh_compute_key(test_ctx, pTag)) { + ret = -1; + goto fail_release; + } + } + + pdata->send_task_num++; + if (!is_async_test(opType)) { + + if (g_config.soft_test && !g_config.perf_test) { + ecc_del_test_ctx(test_ctx); + goto new_test_with_no_req_ctx; + } else if (!g_config.perf_test) { + if (ecc_result_check(test_ctx, 0)) { + ret = -1; + goto fail_release; + } + + if (is_allow_print(pdata->send_task_num, opType, thread_num)) { + HPRE_TST_PRT("Proc-%d, %d-TD: %s %uth succ!\n", + getpid(), (int)syscall(__NR_gettid), + ecc_op_str[test_ctx->setup.op_type], pdata->send_task_num); + } + + + if (!strncmp(g_config.op, "sm2", 3)) { + ecc_del_openssl_handle(test_ctx->setup.openssl_handle); + test_ctx->setup.openssl_handle = NULL; + } + + wd_ecc_free_sess(sess); + ecc_del_test_ctx(test_ctx); + sess = 0; + test_ctx = NULL; + + if (is_exit(pdata)) + goto func_test_exit; + + goto new_test_again; + } + } else { + if (is_exit(pdata)) + break; + + goto new_test_with_no_req_ctx; + } + } while(!is_exit(pdata)); + + if (!is_async_test(opType)) + pdata->recv_task_num = pdata->send_task_num; + + if (g_config.perf_test) { + gettimeofday(&cur_tval, NULL); + time_used = (float)((cur_tval.tv_sec -pdata->start_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - pdata->start_tval.tv_usec); + + if (g_config.seconds){ + speed = pdata->recv_task_num / time_used * 1000000; + } else if (g_config.times) { + speed = pdata->recv_task_num * 1.0 * 1000 * 1000 / time_used; + } + HPRE_TST_PRT("<< Proc-%d, %d-TD: run %s %s mode %u key_bits at %0.3f ops!\n", + pid, thread_id, g_config.op, g_config.alg_mode, g_config.key_bits, speed); + pdata->perf = speed; + } + + /* wait for recv finish */ + while (pdata->send_task_num != pdata->recv_task_num) { + usleep(1000 * 1000); + if (g_config.with_log) + HPRE_TST_PRT("<< Proc-%d, %d-TD: total send %u: recv %u, wait recv finish...!\n", + pid, thread_id, pdata->send_task_num, pdata->recv_task_num); + } + + ret = 0; + +fail_release: + + if (!g_config.soft_test && !is_async_test(opType)) + wd_ecc_free_sess(test_ctx->setup.sess); + + if (!is_async_test(opType)) + ecc_del_test_ctx(test_ctx); + + return NULL; + +func_test_exit: + + return NULL; +} + +static inline int _get_cpu_id(int thr, __u64 core_mask) +{ + __u64 i; + int cnt = 0; + + + for (i = 1; i < 64; i++) { + if (core_mask & (0x1ull << i)) { + if (thr == cnt) + return i; + cnt++; + } + } + + return 0; +} + +static inline int _get_one_bits(__u64 val) +{ + int count = 0; + + while (val) { + if (val % 2 == 1) + count++; + val = val / 2; + } + + return count; +} + +int hpre_test_write_to_file(__u8 *out, int size, char *out_file, + int handle, int try_close) +{ + int fd = -1, bytes_write; + + if (!out || !size || !out_file) { + HPRE_TST_PRT("para err while try to write file!\n"); + return -EINVAL; + } + + if (handle < 0) { + fd = open(out_file, O_WRONLY | O_CREAT, + S_IRUSR | S_IWUSR); + if (fd < 0) { + HPRE_TST_PRT("create %s file fail!\n", out_file); + return fd; + } + } else + fd = handle; + + bytes_write = write(fd, out, size); + if (bytes_write < 0 || bytes_write < size) { + if (try_close) + close(fd); + HPRE_TST_PRT("write data to %s file fail!\n", out_file); + return -ENOMEM; + } + if (try_close) + close(fd); + + /* to be fixed */ + return fd; +} + +#ifndef WITH_OPENSSL_DIR +static int get_rsa_key_from_test_sample(handle_t sess, char *pubkey_file, + char *privkey_file, + char *crt_privkey_file, int is_file) +{ + int ret = -1, bits; + const __u8 *p, *q, *n, *e, *d, *dmp1, *dmq1, *iqmp; + struct wd_dtb wd_e, wd_d, wd_n, wd_dq, wd_dp, wd_qinv, wd_q, wd_p; + u32 key_size = g_config.key_bits >> 3; + __u32 key_bits = g_config.key_bits; + + memset(&wd_e, 0, sizeof(wd_e)); + memset(&wd_d, 0, sizeof(wd_d)); + memset(&wd_n, 0, sizeof(wd_n)); + memset(&wd_dq, 0, sizeof(wd_dq)); + memset(&wd_dp, 0, sizeof(wd_dp)); + memset(&wd_qinv, 0, sizeof(wd_qinv)); + memset(&wd_q, 0, sizeof(wd_q)); + memset(&wd_p, 0, sizeof(wd_p)); + + bits = wd_rsa_get_key_bits(sess); + if (bits == 1024) { + e = rsa_e_1024; + p = rsa_p_1024; + q = rsa_q_1024; + dmp1 = rsa_dp_1024; + dmq1 = rsa_dq_1024; + iqmp = rsa_qinv_1024; + d = rsa_d_1024; + n = rsa_n_1024; + } else if (bits == 2048) { + e = rsa_e_2048; + p = rsa_p_2048; + q = rsa_q_2048; + dmp1 = rsa_dp_2048; + dmq1 = rsa_dq_2048; + iqmp = rsa_qinv_2048; + d = rsa_d_2048; + n = rsa_n_2048; + } else if (bits == 3072) { + e = rsa_e_3072; + p = rsa_p_3072; + q = rsa_q_3072; + dmp1 = rsa_dp_3072; + dmq1 = rsa_dq_3072; + iqmp = rsa_qinv_3072; + d = rsa_d_3072; + n = rsa_n_3072; + } else if (bits == 4096) { + e = rsa_e_4096; + p = rsa_p_4096; + q = rsa_q_4096; + dmp1 = rsa_dp_4096; + dmq1 = rsa_dq_4096; + iqmp = rsa_qinv_4096; + d = rsa_d_4096; + n = rsa_n_4096; + } else { + HPRE_TST_PRT("invalid key bits = %d!\n", bits); + return -1; + } + + wd_e.bsize = key_size; + wd_e.data = malloc(GEN_PARAMS_SZ(key_size)); + wd_n.bsize = wd_e.bsize; + wd_n.data = wd_e.data + wd_e.bsize; + + memcpy(wd_e.data, e, key_size); + wd_e.dsize = key_size; + memcpy(wd_n.data, n, key_size); + wd_n.dsize = key_size; + if (wd_rsa_set_pubkey_params(sess, &wd_e, &wd_n)) + { + HPRE_TST_PRT("set rsa pubkey failed %d!\n", ret); + goto gen_fail; + } + + if (pubkey_file && is_file) { + ret = hpre_test_write_to_file((unsigned char *)wd_e.data, g_config.key_bits >> 2, + pubkey_file, -1, 1); + if (ret < 0) + goto gen_fail; + HPRE_TST_PRT("RSA public key was written to %s!\n", + privkey_file); + } + + if (rsa_key_in) { + memset(rsa_key_in->e, 0, key_size); + memset(rsa_key_in->p, 0, key_size >> 1); + memset(rsa_key_in->q, 0, key_size >> 1); + memcpy(rsa_key_in->e, e, key_size); + rsa_key_in->e_size = key_size; + rsa_key_in->p_size = key_size / 2; + rsa_key_in->q_size = key_size / 2; + memcpy(rsa_key_in->p, p, key_size / 2); + memcpy(rsa_key_in->q, q, key_size / 2); + } + + if (wd_rsa_is_crt(sess)) { + wd_dq.bsize = CRT_PARAM_SZ(key_size); + wd_dq.data = malloc(CRT_PARAMS_SZ(key_size)); + wd_dp.bsize = CRT_PARAM_SZ(key_size); + wd_dp.data = wd_dq.data + wd_dq.bsize; + wd_q.bsize = CRT_PARAM_SZ(key_size); + wd_q.data = wd_dp.data + wd_dp.bsize; + wd_p.bsize = CRT_PARAM_SZ(key_size); + wd_p.data = wd_q.data + wd_q.bsize; + wd_qinv.bsize = CRT_PARAM_SZ(key_size); + wd_qinv.data = wd_p.data + wd_p.bsize; + + /* CRT mode private key */ + wd_dq.dsize = key_size / 2; + memcpy(wd_dq.data, dmq1, key_size / 2); + + wd_dp.dsize = key_size / 2; + memcpy(wd_dp.data, dmp1, key_size / 2); + + wd_q.dsize = key_size / 2; + memcpy(wd_q.data, q, key_size / 2); + + wd_p.dsize = key_size / 2; + memcpy(wd_p.data, p, key_size / 2); + + wd_qinv.dsize = key_size / 2; + memcpy(wd_qinv.data, iqmp, key_size / 2); + + if (wd_rsa_set_crt_prikey_params(sess, &wd_dq, + &wd_dp, &wd_qinv, + &wd_q, &wd_p)) + { + HPRE_TST_PRT("set rsa crt prikey failed %d!\n", ret); + goto gen_fail; + } + + + if (crt_privkey_file && is_file) { + ret = hpre_test_write_to_file((unsigned char *)wd_dq.data, + (key_bits >> 4) * 5, crt_privkey_file, -1, 0); + if (ret < 0) + goto gen_fail; + ret = hpre_test_write_to_file((unsigned char *)wd_e.data, + (key_bits >> 2), crt_privkey_file, ret, 1); + if (ret < 0) + goto gen_fail; + HPRE_TST_PRT("RSA CRT private key was written to %s!\n", + crt_privkey_file); + } else if (crt_privkey_file && !is_file) { + memcpy(crt_privkey_file, wd_dq.data, (key_bits >> 4) * 5); + memcpy(crt_privkey_file + (key_bits >> 4) * 5, + wd_e.data, (key_bits >> 2)); + } + + } else { + //wd_rsa_get_prikey_params(prikey, &wd_d, &wd_n); + wd_d.bsize = key_size; + wd_d.data = malloc(GEN_PARAMS_SZ(key_size)); + wd_n.bsize = key_size; + wd_n.data = wd_d.data + wd_d.bsize; + + /* common mode private key */ + wd_d.dsize = key_size; + memcpy(wd_d.data, d, key_size); + wd_n.dsize = key_size; + memcpy(wd_n.data, n, key_size); + + if (wd_rsa_set_prikey_params(sess, &wd_d, &wd_n)) + { + HPRE_TST_PRT("set rsa prikey failed %d!\n", ret); + goto gen_fail; + } + + + if (privkey_file && is_file) { + ret = hpre_test_write_to_file((unsigned char *)wd_d.data, + (key_size), + privkey_file, -1, 0); + if (ret < 0) + goto gen_fail; + ret = hpre_test_write_to_file((unsigned char *)wd_n.data, + (key_size), + privkey_file, ret, 1); + if (ret < 0) + goto gen_fail; + + ret = hpre_test_write_to_file((unsigned char *)wd_e.data, + (key_size), privkey_file, ret, 1); + if (ret < 0) + goto gen_fail; + HPRE_TST_PRT("RSA common private key was written to %s!\n", + privkey_file); + } else if (privkey_file && !is_file) { + memcpy(privkey_file, wd_d.data, key_size); + memcpy(privkey_file + key_size, wd_n.data, key_size); + memcpy(privkey_file + 2 * key_size, wd_e.data, key_size); + memcpy(privkey_file + 3 * key_size, wd_n.data, key_size); + } + } + + if (wd_e.data) + free(wd_e.data); + + if (wd_rsa_is_crt(sess)) { + if (wd_dq.data) + free(wd_dq.data); + } else { + if (wd_d.data) + free(wd_d.data); + } + + return 0; +gen_fail: + + if (wd_e.data) + free(wd_e.data); + + if (wd_rsa_is_crt(sess)) { + if (wd_dq.data) + free(wd_dq.data); + } else { + if (wd_d.data) + free(wd_d.data); + } + + return ret; +} + +#else + +static int test_rsa_key_gen(handle_t sess, char *pubkey_file, + char *privkey_file, + char *crt_privkey_file, int is_file) +{ + int ret; + RSA *test_rsa; + BIGNUM *p, *q, *e_value, *n, *e, *d, *dmp1, *dmq1, *iqmp; + //struct wd_dtb *wd_e, *wd_d, *wd_n, *wd_dq, *wd_dp, *wd_qinv, *wd_q, *wd_p; + struct wd_dtb wd_e, wd_d, wd_n, wd_dq, wd_dp, wd_qinv, wd_q, wd_p; + //struct wd_rsa_pubkey *pubkey; + //struct wd_rsa_prikey *prikey; + u32 key_size = g_config.key_bits >> 3; + u32 key_bits = g_config.key_bits; + char *tmp; + + memset(&wd_e, 0, sizeof(wd_e)); + memset(&wd_d, 0, sizeof(wd_d)); + memset(&wd_n, 0, sizeof(wd_n)); + memset(&wd_dq, 0, sizeof(wd_dq)); + memset(&wd_dp, 0, sizeof(wd_dp)); + memset(&wd_qinv, 0, sizeof(wd_qinv)); + memset(&wd_q, 0, sizeof(wd_q)); + memset(&wd_p, 0, sizeof(wd_p)); + + test_rsa = RSA_new(); + if (!test_rsa) { + HPRE_TST_PRT("RSA new fail!\n"); + return -ENOMEM; + } + e_value = BN_new(); + if (!e_value) { + RSA_free(test_rsa); + HPRE_TST_PRT("BN new e fail!\n"); + ret = -ENOMEM; + return ret; + } + ret = BN_set_word(e_value, 65537); + if (ret != 1) { + HPRE_TST_PRT("BN_set_word fail!\n"); + ret = -1; + goto gen_fail; + } + + ret = RSA_generate_key_ex(test_rsa, g_config.key_bits, e_value, NULL); + if (ret != 1) { + HPRE_TST_PRT("RSA_generate_key_ex fail!\n"); + ret = -1; + goto gen_fail; + } + RSA_get0_key((const RSA *)test_rsa, (const BIGNUM **)&n, + (const BIGNUM **)&e, (const BIGNUM **)&d); + RSA_get0_factors((const RSA *)test_rsa, (const BIGNUM **)&p, + (const BIGNUM **)&q); + RSA_get0_crt_params((const RSA *)test_rsa, (const BIGNUM **)&dmp1, + (const BIGNUM **)&dmq1, (const BIGNUM **)&iqmp); + + wd_e.bsize = key_size; + wd_e.data = malloc(GEN_PARAMS_SZ(key_size)); + wd_n.bsize = wd_e.bsize; + wd_n.data = wd_e.data + wd_e.bsize; + + wd_e.dsize = BN_bn2bin(e, (unsigned char *)wd_e.data); + if (wd_e.dsize > wd_e.bsize) { + HPRE_TST_PRT("e bn to bin overflow!\n"); + goto gen_fail; + } + wd_n.dsize = BN_bn2bin(n, (unsigned char *)wd_n.data); + if (wd_n.dsize > wd_n.bsize) { + HPRE_TST_PRT("n bn to bin overflow!\n"); + goto gen_fail; + } + + if (wd_rsa_set_pubkey_params(sess, &wd_e, &wd_n)) + { + HPRE_TST_PRT("set rsa pubkey failed %d!\n", ret); + goto gen_fail; + } + + tmp = malloc(key_size); + if (!tmp) { + HPRE_TST_PRT("failed to malloc!\n"); + goto gen_fail; + } + + memcpy(tmp, wd_e.data, wd_e.dsize); + crypto_bin_to_hpre_bin(wd_e.data, tmp, wd_e.bsize, wd_e.dsize); + memcpy(tmp, wd_n.data, wd_n.dsize); + crypto_bin_to_hpre_bin(wd_n.data, tmp, wd_n.bsize, wd_n.dsize); + wd_e.dsize = key_size; + wd_n.dsize = key_size; + + if (pubkey_file && is_file) { + ret = hpre_test_write_to_file((unsigned char *)wd_e.data, key_bits >> 2, + pubkey_file, -1, 1); + if (ret < 0) + goto gen_fail; + HPRE_TST_PRT("RSA public key was written to %s!\n", + privkey_file); + } + + if (rsa_key_in) { + memset(rsa_key_in->e, 0, key_size); + memset(rsa_key_in->p, 0, key_size >> 1); + memset(rsa_key_in->q, 0, key_size >> 1); + rsa_key_in->e_size = BN_bn2bin(e, (unsigned char *)rsa_key_in->e); + rsa_key_in->p_size = BN_bn2bin(p, (unsigned char *)rsa_key_in->p); + rsa_key_in->q_size = BN_bn2bin(q, (unsigned char *)rsa_key_in->q); + } + + //wd_rsa_get_prikey(sess, &prikey); + if (wd_rsa_is_crt(sess)) { + //wd_rsa_get_crt_prikey_params(prikey, &wd_dq, &wd_dp, &wd_qinv, &wd_q, &wd_p); + wd_dq.bsize = CRT_PARAM_SZ(key_size); + wd_dq.data = malloc(CRT_PARAMS_SZ(key_size)); + wd_dp.bsize = CRT_PARAM_SZ(key_size); + wd_dp.data = wd_dq.data + wd_dq.bsize; + wd_q.bsize = CRT_PARAM_SZ(key_size); + wd_q.data = wd_dp.data + wd_dp.bsize; + wd_p.bsize = CRT_PARAM_SZ(key_size); + wd_p.data = wd_q.data + wd_q.bsize; + wd_qinv.bsize = CRT_PARAM_SZ(key_size); + wd_qinv.data = wd_p.data + wd_p.bsize; + + /* CRT mode private key */ + wd_dq.dsize = BN_bn2bin(dmq1, (unsigned char *)wd_dq.data); + if (wd_dq.dsize > wd_dq.bsize) { + HPRE_TST_PRT("dq bn to bin overflow!\n"); + goto gen_fail; + } + + wd_dp.dsize = BN_bn2bin(dmp1, (unsigned char *)wd_dp.data); + if (wd_dp.dsize > wd_dp.bsize) { + HPRE_TST_PRT("dp bn to bin overflow!\n"); + goto gen_fail; + } + + wd_q.dsize = BN_bn2bin(q, (unsigned char *)wd_q.data); + if (wd_q.dsize > wd_q.bsize) { + HPRE_TST_PRT("q bn to bin overflow!\n"); + goto gen_fail; + } + + wd_p.dsize = BN_bn2bin(p, (unsigned char *)wd_p.data); + if (wd_p.dsize > wd_p.bsize) { + HPRE_TST_PRT("p bn to bin overflow!\n"); + goto gen_fail; + } + + wd_qinv.dsize = BN_bn2bin(iqmp, (unsigned char *)wd_qinv.data); + if (wd_qinv.dsize > wd_qinv.bsize) { + HPRE_TST_PRT("qinv bn to bin overflow!\n"); + goto gen_fail; + } + + if (wd_rsa_set_crt_prikey_params(sess, &wd_dq, + &wd_dp, &wd_qinv, + &wd_q, &wd_p)) + { + HPRE_TST_PRT("set rsa crt prikey failed %d!\n", ret); + goto gen_fail; + } + + memcpy(tmp, wd_dq.data, wd_dq.dsize); + crypto_bin_to_hpre_bin(wd_dq.data, tmp, wd_dq.bsize, wd_dq.dsize); + memcpy(tmp, wd_dp.data, wd_dp.dsize); + crypto_bin_to_hpre_bin(wd_dp.data, tmp, wd_dp.bsize, wd_dp.dsize); + memcpy(tmp, wd_q.data, wd_q.dsize); + crypto_bin_to_hpre_bin(wd_q.data, tmp, wd_q.bsize, wd_q.dsize); + memcpy(tmp, wd_p.data, wd_p.dsize); + crypto_bin_to_hpre_bin(wd_p.data, tmp, wd_p.bsize, wd_p.dsize); + memcpy(tmp, wd_qinv.data, wd_qinv.dsize); + crypto_bin_to_hpre_bin(wd_qinv.data, tmp, wd_qinv.bsize, wd_qinv.dsize); + wd_dq.dsize = key_size / 2; + wd_dp.dsize = key_size / 2; + wd_q.dsize = key_size / 2; + wd_p.dsize = key_size / 2; + wd_qinv.dsize = key_size / 2; + + + if (crt_privkey_file && is_file) { + ret = hpre_test_write_to_file((unsigned char *)wd_dq.data, + (key_bits >> 4) * 5, crt_privkey_file, -1, 0); + if (ret < 0) + goto gen_fail; + ret = hpre_test_write_to_file((unsigned char *)wd_e.data, + (key_bits >> 2), crt_privkey_file, ret, 1); + if (ret < 0) + goto gen_fail; + HPRE_TST_PRT("RSA CRT private key was written to %s!\n", + crt_privkey_file); + } else if (crt_privkey_file && !is_file) { + memcpy(crt_privkey_file, wd_dq.data, (key_bits >> 4) * 5); + memcpy(crt_privkey_file + (key_bits >> 4) * 5, + wd_e.data, (key_bits >> 2)); + } + + } else { + //wd_rsa_get_prikey_params(prikey, &wd_d, &wd_n); + wd_d.bsize = key_size; + wd_d.data = malloc(GEN_PARAMS_SZ(key_size)); + wd_n.bsize =key_size; + wd_n.data = wd_d.data + wd_d.bsize; + + /* common mode private key */ + wd_d.dsize = BN_bn2bin(d, (unsigned char *)wd_d.data); + wd_n.dsize = BN_bn2bin(n, (unsigned char *)wd_n.data); + + if (wd_rsa_set_prikey_params(sess, &wd_d, &wd_n)) + { + HPRE_TST_PRT("set rsa prikey failed %d!\n", ret); + goto gen_fail; + } + + memcpy(tmp, wd_d.data, wd_d.dsize); + crypto_bin_to_hpre_bin(wd_d.data, tmp, wd_d.bsize, wd_d.dsize); + memcpy(tmp, wd_n.data, wd_n.dsize); + crypto_bin_to_hpre_bin(wd_n.data, tmp, wd_n.bsize, wd_n.dsize); + wd_d.dsize = key_size; + wd_n.dsize = key_size; + + + if (privkey_file && is_file) { + ret = hpre_test_write_to_file((unsigned char *)wd_d.data, + (key_size), + privkey_file, -1, 0); + if (ret < 0) + goto gen_fail; + ret = hpre_test_write_to_file((unsigned char *)wd_n.data, + (key_size), + privkey_file, ret, 1); + if (ret < 0) + goto gen_fail; + + ret = hpre_test_write_to_file((unsigned char *)wd_e.data, + (key_size), privkey_file, ret, 1); + if (ret < 0) + goto gen_fail; + HPRE_TST_PRT("RSA common private key was written to %s!\n", + privkey_file); + } else if (privkey_file && !is_file) { + memcpy(privkey_file, wd_d.data, key_size); + memcpy(privkey_file + key_size, wd_n.data, key_size); + memcpy(privkey_file + 2 * key_size, wd_e.data, key_size); + memcpy(privkey_file + 3 * key_size, wd_n.data, key_size); + } + } + + RSA_free(test_rsa); + BN_free(e_value); + + if (wd_e.data) + free(wd_e.data); + + if (wd_rsa_is_crt(sess)) { + if (wd_dq.data) + free(wd_dq.data); + } else { + if (wd_d.data) + free(wd_d.data); + } + + free(tmp); + return 0; +gen_fail: + RSA_free(test_rsa); + BN_free(e_value); + + if (wd_e.data) + free(wd_e.data); + + if (wd_rsa_is_crt(sess)) { + if (wd_dq.data) + free(wd_dq.data); + } else { + if (wd_d.data) + free(wd_d.data); + } + + return ret; +} + +#endif + +int hpre_test_fill_keygen_opdata(handle_t sess, struct wd_rsa_req *req) +{ + struct wd_dtb *e, *p, *q; + struct wd_rsa_pubkey *pubkey; + struct wd_rsa_prikey *prikey; + struct wd_dtb t_e, t_p, t_q; + + wd_rsa_get_pubkey(sess, &pubkey); + wd_rsa_get_pubkey_params(pubkey, &e, NULL); + wd_rsa_get_prikey(sess, &prikey); + + if (wd_rsa_is_crt(sess)) { + wd_rsa_get_crt_prikey_params(prikey, NULL , NULL, NULL, &q, &p); + } else { + e = &t_e; + p = &t_p; + q = &t_q; + e->data = rsa_key_in->e; + e->dsize = rsa_key_in->e_size; + p->data = rsa_key_in->p; + p->dsize = rsa_key_in->p_size; + q->data = rsa_key_in->q; + q->dsize = rsa_key_in->q_size; + } + + req->src = wd_rsa_new_kg_in(sess, e, p, q); + if (!req->src) { + HPRE_TST_PRT("create rsa kgen in fail!\n"); + return -ENOMEM; + } + req->dst = wd_rsa_new_kg_out(sess); + if (!req->dst) { + HPRE_TST_PRT("create rsa kgen out fail!\n"); + return -ENOMEM; + } + return 0; +} + +static BIGNUM *hpre_bin_to_bn(void *bin, int raw_size) +{ + if (!bin || !raw_size) + return NULL; + + return BN_bin2bn((const unsigned char *)bin, raw_size, NULL); +} + +int hpre_test_result_check(handle_t sess, struct wd_rsa_req *req, void *key) +{ + struct wd_rsa_kg_out *out = (void *)req->dst; + struct wd_rsa_prikey *prikey; + int ret, keybits, key_size; + void *ssl_out; + BIGNUM *nn; + BIGNUM *e; + RSA *rsa; + + + rsa = RSA_new(); + if (!rsa) { + HPRE_TST_PRT("%s:RSA new fail!\n", __func__); + return -ENOMEM; + } + + wd_rsa_get_prikey(sess, &prikey); + keybits = wd_rsa_get_key_bits(sess); + key_size = keybits >> 3; + if (req->op_type == WD_RSA_GENKEY) { + if (wd_rsa_is_crt(sess)) { + struct wd_dtb qinv, dq, dp; + struct wd_dtb *s_qinv, *s_dq, *s_dp; + + wd_rsa_get_crt_prikey_params(prikey, &s_dq, &s_dp, + &s_qinv, NULL, NULL); + wd_rsa_get_kg_out_crt_params(out, &qinv, &dq, &dp); + + if (memcmp(s_qinv->data, qinv.data, s_qinv->dsize)) { + HPRE_TST_PRT("keygen qinv mismatch!\n"); + return -EINVAL; + } + if (memcmp(s_dq->data, dq.data, s_dq->dsize)) { + HPRE_TST_PRT("keygen dq mismatch!\n"); + return -EINVAL; + } + if (memcmp(s_dp->data, dp.data, s_dp->dsize)) { + HPRE_TST_PRT("keygen dp mismatch!\n"); + return -EINVAL; + } + } else { + struct wd_dtb d, n; + struct wd_dtb *s_d, *s_n; + + wd_rsa_get_kg_out_params(out, &d, &n); + + wd_rsa_get_prikey_params(prikey, &s_d, &s_n); + + /* check D */ + if (memcmp(s_n->data, n.data, s_n->dsize)) { + HPRE_TST_PRT("key generate N result mismatching!\n"); + return -EINVAL; + } + if (memcmp(s_d->data, d.data, s_d->dsize)) { + HPRE_TST_PRT("key generate D result mismatching!\n"); + return -EINVAL; + } + } + } else if (req->op_type == WD_RSA_VERIFY) { + ssl_out = malloc(key_size); + if (!ssl_out) { + HPRE_TST_PRT("malloc ssl out fail!\n"); + return -ENOMEM; + } + if (key) { + nn = hpre_bin_to_bn(key + key_size, + key_size); + if (!nn) { + HPRE_TST_PRT("n bin2bn err!\n"); + return -EINVAL; + } + e = hpre_bin_to_bn(key, key_size); + if (!e) { + HPRE_TST_PRT("e bin2bn err!\n"); + return -EINVAL; + } + ret = RSA_set0_key(rsa, nn, e, NULL); + if (ret <= 0) { + HPRE_TST_PRT("e set0_key err!\n"); + return -EINVAL; + } + } + ret = RSA_public_encrypt(req->src_bytes, req->src, ssl_out, + rsa, RSA_NO_PADDING); + if (ret != (int)req->src_bytes) { + HPRE_TST_PRT("openssl pub encrypto fail!ret=%d\n", ret); + return -ENOMEM; + } + if (!g_config.soft_test && memcmp(ssl_out, req->dst, key_size)) { + HPRE_TST_PRT("pub encrypto result mismatch!\n"); + print_data(ssl_out, req->src_bytes, "openssl out"); + print_data(req->dst, req->dst_bytes, "hpre out"); + RSA_print_fp(stdout, rsa, 4); + return -EINVAL; + } + free(ssl_out); + } else { + + ssl_out = malloc(key_size); + if (!ssl_out) { + HPRE_TST_PRT("malloc ssl out fail!\n"); + return -ENOMEM; + } + + if (key && wd_rsa_is_crt(sess)) { + BIGNUM *dp, *dq, *iqmp, *p, *q; + int size = key_size / 2; + + dq = hpre_bin_to_bn(key, size); + if (!dq) { + HPRE_TST_PRT("dq bin2bn err!\n"); + return -EINVAL; + } + dp = hpre_bin_to_bn(key + size, size); + if (!dp) { + HPRE_TST_PRT("dp bin2bn err!\n"); + return -EINVAL; + } + q = hpre_bin_to_bn(key + 2 * size, size); + if (!q) { + HPRE_TST_PRT("q bin2bn err!\n"); + return -EINVAL; + } + p = hpre_bin_to_bn(key + 3 * size, size); + if (!p) { + HPRE_TST_PRT("p bin2bn err!\n"); + return -EINVAL; + } + iqmp = hpre_bin_to_bn(key + 4 * size, size); + if (!iqmp) { + HPRE_TST_PRT("iqmp bin2bn err!\n"); + return -EINVAL; + } + ret = RSA_set0_crt_params(rsa, dp, dq, iqmp); + if (ret <= 0) { + HPRE_TST_PRT("set0_crt_params err!\n"); + return -EINVAL; + } + ret = RSA_set0_factors(rsa, p, q); + if (ret <= 0) { + HPRE_TST_PRT("set0_factors err!\n"); + return -EINVAL; + } + nn = hpre_bin_to_bn(key + 7 * size, key_size); + if (!nn) { + HPRE_TST_PRT("n bin2bn err!\n"); + return -EINVAL; + } + e = hpre_bin_to_bn(key + 5 * size, key_size); + if (!e) { + HPRE_TST_PRT("e bin2bn err!\n"); + return -EINVAL; + } + ret = RSA_set0_key(rsa, nn, e, NULL); + if (ret <= 0) { + HPRE_TST_PRT("rsa set0_key crt err!\n"); + return -EINVAL; + } + + } else if (key && !wd_rsa_is_crt(sess)) { + BIGNUM *d; + + nn = hpre_bin_to_bn(key + key_size, key_size); + if (!nn) { + HPRE_TST_PRT("n bin2bn err!\n"); + return -EINVAL; + } + d = hpre_bin_to_bn(key, key_size); + if (!d) { + HPRE_TST_PRT("d bin2bn err!\n"); + return -EINVAL; + } + e = hpre_bin_to_bn(key + 2 * key_size, key_size); + if (!e) { + HPRE_TST_PRT("e bin2bn err!\n"); + return -EINVAL; + } + ret = RSA_set0_key(rsa, nn, e, d); + if (ret <= 0) { + HPRE_TST_PRT("d set0_key err!\n"); + return -EINVAL; + } + } + + ret = RSA_private_decrypt(req->src_bytes, req->src, ssl_out, + rsa, RSA_NO_PADDING); + if (ret != (int)req->src_bytes) { + HPRE_TST_PRT("openssl priv decrypto fail!ret=%d\n", ret); + return -ENOMEM; + } +#ifdef DEBUG + print_data(req->dst, 16, "out"); + print_data(req->src, 16, "in"); + print_data(ssl_out, 16, "ssl_out"); +#endif + + if (!g_config.soft_test && memcmp(ssl_out, req->dst, ret)) { + HPRE_TST_PRT("prv decrypto result mismatch!\n"); + print_data(ssl_out, req->src_bytes, "openssl out"); + print_data(req->dst, req->dst_bytes, "hpre out"); + RSA_print_fp(stdout, rsa, 4); + return -EINVAL; + } + free(ssl_out); + + } + + RSA_free(rsa); + + return 0; +} + +int hpre_sys_func_test(struct test_hpre_pthread_dt * pdata) +{ + int pid = getpid(), ret = 0, i = 0; + int thread_id = (int)syscall(__NR_gettid); + struct wd_rsa_sess_setup setup; + struct wd_rsa_req req; + handle_t sess; + void *key_info = NULL; + struct timeval cur_tval; + float time = 0.0, speed = 0.0; + const char *alg_name = pdata->alg_name; + int key_size = g_config.key_bits >> 3; + char m[] = {0x54, 0x85, 0x9b, 0x34, 0x2c, 0x49, 0xea, 0x2a}; + + if (g_config.perf_test && (!g_config.times && !g_config.seconds)) { + HPRE_TST_PRT("g_config.times or g_config.seconds err\n"); + return -1; + } + +new_test_again: + + memset(&setup, 0, sizeof(setup)); + memset(&req, 0, sizeof(req)); + setup.key_bits = g_config.key_bits; + if (!strcmp(g_config.alg_mode, "crt")) + setup.is_crt = true; + else + setup.is_crt = false; + + sess = wd_rsa_alloc_sess(&setup); + if (!sess) { + HPRE_TST_PRT("Proc-%d, %d-TD:create %s sess fail!\n", + pid, thread_id, alg_name); + ret = -EINVAL; + goto fail_release; + } + + /* Just make sure memory size is enough */ + key_info = malloc(key_size * 16); + if (!key_info) { + HPRE_TST_PRT("thrd-%d:malloc key!\n", thread_id); + goto fail_release; + } + + rsa_key_in = malloc(2 * key_size + sizeof(struct hpre_rsa_test_key_in)); + if (!rsa_key_in) { + HPRE_TST_PRT("thrd-%d:malloc err!\n", thread_id); + goto fail_release; + } + + rsa_key_in->e = rsa_key_in + 1; + rsa_key_in->p = rsa_key_in->e + key_size; + rsa_key_in->q = rsa_key_in->p + (key_size >> 1); + + memset(key_info, 0, key_size * 16); + + #ifdef WITH_OPENSSL_DIR + ret = test_rsa_key_gen(sess, NULL, key_info, key_info, 0); + if (ret) { + HPRE_TST_PRT("thrd-%d:Openssl key gen fail!\n", thread_id); + goto fail_release; + } + #else + ret = get_rsa_key_from_test_sample(sess, NULL, key_info, key_info, 0); + if (ret) { + HPRE_TST_PRT("thrd-%d:get sample key fail!\n", thread_id); + goto fail_release; + } + #endif + + /* always key size bytes input */ + req.src_bytes = key_size; + if (pdata->op_type == RSA_KEY_GEN) { + req.op_type = WD_RSA_GENKEY; + } else if (pdata->op_type == RSA_PUB_EN) { + req.op_type = WD_RSA_VERIFY; + } else if (pdata->op_type == RSA_PRV_DE) { + req.op_type = WD_RSA_SIGN; + } else { + HPRE_TST_PRT("thrd-%d:optype=%d err!\n", + thread_id, pdata->op_type); + goto fail_release; + } + + if (req.op_type == WD_RSA_GENKEY) { + ret = hpre_test_fill_keygen_opdata(sess, &req); + if (ret){ + HPRE_TST_PRT("fill key gen req fail!\n"); + goto fail_release; + } + } else { + req.src = malloc(key_size); + if (!req.src) { + HPRE_TST_PRT("alloc in buffer fail!\n"); + goto fail_release; + } + memset(req.src, 0, req.src_bytes); + memcpy(req.src + key_size - sizeof(m), m, sizeof(m)); + req.dst = malloc(key_size); + if (!req.dst) { + HPRE_TST_PRT("alloc out buffer fail!\n"); + goto fail_release; + } + req.dst_bytes = key_size; + } + + do { + if (!g_config.soft_test) { + ret = wd_do_rsa_sync(sess, &req); + if (ret || req.status) { + HPRE_TST_PRT("Proc-%d, T-%d:hpre %s %dth status=%d fail!\n", + pid, thread_id, + g_config.op, i, req.status); + goto fail_release; + } + } + + pdata->send_task_num++; + i++; + if (g_config.check) { + void *check_key; + + if (req.op_type == WD_RSA_SIGN) + check_key = key_info; + if (req.op_type == WD_RSA_VERIFY) + if (wd_rsa_is_crt(sess)) + check_key = key_info + 5 * (g_config.key_bits >> 4); + else + check_key = key_info + 2 * key_size; + else + check_key = key_info; + ret = hpre_test_result_check(sess, &req, check_key); + if (ret) { + HPRE_TST_PRT("P-%d,T-%d:hpre %s %dth mismth\n", + pid, thread_id, + g_config.op, i); + goto fail_release; + } + else { + if (req.op_type == WD_RSA_GENKEY) { + if (is_allow_print(i, WD_RSA_GENKEY, pdata->thread_num)) + HPRE_TST_PRT("HPRE hardware key generate successfully!\n"); + } + } + } + + /* clean output buffer remainings in the last time operation */ + if (req.op_type == WD_RSA_GENKEY) { + char *data; + int len; + + len = wd_rsa_kg_out_data((void *)req.dst, &data); + if (len < 0) { + HPRE_TST_PRT("wd rsa get key gen out data fail!\n"); + goto fail_release; + } + memset(data, 0, len); + } else { +#ifdef DEBUG + print_data(req.dst, 16, "out"); +#endif + } + if (is_allow_print(i, pdata->op_type, pdata->thread_num)) { + gettimeofday(&cur_tval, NULL); + time = (float)((cur_tval.tv_sec - pdata->start_tval.tv_sec) * 1000000 + + (cur_tval.tv_usec - pdata->start_tval.tv_usec)); + speed = 1 / (time / i) * 1000; + HPRE_TST_PRT("Proc-%d, %d-TD %s %dtimes,%0.0fus, %0.3fkops\n", + pid, thread_id, g_config.op, + i, time, speed); + } + + if (!g_config.perf_test && !g_config.soft_test) { + if (req.op_type == WD_RSA_GENKEY) { + if (req.src) + wd_rsa_del_kg_in(sess, req.src); + if (req.dst) + wd_rsa_del_kg_out(sess, req.dst); + } else { + if (req.src) + free(req.src); + if (req.dst) + free(req.dst); + } + + if (sess) + wd_rsa_free_sess(sess); + + if (rsa_key_in) + free(rsa_key_in); + + if (key_info) + free(key_info); + + if (is_exit(pdata)) + return 0; + + goto new_test_again; + } + }while(!is_exit(pdata)); + + pdata->recv_task_num = pdata->send_task_num; + + if (g_config.perf_test) { + gettimeofday(&cur_tval, NULL); + time = (float)((cur_tval.tv_sec -pdata->start_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - pdata->start_tval.tv_usec); + + if (g_config.seconds) { + speed = pdata->recv_task_num / time * 1000000; + } else if (g_config.times) { + speed = pdata->recv_task_num * 1.0 * 1000 * 1000 / time; + } + pdata->perf = speed; + HPRE_TST_PRT("<< Proc-%d, %d-TD: run %s %s mode %u key_bits at %0.3f ops!\n", + pid, thread_id, g_config.op, g_config.alg_mode, g_config.key_bits, speed); + } + +fail_release: + if (req.op_type == WD_RSA_GENKEY) { + if (req.src) + wd_rsa_del_kg_in(sess, req.src); + if (req.dst) + wd_rsa_del_kg_out(sess, req.dst); + } else { + if (req.src) + free(req.src); + if (req.dst) + free(req.dst); + } + if (sess) + wd_rsa_free_sess(sess); + if (key_info) + free(key_info); + if (rsa_key_in) + free(rsa_key_in); + + + return ret; +} + +void *_hpre_rsa_sys_test_thread(void *data) +{ + int ret, cpuid; + struct test_hpre_pthread_dt *pdata = data; + cpu_set_t mask; + int pid = getpid(); + int thread_id = (int)syscall(__NR_gettid); + + CPU_ZERO(&mask); + cpuid = pdata->cpu_id; + CPU_SET(cpuid, &mask); + if (cpuid) { + ret = pthread_setaffinity_np(pthread_self(), + sizeof(mask), &mask); + if (ret < 0) { + HPRE_TST_PRT("Proc-%d, thrd-%d:set affinity fail!\n", + pid, thread_id); + return NULL; + } + HPRE_TST_PRT("Proc-%d, thrd-%d bind to cpu-%d!\n", + pid, thread_id, cpuid); + } + ret = hpre_sys_func_test(pdata); + if (ret) + return NULL; + + return NULL; +} + +static int hpre_sys_test(int thread_num, __u64 lcore_mask, + __u64 hcore_mask, enum alg_op_type op_type, + char *dev_path, unsigned int node_msk) +{ + int i, ret, cnt = 0; + int h_cpuid; + float speed = 0.0; + + if (_get_one_bits(lcore_mask) > 0) + cnt = _get_one_bits(lcore_mask); + else if (_get_one_bits(lcore_mask) == 0 && + _get_one_bits(hcore_mask) == 0) + cnt = thread_num; + for (i = 0; i < cnt; i++) { + test_thrds_data[i].thread_num = thread_num; + test_thrds_data[i].op_type = op_type; + test_thrds_data[i].cpu_id = _get_cpu_id(i, lcore_mask); + gettimeofday(&test_thrds_data[i].start_tval, NULL); + ret = pthread_create(&system_test_thrds[i], NULL, + _hpre_sys_test_thread, &test_thrds_data[i]); + if (ret) { + HPRE_TST_PRT("Create %dth thread fail!\n", i); + return ret; + } + } + for (i = 0; i < thread_num - cnt; i++) { + h_cpuid = _get_cpu_id(i, hcore_mask); + if (h_cpuid > 0) + h_cpuid += 64; + + test_thrds_data[i + cnt].thread_num = thread_num; + test_thrds_data[i + cnt].op_type = op_type; + test_thrds_data[i + cnt].cpu_id = h_cpuid; + gettimeofday(&test_thrds_data[i + cnt].start_tval, NULL); + ret = pthread_create(&system_test_thrds[i + cnt], NULL, + _hpre_sys_test_thread, &test_thrds_data[i + cnt]); + if (ret) { + HPRE_TST_PRT("Create %dth thread fail!\n", i); + return ret; + } + } + for (i = 0; i < thread_num; i++) { + ret = pthread_join(system_test_thrds[i], NULL); + if (ret) { + HPRE_TST_PRT("Join %dth thread fail!\n", i); + return ret; + } + speed += test_thrds_data[i].perf; + } + + if (g_config.perf_test) + HPRE_TST_PRT("<< %s %u thread %s %s mode %u key_bits at %0.3f ops!\n", + g_config.trd_mode, g_config.trd_num, g_config.op, + g_config.alg_mode, g_config.key_bits, speed); + HPRE_TST_PRT("<< test finish!\n"); + + return 0; +} + +static void *_rsa_async_poll_test_thread(void *data) +{ + __u32 count = 0; + __u32 expt = 0; + int ret = 0; + + while (1) { + ret = wd_rsa_poll(expt, &count); + if (ret < 0) { + break; + } + + if (asyn_thread_exit) + break; + } + + if (g_config.with_log) + HPRE_TST_PRT("%s exit!\n", __func__); + + return NULL; +} +static void _rsa_cb(void *req_t) +{ + struct wd_rsa_req *req = req_t; + int keybits, key_size; + struct rsa_async_tag *tag = req->cb_param; + handle_t sess = tag->sess; + int thread_id = tag->thread_id; + int cnt = tag->cnt; + void *out = req->dst; + enum wd_rsa_op_type op_type = req->op_type; + struct wd_rsa_prikey *prikey; + struct test_hpre_pthread_dt *thread_info = tag->thread_info; + + wd_rsa_get_prikey(sess, &prikey); + keybits = wd_rsa_get_key_bits(sess); + key_size = keybits >> 3; + + thread_info->recv_task_num++; + + if (g_config.check) { + if (op_type == WD_RSA_GENKEY) { + struct wd_rsa_kg_out *kout = out; + + if (wd_rsa_is_crt(sess)) { + struct wd_dtb qinv, dq, dp; + struct wd_dtb *s_qinv, *s_dq, *s_dp; + + wd_rsa_get_crt_prikey_params(prikey, &s_dq, &s_dp, + &s_qinv, NULL, NULL); + wd_rsa_get_kg_out_crt_params(kout, &qinv, &dq, &dp); + if (memcmp(s_qinv->data, qinv.data, s_qinv->bsize)) { + HPRE_TST_PRT("keygen qinv mismatch!\n"); + return; + } + if (memcmp(s_dq->data, dq.data, s_dq->bsize)) { + HPRE_TST_PRT("keygen dq mismatch!\n"); + return; + } + if (memcmp(s_dp->data, dp.data, s_dp->bsize)) { + HPRE_TST_PRT("keygen dp mismatch!\n"); + return; + } + + } else { + struct wd_dtb d, n; + struct wd_dtb *s_d, *s_n; + + wd_rsa_get_prikey_params(prikey, &s_d, &s_n); + wd_rsa_get_kg_out_params(kout, &d, &n); + + /* check D */ + if (memcmp(s_d->data, d.data, s_d->bsize)) { + HPRE_TST_PRT("key generate D result mismatching!\n"); + return; + } + if (memcmp(s_n->data, n.data, s_n->bsize)) { + HPRE_TST_PRT("key generate N result mismatching!\n"); + return; + } + } + if (is_allow_print(cnt, DH_ASYNC_GEN, 1)) + HPRE_TST_PRT("HPRE hardware key generate successfully!\n"); + } else if (op_type == WD_RSA_VERIFY) { + if (!g_config.soft_test && memcmp(ssl_params.ssl_verify_result, out, key_size)) { + HPRE_TST_PRT("pub encrypto result mismatch!\n"); + return; + } + } else { + if (wd_rsa_is_crt(sess)) + if (!g_config.soft_test && memcmp(ssl_params.ssl_sign_result, out, key_size)) { + HPRE_TST_PRT("prv decrypto result mismatch!\n"); + return; + } + } + } + + if (is_allow_print(cnt, op_type, 1)) + HPRE_TST_PRT("thread %d do RSA %dth time success!\n", thread_id, cnt); + if (op_type == WD_RSA_GENKEY && out) { + wd_rsa_del_kg_out(sess, out); + } + free(tag); +} + +void *_rsa_async_op_test_thread(void *data) +{ + int ret = 0, i = 0, cpuid; + struct test_hpre_pthread_dt *pdata = data; + const char *alg_name = pdata->alg_name; + cpu_set_t mask; + enum alg_op_type op_type; + int pid = getpid(); + int thread_id = (int)syscall(__NR_gettid); + struct wd_rsa_sess_setup setup; + struct wd_rsa_req req; + handle_t sess; + void *key_info = NULL; + struct wd_rsa_prikey *prikey; + struct wd_rsa_pubkey *pubkey; + struct rsa_async_tag *tag; + struct wd_dtb *wd_e, *wd_d, *wd_n, *wd_dq, *wd_dp, *wd_qinv, *wd_q, *wd_p; + struct wd_dtb t_e, t_p, t_q; + u32 key_size = g_config.key_bits >> 3; + + if (g_config.perf_test && (!g_config.times && !g_config.seconds)) { + HPRE_TST_PRT("g_config.times or g_config.seconds err\n"); + return NULL; + } + + CPU_ZERO(&mask); + cpuid = pdata->cpu_id; + op_type = pdata->op_type; + CPU_SET(cpuid, &mask); + if (cpuid) { + ret = pthread_setaffinity_np(pthread_self(), + sizeof(mask), &mask); + if (ret < 0) { + HPRE_TST_PRT("Proc-%d, thrd-%d:set affinity fail!\n", + pid, thread_id); + return NULL; + } + HPRE_TST_PRT("Proc-%d, thrd-%d bind to cpu-%d!\n", + pid, thread_id, cpuid); + } + memset(&setup, 0, sizeof(setup)); + memset(&req, 0, sizeof(req)); + setup.key_bits = g_config.key_bits; + if (!strcmp(g_config.alg_mode, "crt")) + setup.is_crt = true; + else + setup.is_crt = false; + + sess = wd_rsa_alloc_sess(&setup); + if (!sess) { + HPRE_TST_PRT("Proc-%d, %d-TD:create %s sess fail!\n", + pid, thread_id, alg_name); + goto fail_release; + } + + rsa_key_in = malloc(2 * key_size + sizeof(struct hpre_rsa_test_key_in)); + if (!rsa_key_in) { + HPRE_TST_PRT("thrd-%d:malloc err!\n", thread_id); + goto fail_release; + } + + rsa_key_in->e = rsa_key_in + 1; + rsa_key_in->p = rsa_key_in->e + key_size; + rsa_key_in->q = rsa_key_in->p + (key_size >> 1); + + wd_rsa_get_pubkey(sess, &pubkey); + wd_rsa_get_pubkey_params(pubkey, &wd_e, &wd_n); + +#ifdef WITH_OPENSSL_DIR + wd_e->dsize = BN_bn2bin(ssl_params.e, (unsigned char *)wd_e->data); + if (wd_e->dsize > wd_e->bsize) { + HPRE_TST_PRT("e bn to bin overflow!\n"); + goto fail_release; + } + wd_n->dsize = BN_bn2bin(ssl_params.n, (unsigned char *)wd_n->data); + if (wd_n->dsize > wd_n->bsize) { + HPRE_TST_PRT("n bn to bin overflow!\n"); + goto fail_release; + } +#else + memcpy(wd_e->data, ssl_params.e, key_size); + wd_e->dsize = key_size; + memcpy(wd_n->data, ssl_params.n, key_size); + wd_n->dsize = key_size; +#endif + wd_rsa_get_prikey(sess, &prikey); + if (wd_rsa_is_crt(sess)) { + wd_rsa_get_crt_prikey_params(prikey, &wd_dq, &wd_dp, &wd_qinv, &wd_q, &wd_p); + +#ifdef WITH_OPENSSL_DIR + /* CRT mode private key */ + wd_dq->dsize = BN_bn2bin(ssl_params.dq, (unsigned char *)wd_dq->data); + if (wd_dq->dsize > wd_dq->bsize) { + HPRE_TST_PRT("dq bn to bin overflow!\n"); + goto fail_release; + } + wd_dp->dsize = BN_bn2bin(ssl_params.dp, (unsigned char *)wd_dp->data); + if (wd_dp->dsize > wd_dp->bsize) { + HPRE_TST_PRT("dp bn to bin overflow!\n"); + goto fail_release; + } + wd_qinv->dsize = BN_bn2bin(ssl_params.qinv, (unsigned char *)wd_qinv->data); + if (wd_qinv->dsize > wd_qinv->bsize) { + HPRE_TST_PRT("qinv bn to bin overflow!\n"); + goto fail_release; + } + wd_q->dsize = BN_bn2bin(ssl_params.q, (unsigned char *)wd_q->data); + if (wd_q->dsize > wd_q->bsize) { + HPRE_TST_PRT("q bn to bin overflow!\n"); + goto fail_release; + } + wd_p->dsize = BN_bn2bin(ssl_params.p, (unsigned char *)wd_p->data); + if (wd_p->dsize > wd_p->bsize) { + HPRE_TST_PRT("p bn to bin overflow!\n"); + goto fail_release; + } +#else + memcpy(wd_dq->data, ssl_params.dq, key_size / 2); + wd_dq->dsize = key_size / 2; + memcpy(wd_dp->data, ssl_params.dp, key_size / 2); + wd_dp->dsize = key_size / 2; + memcpy(wd_qinv->data, ssl_params.qinv, key_size / 2); + wd_qinv->dsize = key_size / 2; + memcpy(wd_q->data, ssl_params.q, key_size / 2); + wd_q->dsize = key_size / 2; + memcpy(wd_p->data, ssl_params.p, key_size / 2); + wd_p->dsize = key_size / 2; +#endif + + } else { + wd_rsa_get_prikey_params(prikey, &wd_d, &wd_n); + +#ifdef WITH_OPENSSL_DIR + wd_d->dsize = BN_bn2bin(ssl_params.d, (unsigned char *)wd_d->data); + wd_n->dsize = BN_bn2bin(ssl_params.n, (unsigned char *)wd_n->data); +#else + memcpy(wd_d->data, ssl_params.d, key_size); + wd_d->dsize = key_size; + memcpy(wd_n->data, ssl_params.n, key_size); + wd_n->dsize = key_size; +#endif + wd_e = &t_e; + wd_p = &t_p; + wd_q = &t_q; + memset(rsa_key_in->e, 0, key_size); + memset(rsa_key_in->p, 0, key_size >> 1); + memset(rsa_key_in->q, 0, key_size >> 1); +#ifdef WITH_OPENSSL_DIR + rsa_key_in->e_size = BN_bn2bin(ssl_params.e, (unsigned char *)rsa_key_in->e); + rsa_key_in->p_size = BN_bn2bin(ssl_params.p, (unsigned char *)rsa_key_in->p); + rsa_key_in->q_size = BN_bn2bin(ssl_params.q, (unsigned char *)rsa_key_in->q); +#else + memcpy(rsa_key_in->e, ssl_params.e, key_size); + rsa_key_in->e_size = key_size; + memcpy(rsa_key_in->p, ssl_params.p, key_size / 2); + rsa_key_in->p_size = key_size / 2; + memcpy(rsa_key_in->q, ssl_params.q, key_size / 2); + rsa_key_in->q_size = key_size / 2; +#endif + wd_e->data = rsa_key_in->e; + wd_e->dsize = rsa_key_in->e_size; + wd_p->data = rsa_key_in->p; + wd_p->dsize = rsa_key_in->p_size; + wd_q->data = rsa_key_in->q; + wd_q->dsize = rsa_key_in->q_size; + } + + /* always key size bytes input */ + req.src_bytes = key_size; + req.cb = _rsa_cb; + if (op_type == RSA_KEY_GEN || op_type == RSA_ASYNC_GEN) { + req.op_type = WD_RSA_GENKEY; + } else if (op_type == RSA_PUB_EN || op_type == RSA_ASYNC_EN) { + req.op_type = WD_RSA_VERIFY; + } else if (op_type == RSA_PRV_DE || op_type == RSA_ASYNC_DE) { + req.op_type = WD_RSA_SIGN; + } else { + HPRE_TST_PRT("thrd-%d:optype=%d err!\n", + thread_id, op_type); + goto fail_release; + } + + if (req.op_type == WD_RSA_GENKEY) { + req.src = (__u8 *)wd_rsa_new_kg_in(sess, wd_e, wd_p, wd_q); + if (!req.src) { + HPRE_TST_PRT("thrd-%d:fill key gen req fail!\n", + thread_id); + goto fail_release; + } + //req.dst = wd_rsa_new_kg_out(sess); + //if (!req.dst) { + // HPRE_TST_PRT("create rsa kgen out fail!\n"); + // goto fail_release; + //} + } else { + req.src = malloc(key_size); + if (!req.src) { + HPRE_TST_PRT("alloc in buffer fail!\n"); + goto fail_release; + } + memset(req.src, 0, req.src_bytes); + req.dst = malloc(key_size); + if (!req.dst) { + HPRE_TST_PRT("alloc out buffer fail!\n"); + goto fail_release; + } + memset(req.dst, 0, req.src_bytes); + req.dst_bytes = key_size; + } + + do { + if (req.op_type == WD_RSA_GENKEY) { + req.dst = wd_rsa_new_kg_out(sess); + if (!req.dst) { + HPRE_TST_PRT("create rsa kgen out fail!\n"); + goto fail_release; + } + } + /* set the user tag */ + tag = malloc(sizeof(*tag)); + if (!tag) + goto fail_release; + tag->sess = sess; + tag->thread_id = thread_id; + tag->cnt = i; + tag->thread_info = pdata; + req.cb_param = tag; +try_do_again: + ret = wd_do_rsa_async(sess, &req); + if (ret == -WD_EBUSY) { + usleep(100); + goto try_do_again; + } else if (ret) { + HPRE_TST_PRT("Proc-%d, T-%d:hpre %s %dth fail!\n", + pid, thread_id, g_config.op, i); + goto fail_release; + } + //usleep(100); + i++; + pdata->send_task_num++; + }while (!is_exit(pdata)); + + if (g_config.perf_test) { + struct timeval cur_tval; + float speed = 0.0, time_used = 0.0; + gettimeofday(&cur_tval, NULL); + + //printf("start: s %lu, us %lu\n", pdata->start_tval.tv_sec, pdata->start_tval.tv_usec); + //printf("now: s %lu, us %lu\n", cur_tval.tv_sec, cur_tval.tv_usec); + + time_used = (float)((cur_tval.tv_sec -pdata->start_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - pdata->start_tval.tv_usec); + + if (g_config.seconds) { + speed = pdata->recv_task_num / time_used * 1000000; + } else if (g_config.times) { + speed = pdata->recv_task_num * 1.0 * 1000 * 1000 / time_used; + } + HPRE_TST_PRT("<< Proc-%d, %d-TD: run %s %s mode %u key_bits at %0.3f ops!\n", + pid, thread_id, g_config.op, g_config.alg_mode, g_config.key_bits, speed); + pdata->perf = speed; + } + + /* wait for recv finish */ + while (pdata->send_task_num != pdata->recv_task_num) { + usleep(1000 * 1000); + if (g_config.with_log) + HPRE_TST_PRT("<< Proc-%d, %d-TD: total send %u: recv %u, wait recv finish...!\n", + pid, thread_id, pdata->send_task_num, pdata->recv_task_num); + } + + +fail_release: + if (req.op_type == WD_RSA_GENKEY) { + if (req.src) + wd_rsa_del_kg_in(sess, req.src); + //if (req.dst) + // wd_rsa_del_kg_out(sess, req.dst); + } else { + if (req.src) + free(req.src); + if (req.dst) + free(req.dst); + } + if (sess) + wd_rsa_free_sess(sess); + if (key_info) + free(key_info); + if (rsa_key_in) + free(rsa_key_in); + return NULL; +} + +static int set_ssl_plantext(void) +{ + ssl_params.size = g_config.key_bits >> 3; + ssl_params.plantext = malloc(ssl_params.size); + if (!ssl_params.plantext) + return -ENOMEM; + memset(ssl_params.plantext, 0, ssl_params.size); + return 0; +} + +#ifdef WITH_OPENSSL_DIR +static int rsa_openssl_key_gen_for_async_test(void) +{ + int ret; + + ssl_params.rsa = RSA_new(); + if (!ssl_params.rsa) { + HPRE_TST_PRT("RSA new fail!\n"); + return -ENOMEM; + } + ssl_params.e = BN_new(); + if (!ssl_params.e) { + RSA_free(ssl_params.rsa); + ssl_params.rsa = NULL; + HPRE_TST_PRT("BN new e fail!\n"); + ret = -ENOMEM; + goto gen_fail; + } + ret = BN_set_word(ssl_params.e, 65537); + if (ret != 1) { + HPRE_TST_PRT("BN_set_word fail!\n"); + ret = -1; + goto gen_fail; + } + + /* Generate OpenSSL SW rsa parameters */ + ret = RSA_generate_key_ex(ssl_params.rsa, g_config.key_bits, ssl_params.e, NULL); + if (ret != 1) { + HPRE_TST_PRT("RSA_generate_key_ex fail!\n"); + ret = -1; + goto gen_fail; + } + RSA_get0_key((const RSA *)ssl_params.rsa, (const BIGNUM **)&ssl_params.n, + (const BIGNUM **)&ssl_params.e, (const BIGNUM **)&ssl_params.d); + RSA_get0_factors((const RSA *)ssl_params.rsa, (const BIGNUM **)&ssl_params.p, + (const BIGNUM **)&ssl_params.q); + RSA_get0_crt_params((const RSA *)ssl_params.rsa, (const BIGNUM **)&ssl_params.dp, + (const BIGNUM **)&ssl_params.dq, (const BIGNUM **)&ssl_params.qinv); + + /* Generate OpenSSL SW rsa verify and sign standard result + * for check in the next tests + */ + ret = set_ssl_plantext(); + if (ret) { + HPRE_TST_PRT("set ssl plantext fail!!\n"); + ret = -1; + goto gen_fail; + } + ssl_params.ssl_verify_result = malloc(ssl_params.size); + if (!ssl_params.ssl_verify_result) { + HPRE_TST_PRT("malloc verify result buffer fail!!\n"); + ret = -1; + goto gen_fail; + } + ret = RSA_public_encrypt(ssl_params.size, ssl_params.plantext, + ssl_params.ssl_verify_result, + ssl_params.rsa, RSA_NO_PADDING); + if (ret != ssl_params.size) { + HPRE_TST_PRT("openssl pub encrypto fail!ret=%d\n", ret); + ret = -1; + return ret; + } + ssl_params.ssl_sign_result = malloc(ssl_params.size); + if (!ssl_params.ssl_sign_result) { + HPRE_TST_PRT("malloc sign result buffer fail!!\n"); + ret = -1; + goto gen_fail; + } + ret = RSA_private_decrypt(ssl_params.size, ssl_params.plantext, + ssl_params.ssl_sign_result, + ssl_params.rsa, RSA_NO_PADDING); + if (ret != ssl_params.size) { + HPRE_TST_PRT("openssl priv decrypto fail!ret=%d\n", ret); + ret = -1; + goto gen_fail; + } + + return 0; + +gen_fail: + RSA_free(ssl_params.rsa); + BN_free(ssl_params.e); + if (ssl_params.plantext) + free(ssl_params.plantext); + if (ssl_params.ssl_verify_result) + free(ssl_params.ssl_verify_result); + if (ssl_params.ssl_sign_result) + free(ssl_params.ssl_sign_result); + return ret; +} + +#else +static int rsa_sample_key_gen_for_async_test(void) +{ + const __u8 *p, *q, *n, *e, *d, *dp, *dq, *qinv; + int key_bits = g_config.key_bits; + int ret; + + if (g_config.key_bits == 1024) { + e = rsa_e_1024; + p = rsa_p_1024; + q = rsa_q_1024; + dp = rsa_dp_1024; + dq = rsa_dq_1024; + qinv = rsa_qinv_1024; + d = rsa_d_1024; + n = rsa_n_1024; + } else if (key_bits == 2048) { + e = rsa_e_2048; + p = rsa_p_2048; + q = rsa_q_2048; + dp = rsa_dp_2048; + dq = rsa_dq_2048; + qinv = rsa_qinv_2048; + d = rsa_d_2048; + n = rsa_n_2048; + } else if (key_bits == 3072) { + e = rsa_e_3072; + p = rsa_p_3072; + q = rsa_q_3072; + dp = rsa_dp_3072; + dq = rsa_dq_3072; + qinv = rsa_qinv_3072; + d = rsa_d_3072; + n = rsa_n_3072; + } else if (key_bits == 4096) { + e = rsa_e_4096; + p = rsa_p_4096; + q = rsa_q_4096; + dp = rsa_dp_4096; + dq = rsa_dq_4096; + qinv = rsa_qinv_4096; + d = rsa_d_4096; + n = rsa_n_4096; + } else { + HPRE_TST_PRT("invalid key bits = %d!\n", key_bits); + return -1; + } + + ssl_params.e = BN_bin2bn(e, key_bits >> 3, NULL); + if (!ssl_params.e) { + HPRE_TST_PRT("Bin2bin e fail!\n"); + ret = -ENOMEM; + goto gen_fail; + } + + ssl_params.d = BN_bin2bn(d, key_bits >> 3, NULL); + if (!ssl_params.d) { + HPRE_TST_PRT("Bin2bin d fail!\n"); + ret = -ENOMEM; + goto gen_fail; + } + + ssl_params.n = BN_bin2bn(n, key_bits >> 3, NULL); + if (!ssl_params.n) { + HPRE_TST_PRT("Bin2bin n fail!\n"); + ret = -ENOMEM; + goto gen_fail; + } + + ssl_params.p = BN_bin2bn(p, key_bits >> 4, NULL); + if (!ssl_params.p) { + HPRE_TST_PRT("Bin2bin p fail!\n"); + ret = -ENOMEM; + goto gen_fail; + } + + ssl_params.q = BN_bin2bn(q, key_bits >> 4, NULL); + if (!ssl_params.q) { + HPRE_TST_PRT("Bin2bin q fail!\n"); + ret = -ENOMEM; + goto gen_fail; + } + + ssl_params.dp = BN_bin2bn(dp, key_bits >> 4, NULL); + if (!ssl_params.dp) { + HPRE_TST_PRT("Bin2bin dp fail!\n"); + ret = -ENOMEM; + goto gen_fail; + } + + ssl_params.dq = BN_bin2bn(dq, key_bits >> 4, NULL); + if (!ssl_params.dq) { + HPRE_TST_PRT("Bin2bin dq fail!\n"); + ret = -ENOMEM; + goto gen_fail; + } + + ssl_params.qinv = BN_bin2bn(qinv, key_bits >> 4, NULL); + if (!ssl_params.qinv) { + HPRE_TST_PRT("Bin2bin qinv fail!\n"); + ret = -ENOMEM; + goto gen_fail; + } + + /* Generate OpenSSL SW rsa verify and sign standard result + * for check in the next tests + */ + ret = set_ssl_plantext(); + if (ret) { + HPRE_TST_PRT("set ssl plantext fail!!\n"); + ret = -1; + goto gen_fail; + } + + ssl_params.ssl_verify_result = malloc(ssl_params.size); + if (!ssl_params.ssl_verify_result) { + HPRE_TST_PRT("malloc verify result buffer fail!!\n"); + ret = -1; + goto gen_fail; + } + ssl_params.ssl_sign_result = malloc(ssl_params.size); + if (!ssl_params.ssl_sign_result) { + HPRE_TST_PRT("malloc sign result buffer fail!!\n"); + ret = -1; + goto gen_fail; + } + + return 0; +gen_fail: + if (ssl_params.e) + BN_free(ssl_params.e); + if (ssl_params.d) + BN_free(ssl_params.d); + if (ssl_params.n) + BN_free(ssl_params.n); + if (ssl_params.p) + BN_free(ssl_params.p); + if (ssl_params.q) + BN_free(ssl_params.q); + if (ssl_params.dp) + BN_free(ssl_params.dp); + if (ssl_params.dq) + BN_free(ssl_params.dq); + if (ssl_params.qinv) + BN_free(ssl_params.qinv); + if (ssl_params.plantext) + free(ssl_params.plantext); + if (ssl_params.ssl_verify_result) + free(ssl_params.ssl_verify_result); + if (ssl_params.ssl_sign_result) + free(ssl_params.ssl_sign_result); + return ret; +} +#endif + +static int rsa_async_test(int thread_num, __u64 lcore_mask, + __u64 hcore_mask, enum alg_op_type op_type) +{ + int ret = 0, cnt = 0, i; + int h_cpuid; + float speed = 0.0; + + /* Create poll thread at first */ + test_thrds_data[0].thread_num = 1; + test_thrds_data[0].op_type = op_type; + test_thrds_data[0].cpu_id = 0; + ret = pthread_create(&system_test_thrds[0], NULL, + _rsa_async_poll_test_thread, &test_thrds_data[0]); + if (ret) { + HPRE_TST_PRT("Create poll thread fail!\n"); + return ret; + } + + #ifdef WITH_OPENSSL_DIR + ret = rsa_openssl_key_gen_for_async_test(); + if(ret) { + HPRE_TST_PRT("openssl genkey for async thread test fail!"); + return 0; + } + #else + ret = rsa_sample_key_gen_for_async_test(); + if(ret) { + HPRE_TST_PRT("sample genkey for async thread test fail!"); + return 0; + } + #endif + + if (_get_one_bits(lcore_mask) > 0) + cnt = _get_one_bits(lcore_mask); + else if (_get_one_bits(lcore_mask) == 0 && + _get_one_bits(hcore_mask) == 0) + cnt = thread_num; + for (i = 1; i <= cnt; i++) { + test_thrds_data[i].thread_num = thread_num; + test_thrds_data[i].op_type = op_type; + test_thrds_data[i].cpu_id = _get_cpu_id(i - 1, lcore_mask); + gettimeofday(&test_thrds_data[i].start_tval, NULL); + ret = pthread_create(&system_test_thrds[i], NULL, + _rsa_async_op_test_thread, &test_thrds_data[i]); + if (ret) { + HPRE_TST_PRT("Create %dth thread fail!\n", i); + return ret; + } + } + for (i = 1; i <= thread_num - cnt; i++) { + h_cpuid = _get_cpu_id(i - 1, hcore_mask); + if (h_cpuid > 0) + h_cpuid += 64; + test_thrds_data[i + cnt].thread_num = thread_num; + test_thrds_data[i + cnt].op_type = op_type; + test_thrds_data[i + cnt].cpu_id = h_cpuid; + gettimeofday(&test_thrds_data[i + cnt].start_tval, NULL); + ret = pthread_create(&system_test_thrds[i + cnt], NULL, + _rsa_async_op_test_thread, &test_thrds_data[i + cnt]); + if (ret) { + HPRE_TST_PRT("Create %dth thread fail!\n", i); + return ret; + } + } + for (i = 1; i <= thread_num; i++) { + ret = pthread_join(system_test_thrds[i], NULL); + if (ret) { + HPRE_TST_PRT("Join %dth thread fail!\n", i); + return ret; + } + speed += test_thrds_data[i].perf; + } + + asyn_thread_exit = 1; + + ret = pthread_join(system_test_thrds[0], NULL); + if (ret) { + HPRE_TST_PRT("Join %dth thread fail!\n", i); + return ret; + } + + if (g_config.perf_test) + HPRE_TST_PRT("<< %s %u thread %s %s mode %u key_bits at %0.3f ops!\n", + g_config.trd_mode, g_config.trd_num, g_config.op, + g_config.alg_mode, g_config.key_bits, speed); + HPRE_TST_PRT("<< test finish!\n"); + return 0; +} + +static void *_dh_async_poll_test_thread(void *data) +{ + struct test_hpre_pthread_dt *pdata = data; + int ret, cpuid; + int pid = getpid(); + cpu_set_t mask; + int thread_id = (int)syscall(__NR_gettid); + __u32 count = 0; + + CPU_ZERO(&mask); + cpuid = pdata->cpu_id; + CPU_SET(cpuid, &mask); + if (cpuid) { + ret = pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask); + if (ret < 0) { + HPRE_TST_PRT("Proc-%d, thrd-%d:set affinity fail!\n", + pid, thread_id); + return NULL; + } + HPRE_TST_PRT("Proc-%d, poll thrd-%d bind to cpu-%d!\n", + pid, thread_id, cpuid); + } + + while (1) { + ret = wd_dh_poll(0, &count); + if (ret < 0) { + break; + } + + if (asyn_thread_exit) + break; + } + + if (g_config.with_log) + HPRE_TST_PRT("%s exit!\n", __func__); + return NULL; +} + +static int dh_async_test(int thread_num, __u64 lcore_mask, + __u64 hcore_mask, enum alg_op_type op_type) +{ + int i, ret, cnt = 0; + int h_cpuid; + float speed = 0.0; + + if (_get_one_bits(lcore_mask) > 0) + cnt = _get_one_bits(lcore_mask); + else if (_get_one_bits(lcore_mask) == 0 && + _get_one_bits(hcore_mask) == 0) + cnt = thread_num; + + /* Create poll thread at first */ + test_thrds_data[0].thread_num = 1; + test_thrds_data[0].op_type = op_type; + test_thrds_data[0].cpu_id = 0; + gettimeofday(&test_thrds_data[0].start_tval, NULL); + ret = pthread_create(&system_test_thrds[0], NULL, + _dh_async_poll_test_thread, &test_thrds_data[0]); + if (ret) { + HPRE_TST_PRT("Create poll thread fail!\n"); + return ret; + } + + for (i = 1; i <= cnt; i++) { + test_thrds_data[i].thread_num = thread_num; + test_thrds_data[i].op_type = op_type; + test_thrds_data[i].cpu_id = _get_cpu_id(i - 1, lcore_mask); + gettimeofday(&test_thrds_data[i].start_tval, NULL); + ret = pthread_create(&system_test_thrds[i], NULL, + _hpre_dh_sys_test_thread, &test_thrds_data[i]); + if (ret) { + HPRE_TST_PRT("Create %dth thread fail!\n", i); + return ret; + } + } + + for (i = 1; i <= thread_num - cnt; i++) { + h_cpuid = _get_cpu_id(i - 1, hcore_mask); + if (h_cpuid > 0) + h_cpuid += 64; + + test_thrds_data[i + cnt].thread_num = thread_num; + test_thrds_data[i + cnt].op_type = op_type; + test_thrds_data[i + cnt].cpu_id = h_cpuid; + gettimeofday(&test_thrds_data[i + cnt].start_tval, NULL); + ret = pthread_create(&system_test_thrds[i + cnt], NULL, + _hpre_dh_sys_test_thread, &test_thrds_data[i + cnt]); + if (ret) { + HPRE_TST_PRT("Create %dth thread fail!\n", i); + return ret; + } + } + + for (i = 1; i <= thread_num; i++) { + ret = pthread_join(system_test_thrds[i], NULL); + if (ret) { + HPRE_TST_PRT("Join %dth thread fail!\n", i); + return ret; + } + speed += test_thrds_data[i].perf; + } + + asyn_thread_exit = 1; + + ret = pthread_join(system_test_thrds[0], NULL); + if (ret) { + HPRE_TST_PRT("Join %dth thread fail!\n", i); + return ret; + } + + if (g_config.perf_test) + HPRE_TST_PRT("<< %s %u thread %s %s mode %u key_bits at %0.3f ops!\n", + g_config.trd_mode, g_config.trd_num, g_config.op, + g_config.alg_mode, g_config.key_bits, speed); + HPRE_TST_PRT("<< test finish!\n"); + + return 0; +} + +void *_hpre_sys_test_thread(void *data) +{ + enum alg_op_type op_type; + struct test_hpre_pthread_dt *pdata = data; + + op_type = pdata->op_type; + if (op_type > MAX_DH_TYPE && op_type < MAX_ECC_TYPE) { + return _ecc_sys_test_thread(data); + } else if (op_type > MAX_RSA_ASYNC_TYPE && op_type < MAX_DH_TYPE) { + return _hpre_dh_sys_test_thread(data); + } else { + return _hpre_rsa_sys_test_thread(data); + } + + return NULL; +} + +static void *_ecc_async_poll_test_thread(void *data) +{ + __u32 count = 0; + __u32 expt = 0; + int ret = 0; + + while (1) { + ret = wd_ecc_poll(expt, &count); + if (ret < 0) { + break; + } + + if (asyn_thread_exit) + break; + } + + if (g_config.with_log) + HPRE_TST_PRT("%s exit!\n", __func__); + + return NULL; +} + +static int ecc_async_test(int thread_num, __u64 lcore_mask, + __u64 hcore_mask, enum alg_op_type op_type) +{ + int i, ret, cnt = 0; + int h_cpuid; + float speed = 0.0; + + if (_get_one_bits(lcore_mask) > 0) + cnt = _get_one_bits(lcore_mask); + else if (_get_one_bits(lcore_mask) == 0 && + _get_one_bits(hcore_mask) == 0) + cnt = thread_num; + + /* Create poll thread at first */ + test_thrds_data[0].thread_num = 1; + test_thrds_data[0].op_type = op_type; + test_thrds_data[0].cpu_id = 0; + ret = pthread_create(&system_test_thrds[0], NULL, + _ecc_async_poll_test_thread, &test_thrds_data[0]); + if (ret) { + HPRE_TST_PRT("Create poll thread fail!\n"); + return ret; + } + + for (i = 1; i <= cnt; i++) { + test_thrds_data[i].thread_num = thread_num; + test_thrds_data[i].op_type = op_type; + test_thrds_data[i].cpu_id = _get_cpu_id(i - 1, lcore_mask); + gettimeofday(&test_thrds_data[i].start_tval, NULL); + ret = pthread_create(&system_test_thrds[i], NULL, + _ecc_sys_test_thread, &test_thrds_data[i]); + if (ret) { + HPRE_TST_PRT("Create %dth thread fail!\n", i); + return ret; + } + } + + for (i = 1; i <= thread_num - cnt; i++) { + h_cpuid = _get_cpu_id(i - 1, hcore_mask); + if (h_cpuid > 0) + h_cpuid += 64; + + test_thrds_data[i + cnt].thread_num = thread_num; + test_thrds_data[i + cnt].op_type = op_type; + test_thrds_data[i + cnt].cpu_id = h_cpuid; + gettimeofday(&test_thrds_data[i + cnt].start_tval, NULL); + ret = pthread_create(&system_test_thrds[i + cnt], NULL, + _ecc_sys_test_thread, &test_thrds_data[i + cnt]); + if (ret) { + HPRE_TST_PRT("Create %dth thread fail!\n", i); + return ret; + } + } + + for (i = 1; i <= thread_num; i++) { + ret = pthread_join(system_test_thrds[i], NULL); + if (ret) { + HPRE_TST_PRT("Join %dth thread fail!\n", i); + return ret; + } + speed += test_thrds_data[i].perf; + } + + asyn_thread_exit = 1; + + ret = pthread_join(system_test_thrds[0], NULL); + if (ret) { + HPRE_TST_PRT("Join %dth thread fail!\n", i); + return ret; + } + + if (g_config.perf_test) + HPRE_TST_PRT("<< %s %u thread %s %s mode %u key_bits at %0.3f ops!\n", + g_config.trd_mode, g_config.trd_num, g_config.op, + g_config.alg_mode, g_config.key_bits, speed); + + HPRE_TST_PRT("<< test finish!\n"); + + return 0; +} + +static void print_help(void); +static int parse_cmd_line(int argc, char *argv[]) +{ + int option_index = 0; + int rand_type_set = 0; + int msg_type_set = 0; + int id_len_set = 0; + int hash_type_set = 0; + int rand_len_set = 0; + int optind_t; + int ret = 0; + int bits; + int c; + + static struct option long_options[] = { + {"op", required_argument, 0, 0 }, + {"mode", required_argument, 0, 0 }, + {"dev_path", required_argument, 0, 0 }, + {"key_bits", required_argument, 0, 0 }, + {"cycles", required_argument, 0, 0}, + {"seconds", required_argument, 0, 0 }, + {"log", required_argument, 0, 0 }, + {"check", required_argument, 0, 0 }, + {"data_from", required_argument, 0, 0 }, + {"soft", no_argument, 0, 0 }, + {"perf", no_argument, 0, 0 }, + {"use_env", no_argument, 0, 0 }, + {"trd_mode", required_argument, 0, 0 }, + {"curve", required_argument, 0, 0 }, + {"msg_type", required_argument, 0, 0 }, + {"rand_type", required_argument, 0, 0 }, + {"hash_type", required_argument, 0, 0 }, + {"msg_len", required_argument, 0, 0 }, + {"rand_len", required_argument, 0, 0 }, + {"id_len", required_argument, 0, 0 }, + {"help", no_argument, 0, 'h' }, + {0, 0, 0, 0 } + }; + + while (1) { + optind_t = optind ? optind: 1; + + c = getopt_long(argc, argv, "t:c:", long_options, &option_index); + if (c == -1) { + if (optind_t < argc) { + print_help(); + ret = -1; + } + break; + } + + switch (c) { + case 0: + if (!strncmp(long_options[option_index].name, "mode", 4)) { + snprintf(g_config.alg_mode, sizeof(g_config.alg_mode), "%s", optarg); + } else if (!strncmp(long_options[option_index].name, "dev_path", 8)) { + snprintf(g_config.dev_path, sizeof(g_config.dev_path), "%s", optarg); + } else if (!strncmp(long_options[option_index].name, "key_bits", 8)) { + g_config.key_bits = strtoul((char *)optarg, NULL, 10); + } else if (!strncmp(long_options[option_index].name, "cycles", 6)) { + g_config.times = strtoul((char *)optarg, NULL, 10); + } else if (!strncmp(long_options[option_index].name, "seconds", 7)) { + g_config.seconds = strtoul((char *)optarg, NULL, 10); + } else if (!strncmp(long_options[option_index].name, "curve", 5)) { + snprintf(g_config.curve, sizeof(g_config.curve), "%s", optarg); + } else if (!strncmp(long_options[option_index].name, "data_from", 9)) { + g_config.data_from = strtoul((char *)optarg, NULL, 10); + if (g_config.data_from != 0 && g_config.data_from != 1) { + HPRE_TST_PRT("data must set 0 or 1\n"); + return -1; + } + } else if (!strncmp(long_options[option_index].name, "log", 3)) { + if (!strncmp(optarg, "y", 1) || !strncmp(optarg, "Y", 1)) + g_config.with_log = 1; + else + g_config.with_log = 0; + } else if (!strncmp(long_options[option_index].name, "check", 5)) { + if (!strncmp(optarg, "y", 1) || !strncmp(optarg, "Y", 1)) { + g_config.check = 1; + } else { + g_config.check = 0; + } + } else if (!strncmp(long_options[option_index].name, "soft", 4)) { + g_config.soft_test = 1; + } else if (!strncmp(long_options[option_index].name, "perf", 4)) { + g_config.perf_test = 1; + } else if (!strncmp(long_options[option_index].name, "use_env", 7)) { + g_config.use_env = 1; + } else if (!strncmp(long_options[option_index].name, "trd_mode", 8)) { + snprintf(g_config.trd_mode, sizeof(g_config.trd_mode), "%s", optarg); + } else if (!strncmp(long_options[option_index].name, "op", 2)) { + snprintf(g_config.op, sizeof(g_config.op), "%s", optarg); + } else if (!strncmp(long_options[option_index].name, "msg_type", 8)) { + if (!strncmp(optarg, "digest", 6)) + g_config.msg_type = MSG_DIGEST; + else if (!strncmp(optarg, "plaintext", 9)) + g_config.msg_type = MSG_PLAINTEXT; + msg_type_set = 1; + } else if (!strncmp(long_options[option_index].name, "msg_len", 7)) { + g_config.msg_len = strtoul((char *)optarg, NULL, 10); + } else if (!strncmp(long_options[option_index].name, "id_len", 6)) { + g_config.id_len = strtoul((char *)optarg, NULL, 10); + id_len_set = 1; + } else if (!strncmp(long_options[option_index].name, "rand_type", 9)) { + if (!strncmp(optarg, "param", 5)) + g_config.rand_type = RAND_PARAM; + else if (!strncmp(optarg, "cb", 2)) + g_config.rand_type = RAND_CB; + else if (!strncmp(optarg, "non", 2)) + g_config.rand_type = RAND_NON; + rand_type_set = 1; + } else if (!strncmp(long_options[option_index].name, "rand_len", 8)) { + g_config.k_len = strtoul((char *)optarg, NULL, 10); + rand_len_set = 1; + } else if (!strncmp(long_options[option_index].name, "hash_type", 9)) { + if (!strncmp(optarg, "non", 3)) + g_config.hash_type = HASH_NON; + else if (!strncmp(optarg, "sm3", 3)) + g_config.hash_type = HASH_SM3; + else if (!strncmp(optarg, "sha1", 4)) + g_config.hash_type = HASH_SHA1; + else if (!strncmp(optarg, "sha224", 6)) + g_config.hash_type = HASH_SHA224; + else if (!strncmp(optarg, "sha256", 6)) + g_config.hash_type = HASH_SHA256; + else if (!strncmp(optarg, "sha384", 6)) + g_config.hash_type = HASH_SHA384; + else if (!strncmp(optarg, "sha512", 6)) + g_config.hash_type = HASH_SHA512; + else if (!strncmp(optarg, "md4", 3)) + g_config.hash_type = HASH_MD4; + else if (!strncmp(optarg, "md5", 3)) + g_config.hash_type = HASH_MD5; + hash_type_set = 1; + } + break; + + case 't': + g_config.trd_num = strtoul((char *)optarg, NULL, 10); + if (g_config.trd_num <= 0 || g_config.trd_num > TEST_MAX_THRD) { + HPRE_TST_PRT("Invalid threads num:%d!\n", + g_config.trd_num); + HPRE_TST_PRT("Now set threads num as 2\n"); + g_config.trd_num = 2; + } + break; + case 'c': + if (optarg[0] != '0' || optarg[1] != 'x') { + HPRE_TST_PRT("Err:coremask should be hex!\n"); + return -EINVAL; + } + + if (strlen(optarg) > 34) { + HPRE_TST_PRT("warn:coremask is cut!\n"); + optarg[34] = 0; + } + + if (strlen(optarg) <= 18) { + g_config.core_mask[0] = strtoull(optarg, NULL, 16); + if (g_config.core_mask[0] & 0x1) { + HPRE_TST_PRT("Warn:cannot bind to core 0,\n"); + HPRE_TST_PRT("now run without binding\n"); + g_config.core_mask[0] = 0x0; /* no binding */ + } + g_config.core_mask[1] = 0; + } else { + int offset = 0; + char *temp; + + offset = strlen(optarg) - 16; + g_config.core_mask[0] = strtoull(&optarg[offset], NULL, 16); + if (g_config.core_mask[0] & 0x1) { + HPRE_TST_PRT("Warn:cannot bind to core 0,\n"); + HPRE_TST_PRT("now run without binding\n"); + g_config.core_mask[0] = 0x0; /* no binding */ + } + temp = malloc(64); + strcpy(temp, optarg); + temp[offset] = 0; + g_config.core_mask[1] = strtoull(temp, NULL, 16); + free(temp); + } + bits = _get_one_bits(g_config.core_mask[0]); + bits += _get_one_bits(g_config.core_mask[1]); + if (g_config.trd_num > bits) { + HPRE_TST_PRT("Coremask not covers all thrds,\n"); + HPRE_TST_PRT("Bind first %d thrds!\n", bits); + } else if (g_config.trd_num < bits) { + HPRE_TST_PRT("Coremask overflow,\n"); + HPRE_TST_PRT("Just try to bind all thrds!\n"); + }; + break; + + case '?': + case 'h': + print_help(); + ret = -1; + break; + + default: + printf("?? getopt returned character code 0%o ??\n", c); + break; + } + } + + if (g_config.perf_test) + g_config.data_from = 1; + + if (!strncmp(g_config.op, "sm2-verf", 8) && g_config.msg_type != MSG_PLAINTEXT) { + g_config.msg_type = MSG_PLAINTEXT; + HPRE_TST_PRT("message only support plantext!\n"); + } else if (g_config.data_from && (!strncmp(g_config.op, "sm2-sign", 8) || !strncmp(g_config.op, "sm2-verf", 8))) { + g_config.msg_type = MSG_DIGEST; + } + + if (g_config.data_from && + (rand_type_set || msg_type_set || id_len_set || rand_len_set || hash_type_set)) + HPRE_TST_PRT("The algorithm input parameters comes from samples, do not config it!\n"); + + return ret; +} + +int main(int argc, char *argv[]) +{ + enum alg_op_type alg_op_type = HPRE_ALG_INVLD_TYPE; + int ret = 0; + + ret = parse_cmd_line(argc, argv); + if (ret) + return -1; + + if (!strcmp(g_config.op, "rsa-gen")) { + if (!strcmp(g_config.trd_mode, "async")) + alg_op_type = RSA_ASYNC_GEN; + else + alg_op_type = RSA_KEY_GEN; + } else if (!strcmp(g_config.op, "rsa-vrf")) { + if (!strcmp(g_config.trd_mode, "async")) + alg_op_type = RSA_ASYNC_EN; + else + alg_op_type = RSA_PUB_EN; + } else if (!strcmp(g_config.op, "rsa-sgn")) { + if (!strcmp(g_config.trd_mode, "async")) + alg_op_type = RSA_ASYNC_DE; + else + alg_op_type = RSA_PRV_DE; + } else if (!strcmp(g_config.op, "dh-gen1")) { + if (!strcmp(g_config.trd_mode, "async")) + alg_op_type = DH_ASYNC_GEN; + else + alg_op_type = DH_GEN; + } else if (!strcmp(g_config.op, "dh-gen2")) { + if (!strcmp(g_config.trd_mode, "async")) + alg_op_type = DH_ASYNC_COMPUTE; + else + alg_op_type = DH_COMPUTE; + } else if (!strcmp(g_config.op, "ecdh-gen1")) { + if (!strcmp(g_config.trd_mode, "async")) + alg_op_type = ECDH_ASYNC_GEN; + else + alg_op_type = ECDH_GEN; + } else if (!strcmp(g_config.op, "ecdh-gen2")) { + if (!strcmp(g_config.trd_mode, "async")) + alg_op_type = ECDH_ASYNC_COMPUTE; + else + alg_op_type = ECDH_COMPUTE; + } else if (!strcmp(g_config.op, "ecdsa-sign")) { + if (!strcmp(g_config.trd_mode, "async")) + alg_op_type = ECDSA_ASYNC_SIGN; + else + alg_op_type = ECDSA_SIGN; + } else if (!strcmp(g_config.op, "ecdsa-verf")) { + if (!strcmp(g_config.trd_mode, "async")) + alg_op_type = ECDSA_ASYNC_VERF; + else + alg_op_type = ECDSA_VERF; + } else if (!strcmp(g_config.op, "x25519-gen1")) { + if (!strcmp(g_config.trd_mode, "async")) + alg_op_type = X25519_ASYNC_GEN; + else + alg_op_type = X25519_GEN; + } else if (!strcmp(g_config.op, "x25519-gen2")) { + if (!strcmp(g_config.trd_mode, "async")) + alg_op_type = X25519_ASYNC_COMPUTE; + else + alg_op_type = X25519_COMPUTE; + } else if (!strcmp(g_config.op, "x448-gen1")) { + if (!strcmp(g_config.trd_mode, "async")) + alg_op_type = X448_ASYNC_GEN; + else + alg_op_type = X448_GEN; + } else if (!strcmp(g_config.op, "x448-gen2")) { + if (!strcmp(g_config.trd_mode, "async")) + alg_op_type = X448_ASYNC_COMPUTE; + else + alg_op_type = X448_COMPUTE; + } else if (!strcmp(g_config.op, "sm2-sign")) { + if (!strcmp(g_config.trd_mode, "async")) + alg_op_type = SM2_ASYNC_SIGN; + else + alg_op_type = SM2_SIGN; + } else if (!strcmp(g_config.op, "sm2-verf")) { + if (!strcmp(g_config.trd_mode, "async")) + alg_op_type = SM2_ASYNC_VERF; + else + alg_op_type = SM2_VERF; + } else if (!strcmp(g_config.op, "sm2-enc")) { + if (!strcmp(g_config.trd_mode, "async")) + alg_op_type = SM2_ASYNC_ENC; + else + alg_op_type = SM2_ENC; + } else if (!strcmp(g_config.op, "sm2-dec")) { + if (!strcmp(g_config.trd_mode, "async")) + alg_op_type = SM2_ASYNC_DEC; + else + alg_op_type = SM2_DEC; + } else if (!strcmp(g_config.op, "sm2-kg")) { + if (!strcmp(g_config.trd_mode, "async")) + alg_op_type = SM2_ASYNC_KG; + else + alg_op_type = SM2_KG; + } else { + } + + if ((alg_op_type >= X25519_GEN && alg_op_type <= X25519_ASYNC_COMPUTE) || + !strncmp(g_config.op, "sm2", 3)) + g_config.key_bits = 256; + else if (alg_op_type >= X448_GEN && alg_op_type <= X448_ASYNC_COMPUTE) + g_config.key_bits = 448; + + ret = init_hpre_global_config(alg_op_type); + if (ret) { + HPRE_TST_PRT("failed to init_hpre_global_config, ret %d!\n", ret); + return -1; + } + + HPRE_TST_PRT(">> test start run %s :\n", g_config.op); + HPRE_TST_PRT(">> key_bits = %u\n", g_config.key_bits); + HPRE_TST_PRT(">> trd_mode = %s\n", g_config.trd_mode); + HPRE_TST_PRT(">> trd_num = %u\n", g_config.trd_num); + HPRE_TST_PRT(">> core_mask = [0x%llx][0x%llx]\n", g_config.core_mask[1], + g_config.core_mask[0]); + HPRE_TST_PRT(">> msg_type = %u\n", g_config.msg_type); + HPRE_TST_PRT(">> msg_len = 0x%x\n", g_config.msg_len); + HPRE_TST_PRT(">> id_len = 0x%x\n", g_config.id_len); + HPRE_TST_PRT(">> hash_type = %u\n", g_config.hash_type); + HPRE_TST_PRT(">> rand_type = %u\n", g_config.rand_type); + HPRE_TST_PRT(">> rand_len = 0x%x\n", g_config.k_len); + HPRE_TST_PRT(">> data_from = %u\n", g_config.data_from); + HPRE_TST_PRT(">> perf_test = %u\n", g_config.perf_test); + HPRE_TST_PRT(">> check = %u\n", g_config.check); + HPRE_TST_PRT(">> cycles = %u\n", g_config.times); + HPRE_TST_PRT(">> seconds = %u\n", g_config.seconds); + + if (g_config.perf_test) + HPRE_TST_PRT("performance test did not verify output!\n"); + + if (alg_op_type < MAX_RSA_SYNC_TYPE || + alg_op_type == DH_GEN || alg_op_type == DH_COMPUTE || + alg_op_type == ECDH_GEN || alg_op_type == ECDH_COMPUTE || + alg_op_type == ECDSA_SIGN || alg_op_type == ECDSA_VERF || + alg_op_type == X25519_GEN || alg_op_type == X25519_COMPUTE || + alg_op_type == X448_GEN || alg_op_type == X448_COMPUTE || + alg_op_type == SM2_SIGN || alg_op_type == SM2_VERF || + alg_op_type == SM2_ENC || alg_op_type == SM2_DEC || + alg_op_type == SM2_KG) + ret = hpre_sys_test(g_config.trd_num, g_config.core_mask[0], + g_config.core_mask[1], alg_op_type, g_config.dev_path, 0); + else if (alg_op_type > MAX_RSA_SYNC_TYPE && alg_op_type < MAX_RSA_ASYNC_TYPE) + ret = rsa_async_test(g_config.trd_num, g_config.core_mask[0], + g_config.core_mask[1], alg_op_type); + else if (alg_op_type == DH_ASYNC_GEN || alg_op_type == DH_ASYNC_COMPUTE) + ret = dh_async_test(g_config.trd_num, g_config.core_mask[0], + g_config.core_mask[1], alg_op_type); + else if (alg_op_type == ECDH_ASYNC_GEN || alg_op_type == ECDH_ASYNC_COMPUTE || + alg_op_type == ECDSA_ASYNC_SIGN || alg_op_type == ECDSA_ASYNC_VERF || + alg_op_type == X25519_ASYNC_GEN || alg_op_type == X25519_ASYNC_COMPUTE || + alg_op_type == X448_ASYNC_GEN || alg_op_type == X448_ASYNC_COMPUTE || + alg_op_type == SM2_ASYNC_SIGN || alg_op_type == SM2_ASYNC_VERF || + alg_op_type == SM2_ASYNC_ENC || alg_op_type == SM2_ASYNC_DEC || + alg_op_type == SM2_ASYNC_KG) + return ecc_async_test(g_config.trd_num, g_config.core_mask[0], + g_config.core_mask[1], alg_op_type); + else + ret = -1; /* to extend other test samples */ + + uninit_hpre_global_config(alg_op_type); + + return ret; + +} + +static void print_help(void) +{ + HPRE_TST_PRT("UPDATE:2021-02-01\n"); + HPRE_TST_PRT("NAME\n"); + HPRE_TST_PRT(" test_hisi_hpre: test wd hpre function,etc\n"); + HPRE_TST_PRT("USAGE\n"); + HPRE_TST_PRT(" test_hisi_hpre [--op=] [-t] [-c] [--mode=] [--help]\n"); + HPRE_TST_PRT(" test_hisi_hpre [--dev_path=] [--curve=] [--key_bits=]\n"); + HPRE_TST_PRT(" test_hisi_hpre [--seconds=] [--times=] [--trd_mode=]\n"); + HPRE_TST_PRT(" test_hisi_hpre [--msg_type=] [--msg_len=] [--id_len=]\n"); + HPRE_TST_PRT(" test_hisi_hpre [--rand_type=] [--rand_len=] [--hash_type=]\n"); + HPRE_TST_PRT("DESCRIPTION\n"); + HPRE_TST_PRT(" [--op=]:\n"); + HPRE_TST_PRT(" rsa-gen = RSA key generate test\n"); + HPRE_TST_PRT(" rsa-sgn = RSA signature test\n"); + HPRE_TST_PRT(" rsa-vrf = RSA verification test\n"); + HPRE_TST_PRT(" dh-gen1 = DH phase 1 key generate test\n"); + HPRE_TST_PRT(" dh-gen2 = DH phase 2 key generate test\n"); + HPRE_TST_PRT(" ecdh-gen1 = ECDH phase 1 key generate test\n"); + HPRE_TST_PRT(" ecdh-gen2 = ECDH phase 2 key generate test\n"); + HPRE_TST_PRT(" sm2-sign = SM2 sign test\n"); + HPRE_TST_PRT(" sm2-verf = SM2 verify test\n"); + HPRE_TST_PRT(" sm2-enc = SM2 encrypt test\n"); + HPRE_TST_PRT(" sm2-dec = SM2 decrypt test\n"); + HPRE_TST_PRT(" sm2-kg = SM2 key generate test\n"); + HPRE_TST_PRT(" [-t]: start thread total\n"); + HPRE_TST_PRT(" [-c]: mask for bind cpu core, as 0x3 bind to cpu-1 and cpu-2\n"); + HPRE_TST_PRT(" [--log=]:\n"); + HPRE_TST_PRT(" y\n"); + HPRE_TST_PRT(" n\n"); + HPRE_TST_PRT(" [--perf]: use test algorithm perf\n"); + HPRE_TST_PRT(" [--check=]:\n"); + HPRE_TST_PRT(" y: check result compared with openssl\n"); + HPRE_TST_PRT(" n: no check\n"); + HPRE_TST_PRT(" [--key_bits=]:key size (bits)\n"); + HPRE_TST_PRT(" [--mode=]: used by DH/RSA\n"); + HPRE_TST_PRT(" g2 = DH G2 mode\n"); + HPRE_TST_PRT(" com = common mode\n"); + HPRE_TST_PRT(" crt = RSA CRT mode\n"); + HPRE_TST_PRT(" [--trd_mode=]:\n"); + HPRE_TST_PRT(" sync = synchronize test\n"); + HPRE_TST_PRT(" async = asynchronize test\n"); + HPRE_TST_PRT(" [--curve=]: used by ECDH/ECDSA\n"); + HPRE_TST_PRT(" secp128R1 = 128 bit\n"); + HPRE_TST_PRT(" secp192K1 = 192 bit\n"); + HPRE_TST_PRT(" secp224R1 = 224 bit\n"); + HPRE_TST_PRT(" secp256K1 = 256bit\n"); + HPRE_TST_PRT(" brainpoolP320R1 = 320bit\n"); + HPRE_TST_PRT(" secp384R1 = 384bit\n"); + HPRE_TST_PRT(" secp521R1 = 521bit\n"); + HPRE_TST_PRT(" null = by set parameters\n"); + HPRE_TST_PRT(" [--msg_type=]: used by SM2\n"); + HPRE_TST_PRT(" digest = hash value\n"); + HPRE_TST_PRT(" plaintext\n"); + HPRE_TST_PRT(" [--msg_len=]: used by SM2, default size base on sample data\n"); + HPRE_TST_PRT(" [--rand_type=]: used by SM2\n"); + HPRE_TST_PRT(" param = from user input param\n"); + HPRE_TST_PRT(" cb = from user callback\n"); + HPRE_TST_PRT(" non = both not config\n"); + HPRE_TST_PRT(" [--rand_len=]: used by SM2, default size base on sample data\n"); + HPRE_TST_PRT(" [--id_len=]: used by SM2, default size base on sample data\n"); + HPRE_TST_PRT(" [--hash_type=]: used by SM2, default SM3\n"); + HPRE_TST_PRT(" sha1/sha224/sha256/sha384/sha512/md4/md5\n"); + HPRE_TST_PRT(" [--data_from=]: 0 - from openssl, 1 - from sample data\n"); + HPRE_TST_PRT(" [--dev_path=]: designed dev path\n"); + HPRE_TST_PRT(" [--seconds=]: test time set (s)\n"); + HPRE_TST_PRT(" [--cycles=]: test cycle set (times)\n"); + HPRE_TST_PRT(" [--help] = usage\n"); +} + diff --git a/uadk/test/hisi_hpre_test/test_hisi_hpre.h b/uadk/test/hisi_hpre_test/test_hisi_hpre.h new file mode 100644 index 0000000..757a4e9 --- /dev/null +++ b/uadk/test/hisi_hpre_test/test_hisi_hpre.h @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. */ + +#ifndef __HISI_TEST_HPRE_H +#define __HISI_TEST_HPRE_H + +enum alg_op_type { + HPRE_ALG_INVLD_TYPE, + RSA_KEY_GEN, + RSA_PUB_EN, + RSA_PRV_DE, + MAX_RSA_SYNC_TYPE, + RSA_ASYNC_EN, + RSA_ASYNC_DE, + RSA_ASYNC_GEN, + MAX_RSA_ASYNC_TYPE, + DH_GEN, + DH_ASYNC_GEN, + DH_COMPUTE, + DH_ASYNC_COMPUTE, + MAX_DH_TYPE, + ECDH_GEN, + ECDH_COMPUTE, + ECDH_ASYNC_GEN, + ECDH_ASYNC_COMPUTE, + MAX_ECDH_TYPE, + ECDSA_SIGN, + ECDSA_VERF, + ECDSA_ASYNC_SIGN, + ECDSA_ASYNC_VERF, + MAX_ECDSA_TYPE, + X25519_GEN, + X25519_COMPUTE, + X25519_ASYNC_GEN, + X25519_ASYNC_COMPUTE, + X448_GEN, + X448_COMPUTE, + X448_ASYNC_GEN, + X448_ASYNC_COMPUTE, + SM2_SIGN, + SM2_VERF, + SM2_ENC, + SM2_DEC, + SM2_KG, + SM2_ASYNC_SIGN, + SM2_ASYNC_VERF, + SM2_ASYNC_ENC, + SM2_ASYNC_DEC, + SM2_ASYNC_KG, + MAX_ECC_TYPE, + HPRE_MAX_OP_TYPE +}; + +enum alg_op_mode { + HPRE_ALG_INVLD_MODE, + RSA_COM_MD, + RSA_CRT_MD, + DH_COM_MD, + DH_G2, + HPRE_MAX_OP_MODE, +}; + + + +struct hpre_queue_mempool { + struct wd_queue *q; + void *base; + unsigned int *bitmap; + unsigned int block_size; + unsigned int block_num; + unsigned int mem_size; + unsigned int block_align_size; + unsigned int free_num; + unsigned int fail_times; + unsigned long long index; + sem_t sem; + int dev; +}; + +struct hpre_queue_mempool *hpre_test_mempool_create(struct wd_queue *q, + unsigned int block_size, unsigned int block_num); +void hpre_test_mempool_destroy(struct hpre_queue_mempool *pool); +void *hpre_test_alloc_buf(struct hpre_queue_mempool *pool, size_t sz); +void hpre_test_free_buf(struct hpre_queue_mempool *pool, void *buf); +#endif diff --git a/uadk/test/hisi_sec_test/Makefile.am b/uadk/test/hisi_sec_test/Makefile.am new file mode 100644 index 0000000..9955ab1 --- /dev/null +++ b/uadk/test/hisi_sec_test/Makefile.am @@ -0,0 +1,15 @@ +AM_CFLAGS=-Wall -Werror -fno-strict-aliasing -I$(top_srcdir)/include -pthread +AUTOMAKE_OPTIONS = subdir-objects + +bin_PROGRAMS=test_hisi_sec + +test_hisi_sec_SOURCES=test_hisi_sec.c + +if WD_STATIC_DRV +AM_CFLAGS+=-Bstatic +test_hisi_sec_LDADD=../../.libs/libwd.a ../../.libs/libwd_crypto.a \ + ../../.libs/libhisi_sec.a -lnuma +else +test_hisi_sec_LDADD=-L../../.libs -l:libwd.so.2 -l:libwd_crypto.so.2 -lnuma +endif +test_hisi_sec_LDFLAGS=-Wl,-rpath,'/usr/local/lib' diff --git a/uadk/test/hisi_sec_test/test_hisi_sec.c b/uadk/test/hisi_sec_test/test_hisi_sec.c new file mode 100644 index 0000000..7d5da7c --- /dev/null +++ b/uadk/test/hisi_sec_test/test_hisi_sec.c @@ -0,0 +1,4360 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "test_hisi_sec.h" +#include "wd_cipher.h" +#include "wd_digest.h" +#include "wd_aead.h" +#include "wd_sched.h" + +#define SEC_TST_PRT printf +#define HW_CTX_SIZE (24 * 1024) +#define BUFF_SIZE 1024 +#define IV_SIZE 256 +#define THREADS_NUM 64 +#define SVA_THREADS 64 +#define USE_CTX_NUM 64 +#define BYTES_TO_MB 20 + +#define SCHED_SINGLE "sched_single" +#define SCHED_NULL_CTX_SIZE 4 +#define TEST_WORD_LEN 4096 +#define MAX_ALGO_PER_TYPE 16 +#define MIN_SVA_BD_NUM 1 +#define AES_KEYSIZE_128 16 +#define AES_KEYSIZE_192 24 +#define AES_KEYSIZE_256 32 + +#define SGL_ALIGNED_BYTES 64 + +static struct wd_ctx_config g_ctx_cfg; +static struct wd_sched *g_sched; + +static long long int g_times; +static unsigned int g_thread_num; +static unsigned int g_testalg; +static unsigned int g_keylen; +static unsigned int g_pktlen; +static unsigned int g_block; +static unsigned int g_blknum; +static unsigned int g_direction; +static unsigned int g_stream; +static unsigned int g_alg_op_type; +static unsigned int g_ivlen; +static unsigned int g_syncmode; +static unsigned int g_use_env; +static unsigned int g_ctxnum; +static unsigned int g_data_fmt = WD_FLAT_BUF; +static unsigned int g_sgl_num = 0; +static pthread_spinlock_t lock = 0; + +static struct hash_testvec g_long_hash_tv; + +char *skcipher_names[MAX_ALGO_PER_TYPE] = + {"ecb(aes)", "cbc(aes)", "xts(aes)", "ofb(aes)", "cfb(aes)", "ecb(des3_ede)", + "cbc(des3_ede)", "cbc(sm4)", "xts(sm4)", "ofb(sm4)", "cfb(sm4)", "ecb(sm4)", + "cbc_cs1(aes)", "cbc_cs2(aes)", "cbc_cs3(aes)", NULL,}; + +enum digest_type { + LOCAL_SM3, + LOCAL_MD5, + LOCAL_SHA1, + LOCAL_SHA256, + LOCAL_SHA224, + LOCAL_SHA384, + LOCAL_SHA512, + LOCAL_SHA512_224, + LOCAL_SHA512_256, + LOCAL_AES_CMAC, + LOCAL_AES_GMAC_128, + LOCAL_AES_GMAC_192, + LOCAL_AES_GMAC_256, + LOCAL_AES_XCBC_MAC_96, +}; + +struct sva_bd { + char *src; + char *dst; +}; + +struct sva_bd_pool { + struct sva_bd *bds; +}; + +typedef struct _thread_data_t { + int tid; + int flag; + int mode; + int cpu_id; + struct sva_bd_pool *bd_pool; + struct wd_cipher_req *req; + struct wd_cipher_sess_setup *setup; + struct timeval start_tval; + unsigned long long send_task_num; + unsigned long long recv_task_num; +} thread_data_t; + +typedef struct wd_thread_res { + handle_t h_sess; + struct wd_digest_req *req; + struct wd_aead_req *areq; + unsigned long long send_num; + unsigned long long recv_num; + struct timeval start_tval; + unsigned long long sum_perf; +} thread_data_d; + +/** + * struct test_sec_option - Define the test sec app option list. + * @algclass: 0:cipher 1:digest + * @algtype: The sub alg type, reference func get_cipher_resource. + * @syncmode: 0:sync mode 1:async mode + */ +struct test_sec_option { + __u32 algclass; + __u32 algtype; + __u32 optype; + __u32 pktlen; + __u32 keylen; + __u32 times; + __u32 syncmode; + __u32 xmulti; + __u32 ctxnum; + __u32 block; + __u32 blknum; + __u32 stream_mode; + __u32 sgl_num; + __u32 use_env; +}; + +//static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; +static pthread_mutex_t test_sec_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_t system_test_thrds[THREADS_NUM]; +static thread_data_t thr_data[THREADS_NUM]; + +/* + * Calculate SGL unit size. + */ +static inline size_t cal_unit_sz(size_t sz, int sgl_num) +{ + return (sz + SGL_ALIGNED_BYTES - 1) & ~(SGL_ALIGNED_BYTES - 1); +} + +/* + * Create SGL or common memory buffer. + */ +static void *create_buf(int sgl, size_t sz, size_t unit_sz) +{ + struct wd_datalist *head, *p, *q; + int i, tail_sz, sgl_num; + void *buf; + + buf = calloc(sz, sizeof(char)); + if (!buf) { + SEC_TST_PRT("Fail to allocate buffer %ld size!\n", sz); + return NULL; + } + if (sgl == WD_FLAT_BUF) + return buf; + tail_sz = sz % unit_sz; + sgl_num = sz / unit_sz; /* the number with unit_sz bytes */ + + /* the additional slot is for tail_sz */ + head = calloc(sgl_num + 1, sizeof(struct wd_datalist)); + if (!head) { + SEC_TST_PRT("Fail to allocate memory for SGL head!\n"); + goto out; + } + for (i = 0, p = head, q = NULL; i < sgl_num;) { + p->data = buf + i * unit_sz; + p->len = unit_sz; + if (q) + q->next = p; + q = p; + p = &head[++i]; + } + if (tail_sz) { + p->data = buf + i * unit_sz; + p->len = tail_sz; + if (q) + q->next = p; + } + return head; +out: + free(buf); + return NULL; +} + +static void free_buf(int sgl, void *buf) +{ + struct wd_datalist *p; + + if (!buf) + return; + if (sgl == WD_FLAT_BUF) { + free(buf); + return; + } + p = (struct wd_datalist *)buf; + /* free the whole data buffer of SGL */ + free(p->data); + /* free SGL headers */ + free(buf); +} + +static inline void copy_mem(int dst_sgl, void *dst, int src_sgl, void *src, + size_t len) +{ + struct wd_datalist *p, *q; + size_t cnt = 0; + + if (dst_sgl == WD_FLAT_BUF && src_sgl == WD_FLAT_BUF) { + memcpy(dst, src, len); + } else if (dst_sgl == WD_FLAT_BUF && src_sgl == WD_SGL_BUF) { + p = (struct wd_datalist *)src; + while (p && len) { + if (p->len > len) { + memcpy(dst + cnt, p->data, len); + cnt += len; + len = 0; + } else { + memcpy(dst + cnt, p->data, p->len); + cnt += p->len; + len = len - p->len; + } + p = p->next; + } + } else if (dst_sgl == WD_SGL_BUF && src_sgl == WD_FLAT_BUF) { + p = (struct wd_datalist *)dst; + while (p && len) { + if (p->len > len) { + memcpy(p->data, src + cnt, len); + cnt += len; + len = 0; + } else { + memcpy(p->data, src + cnt, p->len); + cnt += p->len; + len = len - p->len; + } + p = p->next; + } + } else if (dst_sgl == WD_SGL_BUF && src_sgl == WD_SGL_BUF) { + p = (struct wd_datalist *)dst; + q = (struct wd_datalist *)src; + while (p && q && len) { + if (q->len > len) { + memcpy(p->data, q->data, len); + len = 0; + } else { + memcpy(p->data, q->data, q->len); + len = len - q->len; + } + p = p->next; + q = q->next; + } + if (len) + SEC_TST_PRT("%ld bytes not copied from src to dst.\n", + len); + } else + SEC_TST_PRT("Not supported memory type for copy.\n"); +} + +static void dump_mem(int sgl, unsigned char *buf, size_t len) +{ + struct wd_datalist *p; + size_t i, tmp; + + if (!buf) { + SEC_TST_PRT("Can't dump invalid buffer!"); + return; + } + + if (sgl == WD_FLAT_BUF) { + for (i = 0; i < len; i++) { + SEC_TST_PRT("\\0x%02x", buf[i]); + if ((i + 1) % 8 == 0) + SEC_TST_PRT("\n"); + } + SEC_TST_PRT("\n"); + } else if (sgl == WD_SGL_BUF) { + p = (struct wd_datalist *)buf; + for (i = 0, tmp = 0; i < len; i++, tmp++) { + if (tmp == p->len) { + p = p->next; + tmp = 0; + } + if (!p) { + SEC_TST_PRT("Left %ld bytes could not dump\n", + len - i); + return; + } + SEC_TST_PRT("\\0x%02x", *((char *)p->data + i)); + if ((i + 1) % 8 == 0) + SEC_TST_PRT("\n"); + } + SEC_TST_PRT("\n"); + } +} + +/* + * Parse alg & mode from variable g_testalg. + */ +int get_cipher_resource(struct cipher_testvec **alg_tv, int* alg, int* mode) +{ + struct cipher_testvec *tv; + int alg_type; + int mode_type; + + switch (g_testalg) { + case 0: + alg_type = WD_CIPHER_AES; + mode_type = WD_CIPHER_ECB; + switch (g_keylen) { + case AES_KEYSIZE_128: + tv = &aes_ecb_tv_template_128[0]; + break; + case AES_KEYSIZE_192: + tv = &aes_ecb_tv_template_192[0]; + break; + case AES_KEYSIZE_256: + tv = &aes_ecb_tv_template_256[0]; + break; + default: + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + break; + case 1: + alg_type = WD_CIPHER_AES; + mode_type = WD_CIPHER_CBC; + switch (g_keylen) { + case AES_KEYSIZE_128: + tv = &aes_cbc_tv_template_128[0]; + break; + case AES_KEYSIZE_192: + tv = &aes_cbc_tv_template_192[0]; + break; + case AES_KEYSIZE_256: + tv = &aes_cbc_tv_template_256[0]; + break; + default: + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + break; + case 2: + alg_type = WD_CIPHER_AES; + mode_type = WD_CIPHER_XTS; + switch (g_keylen / 2) { + case AES_KEYSIZE_128: + tv = &aes_xts_tv_template_256[0]; + break; + case AES_KEYSIZE_256: + tv = &aes_xts_tv_template_512[0]; + break; + default: + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + tv->ivlen = 16; + break; + case 3: + alg_type = WD_CIPHER_AES; + mode_type = WD_CIPHER_OFB; + switch (g_keylen) { + case AES_KEYSIZE_128: + tv = &aes_ofb_tv_template_128[0]; + break; + case AES_KEYSIZE_192: + tv = &aes_ofb_tv_template_192[0]; + break; + case AES_KEYSIZE_256: + tv = &aes_ofb_tv_template_256[0]; + break; + default: + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + break; + case 4: + alg_type = WD_CIPHER_AES; + mode_type = WD_CIPHER_CFB; + switch (g_keylen) { + case AES_KEYSIZE_128: + tv = &aes_cfb_tv_template_128[0]; + break; + case AES_KEYSIZE_192: + tv = &aes_cfb_tv_template_192[0]; + break; + case AES_KEYSIZE_256: + tv = &aes_cfb_tv_template_256[0]; + break; + default: + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + break; + + case 5: + alg_type = WD_CIPHER_3DES; + mode_type = WD_CIPHER_ECB; + if (g_keylen == 16) + tv = &des3_ecb_tv_template_128[0]; + else if (g_keylen == 24) + tv = &des3_ecb_tv_template_192[0]; + else { + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + break; + case 6: + alg_type = WD_CIPHER_3DES; + mode_type = WD_CIPHER_CBC; + if (g_keylen == 16) + tv = &des3_cbc_tv_template_128[0]; + else if (g_keylen == 24) + tv = &des3_cbc_tv_template_192[0]; + else { + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + break; + case 7: + alg_type = WD_CIPHER_SM4; + mode_type = WD_CIPHER_CBC; + if (g_keylen != 16) { + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + tv = &sm4_cbc_tv_template[0]; + break; + case 8: + alg_type = WD_CIPHER_SM4; + mode_type = WD_CIPHER_XTS; + if (g_keylen != 32) { + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + tv = &sm4_xts_tv_template[0]; + tv->ivlen = 16; + break; + case 9: + alg_type = WD_CIPHER_SM4; + mode_type = WD_CIPHER_OFB; + if (g_keylen != 16) { + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + tv = &sm4_ofb_tv_template_128[0]; + break; + case 10: + alg_type = WD_CIPHER_SM4; + mode_type = WD_CIPHER_CFB; + if (g_keylen != 16) { + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + tv = &sm4_cfb_tv_template_128[0]; + break; + case 11: + alg_type = WD_CIPHER_SM4; + mode_type = WD_CIPHER_ECB; + if (g_keylen != 16) { + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + tv = &sm4_ecb_tv_template_128[0]; + break; + case 12: + alg_type = WD_CIPHER_AES; + switch (g_keylen) { + case AES_KEYSIZE_128: + mode_type = WD_CIPHER_CBC_CS1; + tv = &aes_cbc_cs1_tv_template_128[0]; + break; + case AES_KEYSIZE_192: + mode_type = WD_CIPHER_CBC_CS1; + tv = &aes_cbc_cs1_tv_template_192[0]; + break; + case AES_KEYSIZE_256: + mode_type = WD_CIPHER_CBC_CS1; + tv = &aes_cbc_cs1_tv_template_256[0]; + break; + default: + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + break; + case 13: + alg_type = WD_CIPHER_AES; + switch (g_keylen) { + case AES_KEYSIZE_128: + mode_type = WD_CIPHER_CBC_CS2; + tv = &aes_cbc_cs1_tv_template_128[0]; + break; + case AES_KEYSIZE_192: + mode_type = WD_CIPHER_CBC_CS2; + tv = &aes_cbc_cs1_tv_template_192[0]; + break; + case AES_KEYSIZE_256: + mode_type = WD_CIPHER_CBC_CS2; + tv = &aes_cbc_cs1_tv_template_256[0]; + break; + default: + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + break; + case 14: + alg_type = WD_CIPHER_AES; + switch (g_keylen) { + case AES_KEYSIZE_128: + mode_type = WD_CIPHER_CBC_CS3; + tv = &aes_cbc_cs1_tv_template_128[0]; + break; + case AES_KEYSIZE_192: + mode_type = WD_CIPHER_CBC_CS3; + tv = &aes_cbc_cs1_tv_template_192[0]; + break; + case AES_KEYSIZE_256: + mode_type = WD_CIPHER_CBC_CS3; + tv = &aes_cbc_cs1_tv_template_256[0]; + break; + default: + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + break; + case 16: + alg_type = WD_CIPHER_AES; + mode_type = WD_CIPHER_CBC; + if (g_keylen != 16) { + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + tv = &aes_cbc_perf_128[0]; + break; + default: + SEC_TST_PRT("keylenth error, default test alg: %s\n", "ecb(aes)"); + return -EINVAL; + } + *alg = alg_type; + *mode = mode_type; + *alg_tv = tv; + + return 0; +} + +static int sched_single_poll_policy(handle_t h_sched_ctx, + __u32 expect, __u32 *count) +{ + return 0; +} + +static int init_ctx_config(int type, int mode) +{ + struct uacce_dev_list *list; + struct sched_params param; + int ret = 0; + int i; + + list = wd_get_accel_list("cipher"); + if (!list) { + printf("Fail to get cipher device\n"); + return -ENODEV; + } + + /* If there is no numa, we default config to zero */ + if (list->dev->numa_id < 0) + list->dev->numa_id = 0; + + g_sched = wd_sched_rr_alloc(SCHED_POLICY_RR, 1, + numa_max_node() + 1, + wd_cipher_poll_ctx); + if (!g_sched) { + printf("Fail to alloc sched!\n"); + goto out; + } + + g_sched->name = SCHED_SINGLE; + param.numa_id = list->dev->numa_id; + param.mode = mode; + param.type = 0; + param.begin = 0; + param.end = g_ctxnum - 1; + ret = wd_sched_rr_instance(g_sched, ¶m); + if (ret) { + printf("Fail to fill sched data!\n"); + goto out; + } + + if (g_use_env) + return wd_cipher_env_init(g_sched); + + memset(&g_ctx_cfg, 0, sizeof(struct wd_ctx_config)); + g_ctx_cfg.ctx_num = g_ctxnum; + g_ctx_cfg.ctxs = calloc(g_ctxnum, sizeof(struct wd_ctx)); + if (!g_ctx_cfg.ctxs) + return -ENOMEM; + + for (i = 0; i < g_ctxnum; i++) { + g_ctx_cfg.ctxs[i].ctx = wd_request_ctx(list->dev); + g_ctx_cfg.ctxs[i].op_type = type; + g_ctx_cfg.ctxs[i].ctx_mode = (__u8)mode; + } + + /*cipher init*/ + ret = wd_cipher_init(&g_ctx_cfg, g_sched); + if (ret) { + printf("Fail to cipher ctx!\n"); + goto out; + } + + wd_free_list_accels(list); + + return 0; +out: + free(g_ctx_cfg.ctxs); + wd_sched_rr_release(g_sched); + + return ret; +} + +static void uninit_config(void) +{ + int i; + + if (g_use_env) { + wd_cipher_env_uninit(); + return; + } + + wd_cipher_uninit(); + for (i = 0; i < g_ctx_cfg.ctx_num; i++) + wd_release_ctx(g_ctx_cfg.ctxs[i].ctx); + free(g_ctx_cfg.ctxs); + wd_sched_rr_release(g_sched); +} + +static void digest_uninit_config(void) +{ + int i; + + if (g_use_env) { + wd_digest_env_uninit(); + return; + } + + wd_digest_uninit(); + for (i = 0; i < g_ctx_cfg.ctx_num; i++) + wd_release_ctx(g_ctx_cfg.ctxs[i].ctx); + free(g_ctx_cfg.ctxs); +} + +static int test_sec_cipher_sync_once(void) +{ + struct cipher_testvec *tv = NULL; + handle_t h_sess = 0; + struct wd_cipher_sess_setup setup = {0}; + struct wd_cipher_req req; + struct timeval bg_tval, cur_tval; + int thread_id = (int)syscall(__NR_gettid); + unsigned long Perf = 0; + float speed, time_used; + int pid = getpid(); + int cnt = g_times; + size_t unit_sz; + int ret; + + /* config setup */ + ret = init_ctx_config(CTX_TYPE_ENCRYPT, CTX_MODE_SYNC); + if (ret) { + SEC_TST_PRT("Fail to init sigle ctx config!\n"); + return ret; + } + + /* config arg */ + memset(&req, 0, sizeof(struct wd_cipher_req)); + setup.alg = WD_CIPHER_AES; + setup.mode = WD_CIPHER_CBC; + if (g_direction == 0) + req.op_type = WD_CIPHER_ENCRYPTION; + else + req.op_type = WD_CIPHER_DECRYPTION; + + /* get resource */ + ret = get_cipher_resource(&tv, (int *)&setup.alg, (int *)&setup.mode); + + req.in_bytes = tv->len; + unit_sz = cal_unit_sz(req.in_bytes, g_sgl_num); + req.src = create_buf(g_data_fmt, req.in_bytes, unit_sz); + if (!req.src) { + ret = -ENOMEM; + goto out; + } + + SEC_TST_PRT("req src--------->:\n"); + if (g_direction == 0) + copy_mem(g_data_fmt, req.src, WD_FLAT_BUF, + (void *)tv->ptext, (size_t)tv->len); + else + copy_mem(g_data_fmt, req.src, WD_FLAT_BUF, + (void *)tv->ctext, (size_t)tv->len); + dump_mem(g_data_fmt, req.src, req.in_bytes); + + req.out_bytes = tv->len; + req.out_buf_bytes = g_pktlen; + req.data_fmt = g_data_fmt; + req.dst = create_buf(g_data_fmt, req.out_buf_bytes, unit_sz); + if (!req.dst) { + ret = -ENOMEM; + goto out_dst; + } + + req.iv = malloc(IV_SIZE); + if (!req.iv) { + ret = -ENOMEM; + goto out_iv; + } + if (setup.mode != WD_CIPHER_ECB) { + req.iv_bytes = strlen(tv->iv); + if (tv->ivlen > 0) + req.iv_bytes = tv->ivlen; + memset(req.iv, 0, req.iv_bytes); + if (tv->iv) + memcpy(req.iv, tv->iv, strlen(tv->iv)); + SEC_TST_PRT("cipher req iv--------->:\n"); + dump_mem(WD_FLAT_BUF, req.iv, req.iv_bytes); + } + + h_sess = wd_cipher_alloc_sess(&setup); + if (!h_sess) { + ret = -EINVAL; + goto out_sess; + } + + ret = wd_cipher_set_key(h_sess, (const __u8*)tv->key, tv->klen); + if (ret) { + SEC_TST_PRT("req set key failed!\n"); + goto out_key; + } + SEC_TST_PRT("cipher req key--------->:\n"); + + gettimeofday(&bg_tval, NULL); + while (cnt) { + ret = wd_do_cipher_sync(h_sess, &req); + cnt--; + } + gettimeofday(&cur_tval, NULL); + time_used = (float)((cur_tval.tv_sec - bg_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - bg_tval.tv_usec); + SEC_TST_PRT("time_used:%0.0f us, send task num:%lld\n", time_used, g_times); + speed = g_times / time_used * 1000000; + Perf = speed * g_pktlen / 1024; //B->KB + SEC_TST_PRT("Pro-%d, thread_id-%d, speed:%0.3f ops, Perf: %ld KB/s\n", pid, + thread_id, speed, Perf); + + SEC_TST_PRT("Test cipher sync function: output dst-->\n"); + dump_mem(g_data_fmt, req.dst, req.out_bytes); + +out_key: + wd_cipher_free_sess(h_sess); +out_sess: + free(req.iv); +out_iv: + free_buf(g_data_fmt, req.dst); +out_dst: + free_buf(g_data_fmt, req.src); +out: + uninit_config(); + + return ret; +} + +static void *async_cb(struct wd_cipher_req *req, void *data) +{ + // struct wd_cipher_req *req = (struct wd_cipher_req *)data; + // memcpy(&g_async_req, req, sizeof(struct wd_cipher_req)); + + return NULL; +} + +static int test_sec_cipher_async_once(void) +{ + struct cipher_testvec *tv = NULL; + struct wd_cipher_sess_setup setup = {0}; + thread_data_t data; + handle_t h_sess = 0; + struct wd_cipher_req req; + struct timeval bg_tval, cur_tval; + int thread_id = (int)syscall(__NR_gettid); + unsigned long Perf = 0; + float speed, time_used; + int pid = getpid(); + size_t unit_sz; + + int cnt = g_times; + __u32 num = 0; + int ret; + + memset(&data, 0, sizeof(thread_data_t)); + data.req = &req; + /* config setup */ + ret = init_ctx_config(CTX_TYPE_ENCRYPT, CTX_MODE_ASYNC); + + if (ret) { + SEC_TST_PRT("Fail to init sigle ctx config!\n"); + return ret; + } + + /* config arg */ + memset(&req, 0, sizeof(struct wd_cipher_req)); + setup.alg = WD_CIPHER_AES; + setup.mode = WD_CIPHER_CBC; + + if (g_direction == 0) + req.op_type = WD_CIPHER_ENCRYPTION; + else { + req.op_type = WD_CIPHER_DECRYPTION; + } + + /* get resource */ + ret = get_cipher_resource(&tv, (int *)&setup.alg, (int *)&setup.mode); + + req.data_fmt = g_data_fmt; + req.in_bytes = g_pktlen; + unit_sz = cal_unit_sz(req.in_bytes, g_sgl_num); + req.src = create_buf(g_data_fmt, req.in_bytes, unit_sz); + if (!req.src) { + ret = -ENOMEM; + goto out; + } + + SEC_TST_PRT("req src--------->:\n"); + if (g_direction == 0) + copy_mem(g_data_fmt, req.src, WD_FLAT_BUF, + (void *)tv->ptext, (size_t)tv->len); + else + copy_mem(g_data_fmt, req.src, WD_FLAT_BUF, + (void *)tv->ctext, (size_t)tv->len); + dump_mem(g_data_fmt, req.src, req.in_bytes); + + req.out_bytes = tv->len; + req.out_buf_bytes = BUFF_SIZE; + req.dst = create_buf(g_data_fmt, req.out_buf_bytes, unit_sz); + if (!req.dst) { + ret = -ENOMEM; + goto out_dst; + } + + req.iv = malloc(IV_SIZE); + if (!req.iv) { + ret = -ENOMEM; + goto out_iv; + } + if (setup.mode != WD_CIPHER_ECB) { + req.iv_bytes = strlen(tv->iv); + if (tv->ivlen > 0) + req.iv_bytes = tv->ivlen; + memset(req.iv, 0, req.iv_bytes); + if (tv->iv) + memcpy(req.iv, tv->iv, strlen(tv->iv)); + SEC_TST_PRT("cipher req iv--------->:\n"); + dump_mem(WD_FLAT_BUF, req.iv, req.iv_bytes); + } + h_sess = wd_cipher_alloc_sess(&setup); + if (!h_sess) { + ret = -1; + goto out_sess; + } + + ret = wd_cipher_set_key(h_sess, (const __u8*)tv->key, tv->klen); + if (ret) { + SEC_TST_PRT("req set key failed!\n"); + goto out_key; + } + SEC_TST_PRT("cipher req key--------->:\n"); + gettimeofday(&bg_tval, NULL); + while (cnt) { + req.cb = async_cb; + req.cb_param = &data; + ret = wd_do_cipher_async(h_sess, &req); + if (ret < 0) + goto out; + + if (g_use_env) { + cnt--; + continue; + } + /* poll thread */ +try_again: + num = 0; + ret = wd_cipher_poll_ctx(0, 1, &num); + if (ret < 0) { + if (ret == -EAGAIN) + goto try_again; // loop poll + else + goto out; + } + cnt--; + } + gettimeofday(&cur_tval, NULL); + time_used = (float)((cur_tval.tv_sec - bg_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - bg_tval.tv_usec); + SEC_TST_PRT("time_used:%0.0f us, send task num:%lld\n", time_used, g_times); + speed = g_times / time_used * 1000000; + Perf = speed * g_pktlen / 1024; //B->KB + SEC_TST_PRT("Pro-%d, thread_id-%d, speed:%0.3f ops, Perf: %ld KB/s\n", pid, + thread_id, speed, Perf); + + usleep(100000); + +out_key: + wd_cipher_free_sess(h_sess); +out_sess: + free(req.iv); +out_iv: + free_buf(g_data_fmt, req.dst); +out_dst: + free_buf(g_data_fmt, req.src); +out: + uninit_config(); + + return ret; +} + +static int test_sec_cipher_sync(void *arg) +{ + int thread_id = (int)syscall(__NR_gettid); + thread_data_t *pdata = (thread_data_t *)arg; + struct wd_cipher_sess_setup *setup = pdata->setup; + + struct wd_cipher_req *req = pdata->req; + struct cipher_testvec *tv = NULL; + + struct timeval cur_tval; + unsigned long Perf = 0, pktlen; + handle_t h_sess; + float speed, time_used; + int pid = getpid(); + int cnt = g_times; + int ret; + + /* get resource */ + ret = get_cipher_resource(&tv, (int *)&setup->alg, (int *)&setup->mode); + + h_sess = wd_cipher_alloc_sess(setup); + if (!h_sess) { + ret = -1; + return ret; + } + + pktlen = req->in_bytes; + SEC_TST_PRT("cipher req src--------->:\n"); + dump_mem(g_data_fmt, req->src, req->in_bytes); + + SEC_TST_PRT("ivlen = %d, cipher req iv--------->:\n", req->iv_bytes); + dump_mem(WD_FLAT_BUF, req->iv, req->iv_bytes); + + ret = wd_cipher_set_key(h_sess, (const __u8*)tv->key, tv->klen); + if (ret) { + SEC_TST_PRT("test sec cipher set key is failed!\n"); + goto out;; + } + + SEC_TST_PRT("cipher req key--------->:\n"); + + pthread_mutex_lock(&test_sec_mutex); + /* run task */ + while (cnt) { + ret = wd_do_cipher_sync(h_sess, req); + cnt--; + pdata->send_task_num++; + } + + gettimeofday(&cur_tval, NULL); + time_used = (float)((cur_tval.tv_sec - pdata->start_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - pdata->start_tval.tv_usec); + SEC_TST_PRT("time_used:%0.0f us, send task num:%lld\n", time_used, pdata->send_task_num++); + speed = pdata->send_task_num / time_used * 1000000; + Perf = speed * pktlen / 1024; //B->KB + SEC_TST_PRT("Pro-%d, thread_id-%d, speed:%0.3f ops, Perf: %ld KB/s\n", pid, + thread_id, speed, Perf); + + pthread_mutex_unlock(&test_sec_mutex); + + ret = 0; +out: + if (h_sess) + wd_cipher_free_sess(h_sess); + + return ret; +} + +static void *_test_sec_cipher_sync(void *data) +{ + test_sec_cipher_sync(data); + + return NULL; +} +/* + * Create 2 threads. one threads are enc/dec, and the other + * is polling. + */ +static int test_sync_create_threads(int thread_num, struct wd_cipher_req *reqs, struct wd_cipher_sess_setup *setups) +{ + pthread_attr_t attr; + int i, ret; + + if (thread_num > THREADS_NUM - 1) { + SEC_TST_PRT("can't creat %d threads", thread_num - 1); + return -EINVAL; + } + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + for (i = 0; i < thread_num; i++) { + thr_data[i].tid = i; + thr_data[i].req = &reqs[i]; + thr_data[i].setup = &setups[i]; + gettimeofday(&thr_data[i].start_tval, NULL); + ret = pthread_create(&system_test_thrds[i], &attr, _test_sec_cipher_sync, &thr_data[i]); + if (ret) { + SEC_TST_PRT("Failed to create thread, ret:%d\n", ret); + return ret; + } + } + + thr_data[i].tid = i; + pthread_attr_destroy(&attr); + for (i = 0; i < thread_num; i++) { + ret = pthread_join(system_test_thrds[i], NULL); + } + + return 0; +} + +static int sec_cipher_sync_test(void) +{ + struct wd_cipher_req req[THREADS_NUM]; + struct wd_cipher_sess_setup setup[THREADS_NUM]; + void *iv = NULL; + int parallel = g_thread_num; + struct cipher_testvec *tv = NULL; + int test_alg, test_mode; + int ret, i, j; + unsigned int len; + size_t unit_sz; + + memset(req, 0, sizeof(struct wd_cipher_req) * THREADS_NUM); + memset(setup, 0, sizeof(struct wd_cipher_sess_setup) * THREADS_NUM); + + /* get resource */ + ret = get_cipher_resource(&tv, &test_alg, &test_mode); + + iv = calloc(1, IV_SIZE * THREADS_NUM); + if (!iv) { + ret = -ENOMEM; + goto out_iv; + } + + + len = g_pktlen < tv->len ? g_pktlen : tv->len; + unit_sz = cal_unit_sz(len, g_sgl_num); + for (i = 0; i < parallel; i++) { + req[i].src = create_buf(g_data_fmt, len, unit_sz); + if (!req[i].src) { + ret = -ENOMEM; + goto out_src; + } + req[i].in_bytes = len; + copy_mem(g_data_fmt, req[i].src, WD_FLAT_BUF, + (void *)tv->ptext, (size_t)tv->len); + + req[i].out_bytes = tv->len; + req[i].out_buf_bytes = len; + req[i].dst = create_buf(g_data_fmt, len, unit_sz); + if (!req[i].dst) { + ret = -ENOMEM; + goto out_dst; + } + + req[i].data_fmt = g_data_fmt; + + req[i].iv = iv + i * IV_SIZE; + if (test_mode != WD_CIPHER_ECB) { + req[i].iv_bytes = strlen(tv->iv); + if (tv->ivlen > 0) + req[i].iv_bytes = tv->ivlen; + memcpy(req[i].iv, tv->iv, strlen(tv->iv)); + } + + /* config arg */ + setup[i].alg = test_alg; + setup[i].mode = test_mode; + + if (g_direction == 0) + req[i].op_type = WD_CIPHER_ENCRYPTION; + else + req[i].op_type = WD_CIPHER_DECRYPTION; + } + + ret = init_ctx_config(CTX_TYPE_ENCRYPT, CTX_MODE_SYNC); + if (ret) { + SEC_TST_PRT("fail to init sigle ctx config!\n"); + goto out_cfg; + } + + ret = test_sync_create_threads(parallel, req, setup); + if (ret < 0) + goto out_thr; + +out_thr: + uninit_config(); +out_cfg: + for (j = 0; j < i; j++) { + free_buf(g_data_fmt, req[j].src); + free_buf(g_data_fmt, req[j].dst); + } + free(iv); + return ret; +out_dst: + free_buf(g_data_fmt, req[i].src); +out_src: + for (j = 0; j < i; j++) { + free_buf(g_data_fmt, req[j].src); + free_buf(g_data_fmt, req[j].dst); + } +out_iv: + free(iv); + return ret; +} + +static int test_sec_cipher_async(void *arg) +{ + int thread_id = (int)syscall(__NR_gettid); + thread_data_t *pdata = (thread_data_t *)arg; + struct wd_cipher_sess_setup *setup = pdata->setup; + struct wd_cipher_req *req = pdata->req; + struct cipher_testvec *tv = NULL; + int cnt = g_times; + handle_t h_sess; + int ret; + + /* get resource */ + ret = get_cipher_resource(&tv, (int *)&setup->alg, (int *)&setup->mode); + + h_sess = wd_cipher_alloc_sess(setup); + if (!h_sess) { + ret = -1; + return ret; + } + + ret = wd_cipher_set_key(h_sess, (const __u8*)tv->key, tv->klen); + if (ret) { + SEC_TST_PRT("test sec cipher set key is failed!\n"); + goto out;; + } + + pthread_mutex_lock(&test_sec_mutex); + // pthread_cond_wait(&cond, &test_sec_mutex); + /* run task */ + do { +try_do_again: + ret = wd_do_cipher_async(h_sess, req); + if (ret == -EBUSY) { // busy + usleep(100); + goto try_do_again; + } else if (ret) { + SEC_TST_PRT("test sec cipher send req is error!\n"); + pthread_mutex_unlock(&test_sec_mutex); + goto out; + } + cnt--; + } while (cnt); + pthread_mutex_unlock(&test_sec_mutex); + SEC_TST_PRT("Test cipher async function thread_id is:%d\n", thread_id); + + ret = 0; +out: + if (h_sess) + wd_cipher_free_sess(h_sess); + + return ret; +} + +static void *_test_sec_cipher_async(void *data) +{ + test_sec_cipher_async(data); + + return NULL; +} + +/* create poll threads */ +static void *poll_func(void *arg) +{ + __u32 count = 0; + __u32 index = 0; + int ret; + + int expt = g_times * g_thread_num; + + while (1) { + ret = g_sched->poll_policy(g_sched->h_sched_ctx, 1, &count); + if (ret != -EAGAIN && ret < 0) { + SEC_TST_PRT("poll ctx is error----------->\n"); + break; + } + + index += count; + count = 0; + if (expt == index) { + break; + } + } + + pthread_exit(NULL); +} + +/* + * Create 2 threads. one threads are enc/dec, and the other + * is polling. + */ +static int test_async_create_threads(int thread_num, struct wd_cipher_req *reqs, struct wd_cipher_sess_setup *setups) +{ + int thread_id = (int)syscall(__NR_gettid); + struct timeval cur_tval; + unsigned long Perf = 0; + float speed, time_used; + pthread_attr_t attr; + int i, ret; + + if (thread_num > THREADS_NUM - 1) { + SEC_TST_PRT("can't creat %d threads", thread_num - 1); + return -EINVAL; + } + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + for (i = 0; i < thread_num; i++) { + thr_data[i].tid = i; + thr_data[i].req = &reqs[i]; + thr_data[i].setup = &setups[i]; + gettimeofday(&thr_data[i].start_tval, NULL); + ret = pthread_create(&system_test_thrds[i], &attr, _test_sec_cipher_async, &thr_data[i]); + if (ret) { + SEC_TST_PRT("Failed to create thread, ret:%d\n", ret); + return ret; + } + } + + ret = pthread_create(&system_test_thrds[i], &attr, poll_func, &thr_data[i]); + + pthread_attr_destroy(&attr); + + for (i = 0; i < thread_num; i++) { + ret = pthread_join(system_test_thrds[i], NULL); + if (ret) { + SEC_TST_PRT("Join %dth thread fail!\n", i); + return ret; + } + } + // asyn_thread_exit = 1; + ret = pthread_join(system_test_thrds[i], NULL); + if (ret) { + SEC_TST_PRT("Join %dth thread fail!\n", i); + return ret; + } + + gettimeofday(&cur_tval, NULL); + time_used = (double)((cur_tval.tv_sec - thr_data[0].start_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - thr_data[0].start_tval.tv_usec); + SEC_TST_PRT("time_used:%0.0f us, send task num:%llu\n", time_used, g_times * g_thread_num); + speed = g_times * g_thread_num / time_used * 1000000; + Perf = speed * g_pktlen / 1024; //B->KB + SEC_TST_PRT("Pro-%d, thread_id-%d, speed:%f ops, Perf: %ld KB/s\n", + getpid(), thread_id, speed, Perf); + + return 0; +} + +static int sec_cipher_async_test(void) +{ + struct wd_cipher_req req[THREADS_NUM]; + struct wd_cipher_sess_setup setup[THREADS_NUM] = {{0}}; + void *iv = NULL; + struct cipher_testvec *tv = NULL; + thread_data_t datas[THREADS_NUM]; + int parallel = g_thread_num; + int test_alg, test_mode; + int i, j, ret; + size_t unit_sz; + + memset(datas, 0, sizeof(thread_data_t) * THREADS_NUM); + memset(req, 0, sizeof(struct wd_cipher_req) * THREADS_NUM); + /* get resource */ + ret = get_cipher_resource(&tv, &test_alg, &test_mode); + int step = sizeof(char) * TEST_WORD_LEN; + iv = malloc(step * THREADS_NUM); + if (!iv) { + ret = -ENOMEM; + goto out_iv; + } + + unit_sz = cal_unit_sz(g_pktlen, g_sgl_num); + for (i = 0; i < parallel; i++) { + req[i].src = create_buf(g_data_fmt, g_pktlen, unit_sz); + if (!req[i].src) { + ret = -ENOMEM; + goto out_src; + } + req[i].in_bytes = g_pktlen; + copy_mem(g_data_fmt, req[i].src, WD_FLAT_BUF, + (void *)tv->ptext, (size_t)tv->len); + + req[i].dst = create_buf(g_data_fmt, g_pktlen, unit_sz); + if (!req[i].dst) { + ret = -ENOMEM; + goto out_dst; + } + req[i].out_bytes = tv->len; + req[i].out_buf_bytes = g_pktlen; + + req[i].data_fmt = g_data_fmt; + + req[i].iv = iv + i * step; + memset(req[i].iv, 0, step); + if (test_mode != WD_CIPHER_ECB) { + req[i].iv_bytes = strlen(tv->iv); + if (tv->ivlen > 0) + req[i].iv_bytes = tv->ivlen; + memcpy(req[i].iv, tv->iv, req[i].iv_bytes); + } + + /* config arg */ + setup[i].alg = test_alg; + setup[i].mode = test_mode; + + if (g_direction == 0) + req[i].op_type = WD_CIPHER_ENCRYPTION; + else + req[i].op_type = WD_CIPHER_DECRYPTION; + req[i].cb = async_cb; + req[i].cb_param = &datas[i]; + } + + ret = init_ctx_config(CTX_TYPE_ENCRYPT, CTX_MODE_ASYNC); + if (ret) { + SEC_TST_PRT("fail to init sigle ctx config!\n"); + goto out_cfg; + } + + ret = test_async_create_threads(parallel, req, setup); + if (ret < 0) + goto out_thr; + +out_thr: + uninit_config(); +out_cfg: + for (j = 0; j < i; j++) { + free_buf(g_data_fmt, req[j].src); + free_buf(g_data_fmt, req[j].dst); + } + free(iv); + return ret; +out_dst: + free_buf(g_data_fmt, req[i].src); +out_src: + for (j = 0; j < i; j++) { + free_buf(g_data_fmt, req[j].src); + free_buf(g_data_fmt, req[j].dst); + } +out_iv: + free(iv); + return ret; +} + +/* ------------------digest alg, nomal mode and hmac mode------------------ */ +static handle_t sched_digest_init(handle_t h_sched_ctx, void *sched_param) +{ + return (handle_t)0; +} + +static __u32 sched_digest_pick_next_ctx(handle_t h_sched_ctx, + void *sched_key, const int sched_mode) +{ + /* alway return first ctx */ + return 0; +} + +static int init_digest_ctx_config(int type, int mode) +{ + struct uacce_dev_list *list; + struct wd_sched sched; + int ret; + + if (g_use_env) + return wd_digest_env_init(NULL); + + list = wd_get_accel_list("digest"); + if (!list) + return -ENODEV; + + + memset(&g_ctx_cfg, 0, sizeof(struct wd_ctx_config)); + g_ctx_cfg.ctx_num = 1; + g_ctx_cfg.ctxs = calloc(1, sizeof(struct wd_ctx)); + if (!g_ctx_cfg.ctxs) + return -ENOMEM; + + /* Just use first found dev to test here */ + g_ctx_cfg.ctxs[0].ctx = wd_request_ctx(list->dev); + if (!g_ctx_cfg.ctxs[0].ctx) { + ret = -EINVAL; + SEC_TST_PRT("Fail to request ctx!\n"); + goto out; + } + g_ctx_cfg.ctxs[0].op_type = type; + g_ctx_cfg.ctxs[0].ctx_mode = mode; + + sched.name = SCHED_SINGLE; + sched.pick_next_ctx = sched_digest_pick_next_ctx; + sched.poll_policy = sched_single_poll_policy; + sched.sched_init = sched_digest_init; + /* digest init */ + ret = wd_digest_init(&g_ctx_cfg, &sched); + if (ret) { + SEC_TST_PRT("Fail to digest ctx!\n"); + goto out; + } + + wd_free_list_accels(list); + + return 0; +out: + free(g_ctx_cfg.ctxs); + + return ret; +} + +int get_digest_resource(struct hash_testvec **alg_tv, int* alg, int* mode) +{ + struct hash_testvec *tmp_tv; + struct hash_testvec *tv = NULL; + int alg_type; + int mode_type = 0; + + switch (g_testalg) { + case 0: + switch (g_alg_op_type) { + case 0: + mode_type = WD_DIGEST_NORMAL; + SEC_TST_PRT("test alg: %s\n", "normal(sm3)"); + tv = &sm3_tv_template[0]; + break; + case 1: + mode_type = WD_DIGEST_HMAC; + SEC_TST_PRT("test alg: %s\n", "hmac(sm3)"); + tv = &hmac_sm3_tv_template[0]; + break; + } + tv->dsize = 32; + alg_type = WD_DIGEST_SM3; + break; + case 1: + switch (g_alg_op_type) { + case 0: + mode_type = WD_DIGEST_NORMAL; + SEC_TST_PRT("test alg: %s\n", "normal(md5)"); + tv = &md5_tv_template[0]; + break; + case 1: + mode_type = WD_DIGEST_HMAC; + SEC_TST_PRT("test alg: %s\n", "hmac(md5)"); + tv = &hmac_md5_tv_template[0]; + break; + } + tv->dsize = 16; + alg_type = WD_DIGEST_MD5; + break; + case 2: + switch (g_alg_op_type) { + case 0: + mode_type = WD_DIGEST_NORMAL; + SEC_TST_PRT("test alg: %s\n", "normal(sha1)"); + tv = &sha1_tv_template[0]; + break; + case 1: + mode_type = WD_DIGEST_HMAC; + SEC_TST_PRT("test alg: %s\n", "hmac(sha1)"); + tv = &hmac_sha1_tv_template[0]; + break; + } + tv->dsize = 20; + alg_type = WD_DIGEST_SHA1; + break; + case 3: + switch (g_alg_op_type) { + case 0: + mode_type = WD_DIGEST_NORMAL; + SEC_TST_PRT("test alg: %s\n", "normal(sha256)"); + tv = &sha256_tv_template[0]; + break; + case 1: + mode_type = WD_DIGEST_HMAC; + SEC_TST_PRT("test alg: %s\n", "hmac(sha256)"); + tv = &hmac_sha256_tv_template[0]; + break; + } + tv->dsize = 32; + alg_type = WD_DIGEST_SHA256; + break; + case 4: + switch (g_alg_op_type) { + case 0: + mode_type = WD_DIGEST_NORMAL; + SEC_TST_PRT("test alg: %s\n", "normal(sha224)"); + tv = &sha224_tv_template[0]; + break; + case 1: + mode_type = WD_DIGEST_HMAC; + SEC_TST_PRT("test alg: %s\n", "hmac(sha224)"); + tv = &hmac_sha224_tv_template[0]; + break; + } + tv->dsize = 28; + alg_type = WD_DIGEST_SHA224; + break; + case 5: + switch (g_alg_op_type) { + case 0: + mode_type = WD_DIGEST_NORMAL; + SEC_TST_PRT("test alg: %s\n", "normal(sha384)"); + tv = &sha384_tv_template[0]; + break; + case 1: + mode_type = WD_DIGEST_HMAC; + SEC_TST_PRT("test alg: %s\n", "hmac(sha384)"); + tv = &hmac_sha384_tv_template[0]; + break; + } + tv->dsize = 48; + alg_type = WD_DIGEST_SHA384; + break; + case 6: + switch (g_alg_op_type) { + case 0: + mode_type = WD_DIGEST_NORMAL; + SEC_TST_PRT("test alg: %s\n", "normal(sha512)"); + tv = &sha512_tv_template[0]; + break; + case 1: + mode_type = WD_DIGEST_HMAC; + SEC_TST_PRT("test alg: %s\n", "hmac(sha512)"); + tv = &hmac_sha512_tv_template[0]; + break; + } + tv->dsize = 64; + alg_type = WD_DIGEST_SHA512; + break; + case 7: + switch (g_alg_op_type) { + case 0: + mode_type = WD_DIGEST_NORMAL; + SEC_TST_PRT("test alg: %s\n", "normal(sha512_224)"); + tv = &sha512_224_tv_template[0]; + break; + case 1: + mode_type = WD_DIGEST_HMAC; + SEC_TST_PRT("test alg: %s\n", "hmac(sha512_224"); + tv = &hmac_sha512_224_tv_template[0]; + break; + } + tv->dsize = 28; + alg_type = WD_DIGEST_SHA512_224; + break; + case 8: + switch (g_alg_op_type) { + case 0: + mode_type = WD_DIGEST_NORMAL; + SEC_TST_PRT("test alg: %s\n", "normal(sha512_256)"); + tv = &sha512_256_tv_template[0]; + break; + case 1: + mode_type = WD_DIGEST_HMAC; + SEC_TST_PRT("test alg: %s\n", "hmac(sha512_256)"); + tv = &hmac_sha512_256_tv_template[0]; + break; + } + tv->dsize = 32; + alg_type = WD_DIGEST_SHA512_256; + break; + case 9: + switch (g_alg_op_type) { + case 1: + mode_type = WD_DIGEST_HMAC; + SEC_TST_PRT("test alg: %s\n", "aes-cmac"); + tv = &aes_cmac_tv_template[0]; + break; + } + tv->dsize = 16; + alg_type = WD_DIGEST_AES_CMAC; + break; + case 10: + switch (g_alg_op_type) { + case 1: + mode_type = WD_DIGEST_HMAC; + SEC_TST_PRT("test alg: %s\n", "aes-gmac-128"); + tv = &aes_gmac_128_tv_template[0]; + break; + } + tv->dsize = 16; + alg_type = WD_DIGEST_AES_GMAC; + break; + case 11: + switch (g_alg_op_type) { + case 1: + mode_type = WD_DIGEST_HMAC; + SEC_TST_PRT("test alg: %s\n", "aes-gmac-192"); + tv = &aes_gmac_192_tv_template[0]; + break; + } + tv->dsize = 16; + alg_type = WD_DIGEST_AES_GMAC; + break; + case 12: + switch (g_alg_op_type) { + case 1: + mode_type = WD_DIGEST_HMAC; + SEC_TST_PRT("test alg: %s\n", "aes-gmac-256"); + tv = &aes_gmac_256_tv_template[0]; + break; + } + tv->dsize = 16; + alg_type = WD_DIGEST_AES_GMAC; + break; + case 13: + switch (g_alg_op_type) { + case 1: + mode_type = WD_DIGEST_HMAC; + SEC_TST_PRT("test alg: %s\n", "aes-xcbc-mac-96"); + tv = &aes_xcbc_mac_96_tv_template[0]; + break; + } + tv->dsize = 12; + alg_type = WD_DIGEST_AES_XCBC_MAC_96; + break; + case 14: + switch (g_alg_op_type) { + case 1: + mode_type = WD_DIGEST_HMAC; + SEC_TST_PRT("test alg: %s\n", "aes-xcbc-prf-128"); + tv = &aes_xcbc_mac_96_tv_template[0]; + break; + } + tv->dsize = 16; + alg_type = WD_DIGEST_AES_XCBC_PRF_128; + break; + + default: + SEC_TST_PRT("keylenth error, default test alg: %s\n", "normal(sm3)"); + return -EINVAL; + } + if (g_ivlen == 1) { + tmp_tv = tv; + tv = &g_long_hash_tv; + tv->dsize = tmp_tv->dsize; + } else if (g_ivlen == 2) { + tmp_tv = tv; + tv = &hmac_abnormal1024_tv_template[0]; + tv->dsize = tmp_tv->dsize; + } else if (g_ivlen == 3) { + tmp_tv = tv; + tv = &hmac_abnormal512_tv_template[0]; + tv->dsize = tmp_tv->dsize; + } + + *alg = alg_type; + *mode = mode_type; + *alg_tv = tv; + + return 0; +} + +static int sec_digest_sync_once(void) +{ + struct wd_digest_sess_setup setup = {0}; + struct hash_testvec *tv = NULL; + handle_t h_sess = 0; + struct wd_digest_req req; + struct timeval start_tval; + struct timeval cur_tval; + unsigned long Perf = 0; + float speed, time_used; + unsigned long cnt = g_times; + int ret; + size_t unit_sz; + + /* config setup */ + ret = init_digest_ctx_config(CTX_TYPE_ENCRYPT, CTX_MODE_SYNC); + if (ret) { + SEC_TST_PRT("Fail to init sigle ctx config!\n"); + return ret; + } + + /* config arg */ + memset(&req, 0, sizeof(struct wd_digest_req)); + get_digest_resource(&tv, (int *)&setup.alg, (int *)&setup.mode); + + unit_sz = cal_unit_sz(BUFF_SIZE, g_sgl_num); + req.in = create_buf(g_data_fmt, BUFF_SIZE, unit_sz); + if (!req.in) { + ret = -ENOMEM; + goto out_src; + } + + req.in_bytes = tv->psize; + + SEC_TST_PRT("req src in--------->:\n"); + copy_mem(g_data_fmt, req.in, WD_FLAT_BUF, + (void *)tv->plaintext, tv->psize); + dump_mem(g_data_fmt, req.in, req.in_bytes); + + req.out = create_buf(WD_FLAT_BUF, BUFF_SIZE, unit_sz); + if (!req.out) { + ret = -ENOMEM; + goto out_dst; + } + + req.out_buf_bytes = BUFF_SIZE; + req.out_bytes = tv->dsize; + printf("req.data_fmtaaaa = %u\n", g_data_fmt); + req.data_fmt = g_data_fmt; + req.has_next = 0; + + h_sess = wd_digest_alloc_sess(&setup); + if (!h_sess) { + ret = -EINVAL; + goto out_sess; + } + + /* if mode is HMAC, should set key */ + if (setup.mode == WD_DIGEST_HMAC) { + ret = wd_digest_set_key(h_sess, (const __u8 *)tv->key, tv->ksize); + if (ret) { + SEC_TST_PRT("sess set key failed!\n"); + goto out_key; + } + + if (g_testalg == LOCAL_AES_GMAC_128 || + g_testalg == LOCAL_AES_GMAC_192 || + g_testalg == LOCAL_AES_GMAC_256) { + req.iv = malloc(sizeof(char) * 16); + if (!req.iv) { + SEC_TST_PRT("failed to alloc iv memory!\n"); + goto out_key; + } + memcpy(req.iv, tv->iv, 16); + req.iv_bytes = 16; + } + } + + gettimeofday(&start_tval, NULL); + while (cnt) { + ret = wd_do_digest_sync(h_sess, &req); + cnt--; + } + gettimeofday(&cur_tval, NULL); + + time_used = (float)((cur_tval.tv_sec - start_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - start_tval.tv_usec); + speed = g_times / time_used * 1000000; + Perf = speed * req.in_bytes / 1024; + SEC_TST_PRT("time_used:%0.0f us, send task num:%lld\n", time_used, g_times); + SEC_TST_PRT("Pro-%d, thread_id-%d, speed:%0.3f ops, Perf: %ld KB/s\n", getpid(), + (int)syscall(__NR_gettid), speed, Perf); + dump_mem(WD_FLAT_BUF, req.out, req.out_bytes); + +out_key: + wd_digest_free_sess(h_sess); +out_sess: + free_buf(WD_FLAT_BUF, req.out); +out_dst: + free_buf(g_data_fmt, req.in); +out_src: + digest_uninit_config(); + free(req.iv); + + return ret; +} + +static int sec_digest_sync_stream_cmp(void) +{ + struct wd_digest_sess_setup setup = {0}; + struct hash_testvec *tv = NULL; + handle_t h_sess = 0; + struct wd_digest_req req; + unsigned long cnt = g_times; + int ret; + size_t unit_sz; + + /* config setup */ + ret = init_digest_ctx_config(CTX_TYPE_ENCRYPT, CTX_MODE_SYNC); + if (ret) { + SEC_TST_PRT("Fail to init sigle ctx config!\n"); + return ret; + } + + /* config arg */ + memset(&req, 0, sizeof(struct wd_digest_req)); + get_digest_resource(&tv, (int *)&setup.alg, (int *)&setup.mode); + + unit_sz = cal_unit_sz(BUFF_SIZE * 8, g_sgl_num); + req.in = create_buf(g_data_fmt, BUFF_SIZE * 8, unit_sz); + if (!req.in) { + ret = -ENOMEM; + goto out_src; + } + + req.in_bytes = tv->psize; + copy_mem(g_data_fmt, req.in, WD_FLAT_BUF, + (void *)tv->plaintext, tv->psize); + + req.out = create_buf(WD_FLAT_BUF, BUFF_SIZE, unit_sz); + if (!req.out) { + ret = -ENOMEM; + goto out_dst; + } + + req.out_buf_bytes = BUFF_SIZE; + req.out_bytes = tv->dsize; + req.data_fmt = g_data_fmt; + req.has_next = 0; + + h_sess = wd_digest_alloc_sess(&setup); + if (!h_sess) { + ret = -EINVAL; + goto out_sess; + } + + /* if mode is HMAC, should set key */ + ret = wd_digest_set_key(h_sess, (const __u8 *)tv->key, tv->ksize); + if (ret) { + SEC_TST_PRT("sess set key failed!\n"); + goto out_key; + } + + while (cnt) { + ret = wd_do_digest_sync(h_sess, &req); + cnt--; + } + + SEC_TST_PRT("one hash BD dump the out memory, cmp the stream mode:\n"); + dump_mem(WD_FLAT_BUF, req.out, 16); + +out_key: + wd_digest_free_sess(h_sess); +out_sess: + free_buf(WD_FLAT_BUF, req.out); +out_dst: + free_buf(g_data_fmt, req.in); +out_src: + digest_uninit_config(); + + return ret; +} + +static int sec_digest_sync_stream_mode(void) +{ + struct wd_digest_sess_setup setup; + struct hash_testvec *tv = NULL; + handle_t h_sess = 0; + struct wd_digest_req req; + unsigned long cnt = g_times; + int ret, data_len; + void *bak_in = NULL; + + /* config setup */ + ret = init_digest_ctx_config(CTX_TYPE_ENCRYPT, CTX_MODE_SYNC); + if (ret) { + SEC_TST_PRT("Fail to init sigle ctx config!\n"); + return ret; + } + + /* config arg */ + memset(&req, 0, sizeof(struct wd_digest_req)); + get_digest_resource(&tv, (int *)&setup.alg, (int *)&setup.mode); + + req.in = malloc(BUFF_SIZE * 8); + if (!req.in) { + SEC_TST_PRT("req src in mem malloc failed!\n"); + ret = -1; + goto out; + } + bak_in = req.in; + + memcpy(req.in, tv->plaintext, tv->psize); + req.in_bytes = tv->psize; + + req.out = malloc(BUFF_SIZE); + if (!req.out) { + SEC_TST_PRT("req dst out mem malloc failed!\n"); + ret = -1; + goto out; + } + + req.out_buf_bytes = BUFF_SIZE; + req.out_bytes = tv->dsize; + req.data_fmt = g_data_fmt; + req.has_next = 0; + + h_sess = wd_digest_alloc_sess(&setup); + if (!h_sess) { + ret = -1; + goto out; + } + data_len = tv->psize; + + /* if mode is HMAC, should set key */ + ret = wd_digest_set_key(h_sess, (const __u8 *)tv->key, tv->ksize); + if (ret) { + SEC_TST_PRT("sess set key failed!\n"); + goto out; + } + + while (cnt) { + do { + if (data_len > 256) { // soft block size + req.in_bytes = 256; + data_len -= 256; + req.has_next = 1; + } else { + req.has_next = 0; + req.in_bytes = data_len; + } + ret = wd_do_digest_sync(h_sess, &req); + + if (ret) + goto out; + + if (req.has_next != 0) + req.in += 256; + else + break; + } while (true); + data_len = tv->psize; + req.has_next = 0; + req.in = bak_in; + memcpy(req.in, tv->plaintext, tv->psize); + cnt--; + } + SEC_TST_PRT("long hash BD dump the out memory:--------->:\n"); + dump_mem(g_data_fmt, req.out, 16); + +out: + free(req.out); + free(req.in); + if (h_sess) + wd_digest_free_sess(h_sess); + + digest_uninit_config(); + return ret; +} + +void *digest_sync_stream_mode_send_td(void *data) +{ + int thread_id = (int)syscall(__NR_gettid); + struct wd_digest_sess_setup setup = {0}; + struct hash_testvec *tv = NULL; + unsigned long cnt = g_times; + struct wd_digest_req req; + int ret, data_len; + void *bak_in = NULL; + handle_t h_sess = 0; + + get_digest_resource(&tv, (int *)&setup.alg, (int *)&setup.mode); + + h_sess = wd_digest_alloc_sess(&setup); + if (!h_sess) { + ret = -EINVAL; + return NULL; + } + + /* if mode is HMAC, should set key */ + ret = wd_digest_set_key(h_sess, (const __u8 *)tv->key, tv->ksize); + if (ret) { + SEC_TST_PRT("sess set key failed!\n"); + goto out_key; + } + + /* config arg */ + memset(&req, 0, sizeof(struct wd_digest_req)); + + req.in = malloc(BUFF_SIZE * 8); + if (!req.in) { + SEC_TST_PRT("req src in mem malloc failed!\n"); + ret = -1; + goto out; + } + bak_in = req.in; + + memcpy(req.in, tv->plaintext, tv->psize); + req.in_bytes = tv->psize; + + req.out = malloc(BUFF_SIZE); + if (!req.out) { + SEC_TST_PRT("req dst out mem malloc failed!\n"); + ret = -1; + goto out; + } + + req.out_buf_bytes = BUFF_SIZE; + req.out_bytes = tv->dsize; + req.data_fmt = g_data_fmt; + req.has_next = 0; + + data_len = tv->psize; + + while (cnt) { + do { + if (data_len > 256) { // soft block size + req.in_bytes = 256; + data_len -= 256; + req.has_next = 1; + } else { + req.has_next = 0; + req.in_bytes = data_len; + } + ret = wd_do_digest_sync(h_sess, &req); + + if (ret) + goto out; + + if (req.has_next != 0) + req.in += 256; + else + break; + + } while (true); + data_len = tv->psize; + req.has_next = 0; + req.in = bak_in; + memcpy(req.in, tv->plaintext, tv->psize); + cnt--; + } + SEC_TST_PRT("Pid - %d, thread-id - %d, long hash BD dump the out memory:\n", getpid(), thread_id); + dump_mem(g_data_fmt, req.out, 16); +out_key: + wd_digest_free_sess(h_sess); +out: + if (req.out) + free(req.out); + if (bak_in) + free(bak_in); + return NULL; +} + +static int sec_digest_sync_stream_mode_multi(void) +{ + static pthread_t sendtd[64]; + thread_data_d td_data; + int i, ret; + + /* config setup */ + ret = init_digest_ctx_config(CTX_TYPE_ENCRYPT, CTX_MODE_SYNC); + if (ret) { + SEC_TST_PRT("Fail to init sigle ctx config!\n"); + return ret; + } + + /* send thread */ + td_data.send_num = g_times; + td_data.recv_num = g_times; + for (i = 0; i < g_thread_num; i++) { + ret = pthread_create(&sendtd[i], NULL, digest_sync_stream_mode_send_td, &td_data); + if (ret) { + SEC_TST_PRT("Create send thread fail!\n"); + goto out_thr; + } + } + + /* join thread */ + for (i = 0; i < g_thread_num; i++) { + ret = pthread_join(sendtd[i], NULL); + if (ret) { + SEC_TST_PRT("Join sendtd thread fail!\n"); + goto out_thr; + } + } + +out_thr: + digest_uninit_config(); + return ret; +} + +static void *digest_async_cb(void *data) +{ + // struct wd_digest_req *req = (struct wd_digest_req *)data; + // memcpy(&g_async_req, req, sizeof(struct wd_digest_req)); + + return NULL; +} + +void *digest_send_thread(void *data) +{ + thread_data_d *td_data = data; + struct wd_digest_req *req = td_data->req; + int try_cnt = 0; + unsigned long cnt = 0; + int ret; + + while (cnt < td_data->send_num) { + req->cb = digest_async_cb; + ret = wd_do_digest_async(td_data->h_sess, req); + if (ret < 0) { + usleep(100); + try_cnt++; + if (try_cnt > 100) { + SEC_TST_PRT("Test digest current send fail 100 times !\n"); + break; + } + continue; + } + cnt++; + } + + SEC_TST_PRT("Test digest multi send : %lu pkg !\n", cnt); + return NULL; +} + +void *digest_poll_thread(void *data) +{ + thread_data_d *td_data = data; + struct wd_digest_req *req = td_data->req; + unsigned int recv = 0; + int expt = td_data->recv_num; + struct timeval cur_tval; + unsigned long Perf = 0; + float speed, time_used; + int cnt = 0; + int ret; + + while (cnt < td_data->recv_num) { + ret = wd_digest_poll_ctx(0, expt, &recv); + if (ret < 0) + usleep(100); + + if (recv == 0) { + SEC_TST_PRT("current digest async poll --0-- pkg!\n"); + break; + } + expt -= recv; + cnt += recv; + recv = 0; + } + gettimeofday(&cur_tval, NULL); + + pthread_mutex_lock(&test_sec_mutex); + time_used = (float)((cur_tval.tv_sec - td_data->start_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - td_data->start_tval.tv_usec); + SEC_TST_PRT("time_used:%0.0f us, send task num:%d\n", time_used, cnt); + speed = cnt / time_used * 1000000; + Perf = speed * req->in_bytes / 1024; //B->KB + SEC_TST_PRT("Pro-%d, thread_id-%d, speed:%0.3f ops, Perf: %ld KB/s\n", getpid(), + (int)syscall(__NR_gettid), speed, Perf); + pthread_mutex_unlock(&test_sec_mutex); + + return NULL; +} + +void *digest_sync_send_thread(void *data) +{ + thread_data_d *td_data = data; + struct wd_digest_req *req = td_data->req; + struct timeval cur_tval, start_tval; + unsigned long Perf = 0; + float speed, time_used; + int ret; + int cnt = 0; + + gettimeofday(&start_tval, NULL); + while (cnt < td_data->send_num) { + ret = wd_do_digest_sync(td_data->h_sess, req); + if (ret < 0) { + usleep(100); + SEC_TST_PRT("Test digest current send fail: have send %u pkg !\n", cnt); + continue; + } + cnt++; + } + gettimeofday(&cur_tval, NULL); + + pthread_mutex_lock(&test_sec_mutex); + time_used = (float)((cur_tval.tv_sec - start_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - start_tval.tv_usec); + SEC_TST_PRT("time_used:%0.0f us, send task num:%lld\n", time_used, td_data->send_num); + speed = td_data->send_num / time_used * 1000000; + Perf = speed * req->in_bytes / 1024; //B->KB + SEC_TST_PRT("Pro-%d, thread_id-%d, speed:%0.3f ops, Perf: %ld KB/s\n", getpid(), + (int)syscall(__NR_gettid), speed, Perf); + pthread_mutex_unlock(&test_sec_mutex); + + return NULL; +} + +static int sec_digest_async_once(void) +{ + struct hash_testvec *tv = 0; + struct wd_digest_sess_setup setup = {0}; + static pthread_t send_td; + static pthread_t poll_td; + struct wd_digest_req req; + thread_data_d td_data; + handle_t h_sess = 0; + int test_alg = 0; + int test_mode = 0; + int ret; + size_t unit_sz; + + /* config setup */ + ret = init_digest_ctx_config(CTX_TYPE_ENCRYPT, CTX_MODE_ASYNC); + if (ret) { + SEC_TST_PRT("Fail to init sigle ctx config!\n"); + return ret; + } + + /* config arg */ + get_digest_resource(&tv, &test_alg, &test_mode); + memset(&req, 0, sizeof(struct wd_digest_req)); + setup.alg = test_alg; + setup.mode = test_mode; + + unit_sz = cal_unit_sz(BUFF_SIZE, g_sgl_num); + req.in = create_buf(g_data_fmt, BUFF_SIZE, unit_sz); + if (!req.in) { + ret = -ENOMEM; + goto out_src; + } + + req.in_bytes = tv->psize; + + SEC_TST_PRT("req src in--------->:\n"); + copy_mem(g_data_fmt, req.in, WD_FLAT_BUF, + (void *)tv->plaintext, (size_t)tv->psize); + dump_mem(g_data_fmt, req.in, req.in_bytes); + + req.out = create_buf(WD_FLAT_BUF, BUFF_SIZE, unit_sz); + if (!req.out) { + ret = -ENOMEM; + goto out_dst; + } + req.out_buf_bytes = BUFF_SIZE; + req.out_bytes = tv->dsize; + req.has_next = 0; + req.data_fmt = g_data_fmt; + + h_sess = wd_digest_alloc_sess(&setup); + if (!h_sess) { + ret = -EINVAL; + goto out_sess; + } + + /* if mode is HMAC, should set key */ + if (setup.mode == WD_DIGEST_HMAC) { + ret = wd_digest_set_key(h_sess, (const __u8 *)tv->key, tv->ksize); + if (ret) { + SEC_TST_PRT("sess set key failed!\n"); + goto out_key; + } + } + + /* send thread */ + td_data.req = &req; + td_data.h_sess = h_sess; + td_data.send_num = g_times; + td_data.recv_num = g_times * g_thread_num; + gettimeofday(&td_data.start_tval, NULL); + ret = pthread_create(&send_td, NULL, digest_send_thread, &td_data); + if (ret) { + SEC_TST_PRT("kthread create fail at %s", __func__); + goto out_thr; + } + + /* poll thread */ + ret = pthread_create(&poll_td, NULL, digest_poll_thread, &td_data); + if (ret) { + SEC_TST_PRT("kthread create fail at %s", __func__); + goto out_thr; + } + + ret = pthread_join(send_td, NULL); + if (ret) { + SEC_TST_PRT("pthread_join fail at %s", __func__); + goto out_thr; + } + + ret = pthread_join(poll_td, NULL); + if (ret) { + SEC_TST_PRT("pthread_join fail at %s", __func__); + goto out_thr; + } + dump_mem(WD_FLAT_BUF, req.out, req.out_bytes); + +out_thr: +out_key: + wd_digest_free_sess(h_sess); +out_sess: + free_buf(WD_FLAT_BUF, req.out); +out_dst: + free_buf(g_data_fmt, req.in); +out_src: + digest_uninit_config(); + + return ret; +} + +static int sec_digest_sync_multi(void) +{ + struct wd_digest_sess_setup setup = {0}; + struct hash_testvec *tv = NULL; + handle_t h_sess = 0; + struct wd_digest_req req; + static pthread_t sendtd[64]; + thread_data_d td_data; + int i, ret; + size_t unit_sz; + + /* config setup */ + ret = init_digest_ctx_config(CTX_TYPE_ENCRYPT, CTX_MODE_SYNC); + if (ret) { + SEC_TST_PRT("Fail to init sigle ctx config!\n"); + return ret; + } + + /* config arg */ + memset(&req, 0, sizeof(struct wd_digest_req)); + get_digest_resource(&tv, (int *)&setup.alg, (int *)&setup.mode); + + unit_sz = cal_unit_sz(BUFF_SIZE, g_sgl_num); + req.in = create_buf(g_data_fmt, BUFF_SIZE, unit_sz); + if (!req.in) { + ret = -ENOMEM; + goto out_src; + } + + memcpy(req.in, tv->plaintext, tv->psize); + req.in_bytes = tv->psize; + + SEC_TST_PRT("req src in--------->:\n"); + dump_mem(g_data_fmt, req.in, req.in_bytes); + + req.out = create_buf(g_data_fmt, BUFF_SIZE, unit_sz); + if (!req.out) { + ret = -ENOMEM; + goto out_dst; + } + req.out_buf_bytes = BUFF_SIZE; + req.out_bytes = tv->dsize; + req.has_next = 0; + + h_sess = wd_digest_alloc_sess(&setup); + if (!h_sess) { + ret = -EINVAL; + goto out_sess; + } + + /* if mode is HMAC, should set key */ + if (setup.mode == WD_DIGEST_HMAC) { + ret = wd_digest_set_key(h_sess, (const __u8 *)tv->key, tv->ksize); + if (ret) { + SEC_TST_PRT("sess set key failed!\n"); + goto out_key; + } + } + + td_data.h_sess = h_sess; + td_data.req = &req; + + /* send thread */ + td_data.send_num = g_times; + td_data.recv_num = g_times; + td_data.sum_perf = 0; + for (i = 0; i < g_thread_num; i++) { + ret = pthread_create(&sendtd[i], NULL, digest_sync_send_thread, &td_data); + if (ret) { + SEC_TST_PRT("Create send thread fail!\n"); + goto out_thr; + } + } + + /* join thread */ + for (i = 0; i < g_thread_num; i++) { + ret = pthread_join(sendtd[i], NULL); + if (ret) { + SEC_TST_PRT("Join sendtd thread fail!\n"); + goto out_thr; + } + } + + SEC_TST_PRT("digest sync %u threads, speed:%llu ops, perf: %llu KB/s\n", + g_thread_num, td_data.sum_perf, + (td_data.sum_perf >> 10) * req.in_bytes); + + dump_mem(g_data_fmt, req.out, req.out_bytes); +out_thr: +out_key: + wd_digest_free_sess(h_sess); +out_sess: + free_buf(g_data_fmt, req.out); +out_dst: + free_buf(g_data_fmt, req.in); +out_src: + digest_uninit_config(); + + return ret; +} + +static int sec_digest_async_multi(void) +{ + struct hash_testvec *tv = 0; + struct wd_digest_sess_setup setup = {0}; + handle_t h_sess = 0; + struct wd_digest_req req; + static pthread_t sendtd[64]; + static pthread_t polltd; + thread_data_d td_data; + int test_alg = 0; + int test_mode = 0; + int i, ret; + + /* config setup */ + ret = init_digest_ctx_config(CTX_TYPE_ENCRYPT, CTX_MODE_ASYNC); + if (ret) { + SEC_TST_PRT("Fail to init sigle ctx config!\n"); + return ret; + } + + /* config arg */ + get_digest_resource(&tv, &test_alg, &test_mode); + memset(&req, 0, sizeof(struct wd_digest_req)); + setup.alg = test_alg; + setup.mode = test_mode; + + req.in = malloc(BUFF_SIZE); + if (!req.in) { + SEC_TST_PRT("req src in mem malloc failed!\n"); + ret = -1; + goto out; + } + memcpy(req.in, tv->plaintext, tv->psize); + req.in_bytes = tv->psize; + SEC_TST_PRT("req src in--------->:\n"); + dump_mem(WD_FLAT_BUF, req.in, tv->psize); + req.out = malloc(BUFF_SIZE); + if (!req.out) { + SEC_TST_PRT("req dst out mem malloc failed!\n"); + ret = -1; + goto out; + } + + req.out_buf_bytes = BUFF_SIZE; + req.out_bytes = tv->dsize; + req.has_next = 0; + h_sess = wd_digest_alloc_sess(&setup); + if (!h_sess) { + ret = -1; + goto out; + } + + /* if mode is HMAC, should set key */ + if (setup.mode == WD_DIGEST_HMAC) { + ret = wd_digest_set_key(h_sess, (const __u8 *)tv->key, tv->ksize); + if (ret) { + SEC_TST_PRT("sess set key failed!\n"); + goto out; + } + } + + td_data.h_sess = h_sess; + td_data.req = &req; + + /* send thread */ + td_data.send_num = g_times; + td_data.recv_num = g_times * g_thread_num; + td_data.sum_perf = 0; + gettimeofday(&td_data.start_tval, NULL); + for (i = 0; i < g_thread_num; i++) { + ret = pthread_create(&sendtd[i], NULL, digest_send_thread, &td_data); + if (ret) { + SEC_TST_PRT("Create send thread fail!\n"); + return ret; + } + } + + /* poll thread */ + ret = pthread_create(&polltd, NULL, digest_poll_thread, &td_data); + if (ret) { + SEC_TST_PRT("Create poll thread fail!\n"); + return ret; + } + + /* join thread */ + for (i = 0; i < g_thread_num; i++) { + ret = pthread_join(sendtd[i], NULL); + if (ret) { + SEC_TST_PRT("Join sendtd thread fail!\n"); + return ret; + } + } + ret = pthread_join(polltd, NULL); + if (ret) { + SEC_TST_PRT("Join polltd thread fail!\n"); + return ret; + } + + dump_mem(WD_FLAT_BUF, req.out, req.out_bytes); +out: + if (req.in) + free(req.in); + if (req.out) + free(req.out); + if (h_sess) + wd_digest_free_sess(h_sess); + digest_uninit_config(); + + return ret; +} + +/* ------------------------------aead alg, ccm mode and gcm mode------------------ */ +static handle_t sched_aead_init(handle_t h_sched_ctx, void *sched_param) +{ + return (handle_t)0; +} + +static __u32 sched_aead_pick_next_ctx(handle_t h_sched_ctx, + void *sched_key, const int sched_mode) +{ + return 0; +} + +static int init_aead_ctx_config(int type, int mode) +{ + struct uacce_dev_list *list; + struct wd_sched sched; + int ret; + + if (g_use_env) + return wd_aead_env_init(NULL); + + list = wd_get_accel_list("aead"); + if (!list) + return -ENODEV; + + + memset(&g_ctx_cfg, 0, sizeof(struct wd_ctx_config)); + g_ctx_cfg.ctx_num = 1; + g_ctx_cfg.ctxs = calloc(1, sizeof(struct wd_ctx)); + if (!g_ctx_cfg.ctxs) + return -ENOMEM; + + /* Just use first found dev to test here */ + g_ctx_cfg.ctxs[0].ctx = wd_request_ctx(list->dev); + if (!g_ctx_cfg.ctxs[0].ctx) { + ret = -EINVAL; + SEC_TST_PRT("Fail to request ctx!\n"); + goto out; + } + g_ctx_cfg.ctxs[0].op_type = type; + g_ctx_cfg.ctxs[0].ctx_mode = mode; + + sched.name = SCHED_SINGLE; + sched.pick_next_ctx = sched_aead_pick_next_ctx; + sched.poll_policy = sched_single_poll_policy; + sched.sched_init = sched_aead_init; + /* aead init*/ + ret = wd_aead_init(&g_ctx_cfg, &sched); + if (ret) { + SEC_TST_PRT("Fail to aead ctx!\n"); + goto out; + } + + wd_free_list_accels(list); + + return 0; + +out: + free(g_ctx_cfg.ctxs); + return ret; +} + +static void aead_uninit_config(void) +{ + int i; + + if (g_use_env) { + wd_aead_env_uninit(); + return; + } + + wd_aead_uninit(); + for (i = 0; i < g_ctx_cfg.ctx_num; i++) + wd_release_ctx(g_ctx_cfg.ctxs[i].ctx); + free(g_ctx_cfg.ctxs); +} + +int get_aead_resource(struct aead_testvec **alg_tv, + int* alg, int* mode, int* dalg, int* dmode) +{ + struct aead_testvec *tv; + int alg_type = 0; + int mode_type = 0; + int dalg_type = 0; + int dmode_type = 0; + + switch (g_testalg) { + case 0: + alg_type = WD_CIPHER_AES; + mode_type = WD_CIPHER_CCM; + SEC_TST_PRT("test alg: %s\n", "ccm(aes)"); + switch (g_keylen) { + case AES_KEYSIZE_128: + tv = &aes_ccm_tv_template_128[0]; + break; + case AES_KEYSIZE_192: + tv = &aes_ccm_tv_template_192[0]; + break; + case AES_KEYSIZE_256: + tv = &aes_ccm_tv_template_256[0]; + break; + default: + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + break; + case 1: + alg_type = WD_CIPHER_AES; + mode_type = WD_CIPHER_GCM; + SEC_TST_PRT("test alg: %s\n", "gcm(aes)"); + switch (g_keylen) { + case AES_KEYSIZE_128: + tv = &aes_gcm_tv_template_128[0]; + break; + case AES_KEYSIZE_192: + tv = &aes_gcm_tv_template_192[0]; + break; + case AES_KEYSIZE_256: + tv = &aes_gcm_tv_template_256[0]; + break; + default: + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + break; + case 2: + alg_type = WD_CIPHER_AES; + mode_type = WD_CIPHER_CBC; + dalg_type = WD_DIGEST_SHA256; + dmode_type = WD_DIGEST_HMAC; + SEC_TST_PRT("test alg: %s\n", "hmac(sha256),cbc(aes)"); + tv = &hmac_sha256_aes_cbc_tv_temp[0]; + break; + default: + SEC_TST_PRT("keylenth error, default test alg: %s\n", "ccm(aes)"); + return -EINVAL; + } + *alg = alg_type; + *mode = mode_type; + *dalg = dalg_type; + *dmode = dmode_type; + *alg_tv = tv; + + return 0; +} + +static int sec_aead_sync_once(void) +{ + struct wd_aead_sess_setup setup = {0}; + struct aead_testvec *tv = NULL; + handle_t h_sess = 0; + struct wd_aead_req req; + struct timeval start_tval; + struct timeval cur_tval; + unsigned long Perf = 0; + float speed, time_used; + unsigned long cnt = g_times; + __u16 mac_bytes; + __u16 auth_size; + __u16 in_size; + __u16 iv_len; + int ret; + size_t unit_sz; + + /* config setup */ + ret = init_aead_ctx_config(CTX_TYPE_ENCRYPT, CTX_MODE_SYNC); + if (ret) { + SEC_TST_PRT("Fail to init sigle ctx config!\n"); + return ret; + } + + /* config arg */ + memset(&req, 0, sizeof(struct wd_aead_req)); + ret = get_aead_resource(&tv, (int *)&setup.calg, + (int *)&setup.cmode,(int *)&setup.dalg, (int *)&setup.dmode); + if (ret) { + SEC_TST_PRT("get aead resource fail!\n"); + return ret; + } + + h_sess = wd_aead_alloc_sess(&setup); + if (!h_sess) { + ret = -EINVAL; + goto out; + } + + /* should set key */ + dump_mem(WD_FLAT_BUF, (void *)tv->key, tv->klen); + if (setup.cmode == WD_CIPHER_CCM || setup.cmode == WD_CIPHER_GCM) { + ret = wd_aead_set_ckey(h_sess, (const __u8*)tv->key, tv->klen); + if (ret) { + SEC_TST_PRT("aead sess set key failed!\n"); + goto out_key; + } + } else { + // AEAD template's cipher key is the tail data + ret = wd_aead_set_ckey(h_sess, (__u8*)tv->key + 0x28, 0x10); + if (ret) { + SEC_TST_PRT("set cipher key fail!\n"); + goto out_key; + } + // AEAD template's auth key is the mid data + ret = wd_aead_set_akey(h_sess, (__u8*)tv->key + 0x08, 0x20); + if (ret) { + SEC_TST_PRT("set auth key fail!\n"); + goto out_key; + } + } + + auth_size = (__u16)(tv->clen - tv->plen); + mac_bytes = auth_size; + ret = wd_aead_set_authsize(h_sess, auth_size); + if (ret) { + SEC_TST_PRT("set auth size fail, authsize: %u\n", auth_size); + goto out_key; + } + + // test the auth size + ret = wd_aead_get_authsize(h_sess); + if (ret != auth_size) { + SEC_TST_PRT("get auth size fail!\n"); + goto out_key; + } + + ret = wd_aead_get_maxauthsize(h_sess); + if (ret < auth_size) { + SEC_TST_PRT("get max auth size fail!\n"); + goto out_key; + } + SEC_TST_PRT("aead get max auth size: %u\n", ret); + + if (setup.cmode == WD_CIPHER_CCM || setup.cmode == WD_CIPHER_GCM) + mac_bytes = 16; + + req.mac = malloc(mac_bytes); + if (!req.mac) { + SEC_TST_PRT("req iv mem malloc failed!\n"); + ret = -ENOMEM; + goto out_key; + } + memset(req.mac, 0, mac_bytes); + req.mac_bytes = mac_bytes; + + if (g_direction == 0) + req.op_type = WD_CIPHER_ENCRYPTION_DIGEST; + else + req.op_type = WD_CIPHER_DECRYPTION_DIGEST; + + req.assoc_bytes = tv->alen; + if (g_direction == 0) { + in_size = req.assoc_bytes + tv->plen; + } else { + in_size = req.assoc_bytes + tv->clen; + } + if (in_size > BUFF_SIZE) { + SEC_TST_PRT("alloc in buffer block size too small!\n"); + goto out_mac; + } + unit_sz = cal_unit_sz(in_size, g_sgl_num); + void *src = create_buf(WD_FLAT_BUF, in_size, unit_sz); + if (!src) { + ret = -ENOMEM; + goto out_src; + } + + memset(src, 0, in_size); + // copy the assoc data in the front of in data + SEC_TST_PRT("aead set assoc_bytes: %u\n", req.assoc_bytes); + if (g_direction == 0) { + memcpy(src, tv->assoc, tv->alen); + memcpy((src + req.assoc_bytes), tv->ptext, tv->plen); + req.in_bytes = tv->plen; + } else { + memcpy(src, tv->assoc, tv->alen); + memcpy(src + req.assoc_bytes, tv->ctext, tv->clen - auth_size); + req.in_bytes = tv->clen - auth_size; + memcpy(req.mac, tv->ctext + tv->clen - auth_size, auth_size); + } + + SEC_TST_PRT("mac addr src is:\n"); + dump_mem(0, req.mac, auth_size); + + req.src = create_buf(g_data_fmt, in_size, unit_sz); + if (!req.src) { + ret = -ENOMEM; + goto out_src; + } + copy_mem(g_data_fmt, req.src, WD_FLAT_BUF, src, + (size_t)(req.in_bytes + tv->alen)); + free(src); + SEC_TST_PRT("aead req src in--------->: %u\n", tv->alen + req.in_bytes); + dump_mem(g_data_fmt, req.src, tv->alen + req.in_bytes); + + if (g_direction == 0) { + req.out_bytes = req.assoc_bytes + tv->clen - auth_size; + } else { + req.out_bytes = req.assoc_bytes + tv->plen; + } + + // alloc out buffer memory + unit_sz = cal_unit_sz(req.out_bytes, g_sgl_num); + req.dst = create_buf(g_data_fmt, req.out_bytes, unit_sz); + if (!req.dst) { + ret = -ENOMEM; + goto out_dst; + } + + req.iv = malloc(AES_BLOCK_SIZE); + if (!req.iv) { + SEC_TST_PRT("req iv mem malloc failed!\n"); + ret = -ENOMEM; + goto out_iv; + } + if (setup.cmode == WD_CIPHER_GCM) + iv_len = GCM_BLOCK_SIZE; + else + iv_len = AES_BLOCK_SIZE; + req.iv_bytes = iv_len; + memcpy(req.iv, tv->iv, iv_len); + + req.data_fmt = g_data_fmt; + + gettimeofday(&start_tval, NULL); + while (cnt) { + ret = wd_do_aead_sync(h_sess, &req); + cnt--; + } + gettimeofday(&cur_tval, NULL); + + time_used = (float)((cur_tval.tv_sec - start_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - start_tval.tv_usec); + speed = g_times / time_used * 1000000; + Perf = speed * req.in_bytes / 1024; //B->KB + SEC_TST_PRT("time_used:%0.0f us, send task num:%lld\n", time_used, g_times); + SEC_TST_PRT("Pro-%d, thread_id-%d, speed:%0.3f ops, Perf: %ld KB/s\n", getpid(), + (int)syscall(__NR_gettid), speed, Perf); + + SEC_TST_PRT("aead dump out addr is:\n"); + dump_mem(g_data_fmt, req.dst, req.out_bytes); + SEC_TST_PRT("aead dump mac addr is:\n"); + dump_mem(0, req.mac, auth_size); + + free(req.iv); +out_iv: + free_buf(g_data_fmt, req.dst); +out_dst: + free_buf(g_data_fmt, req.src); +out_src: +out_mac: + free(req.mac); +out_key: + wd_aead_free_sess(h_sess); +out: + aead_uninit_config(); + + return ret; +} + +static void *aead_async_cb(struct wd_aead_req *req, void *cb_param) +{ + //struct wd_aead_req *req = (struct wd_aead_req *)data; + //SEC_TST_PRT("Test digest callback run!\n"); + + return NULL; +} + +void *aead_send_thread(void *data) +{ + thread_data_d *td_data = data; + struct wd_aead_req *req = td_data->areq; + unsigned long cnt = 0; + int try_cnt = 0; + int ret; + + while (cnt < td_data->send_num) { + req->cb = aead_async_cb; + ret = wd_do_aead_async(td_data->h_sess, req); + if (ret < 0) { + usleep(100); + try_cnt++; + if (try_cnt > 100) { + SEC_TST_PRT("Test aead current send fail 100 times !\n"); + break; + } + continue; + } + cnt++; + } + SEC_TST_PRT("Test aead multi send : %lu pkg !\n", cnt); + + return NULL; +} + +void *aead_poll_thread(void *data) +{ + thread_data_d *td_data = data; + struct wd_aead_req *req = td_data->areq; + unsigned int recv = 0; + int expt = td_data->recv_num; + struct timeval cur_tval; + unsigned long Perf = 0; + float speed, time_used; + unsigned long cnt = 0; + int ret; + + while (cnt < td_data->recv_num) { + ret = wd_aead_poll_ctx(0, expt, &recv); + if (ret < 0) + usleep(100); + + if (recv == 0) { + SEC_TST_PRT("current aead async poll --0-- pkg!\n"); + break; + } + expt -= recv; + cnt += recv; + recv = 0; + } + gettimeofday(&cur_tval, NULL); + + SEC_TST_PRT("current aead async poll recv: %lu pkg!\n", cnt); + pthread_mutex_lock(&test_sec_mutex); + time_used = (float)((cur_tval.tv_sec - td_data->start_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - td_data->start_tval.tv_usec); + speed = cnt / time_used * 1000000; + Perf = speed * req->in_bytes / 1024; //B->KB + pthread_mutex_unlock(&test_sec_mutex); + SEC_TST_PRT("time_used:%0.0f us, send task num:%ld\n", time_used, cnt); + SEC_TST_PRT("Pro-%d, thread_id-%d, speed:%0.3f ops, Perf: %ld KB/s\n", getpid(), + (int)syscall(__NR_gettid), speed, Perf); + + return NULL; +} + +void *aead_sync_send_thread(void *data) +{ + thread_data_d *td_data = data; + struct wd_aead_req *req = td_data->areq; + struct timeval cur_tval, start_tval; + unsigned long Perf = 0; + double speed, time_used; + int ret; + int cnt = 0; + + gettimeofday(&start_tval, NULL); + while (cnt < td_data->send_num) { + ret = wd_do_aead_sync(td_data->h_sess, req); + if (ret < 0) { + usleep(100); + SEC_TST_PRT("Test aead current send fail: have send %u pkg !\n", cnt); + continue; + } + cnt++; + } + gettimeofday(&cur_tval, NULL); + + pthread_mutex_lock(&test_sec_mutex); + time_used = (double)((cur_tval.tv_sec - start_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - start_tval.tv_usec); + speed = td_data->send_num / time_used * 1000000; + Perf = speed * req->in_bytes / 1024; //B->KB + pthread_mutex_unlock(&test_sec_mutex); + SEC_TST_PRT("time_used:%0.0f us, send task num:%lld\n", time_used, td_data-> +send_num); + SEC_TST_PRT("Pro-%d, thread_id-%d, speed:%0.3f ops, Perf: %ld KB/s\n", getpid(), + (int)syscall(__NR_gettid), speed, Perf); + + __atomic_add_fetch(&td_data->sum_perf, speed, __ATOMIC_RELAXED); + + return NULL; +} + +static int sec_aead_async_once(void) +{ + struct wd_aead_sess_setup setup = {0}; + struct aead_testvec *tv = NULL; + handle_t h_sess = 0; + struct wd_aead_req req; + static pthread_t send_td; + static pthread_t poll_td; + thread_data_d td_data; + __u16 mac_bytes; + __u16 auth_size; + __u16 in_size; + __u16 iv_len; + int ret; + size_t unit_sz; + + /* config setup */ + ret = init_aead_ctx_config(CTX_TYPE_ENCRYPT, CTX_MODE_ASYNC); + if (ret) { + SEC_TST_PRT("Fail to init sigle ctx config!\n"); + return ret; + } + + /* config arg */ + memset(&req, 0, sizeof(struct wd_aead_req)); + ret = get_aead_resource(&tv, (int *)&setup.calg, (int *)&setup.cmode, + (int *)&setup.dalg, (int *)&setup.dmode); + if (ret) { + SEC_TST_PRT("get aead resource fail!\n"); + goto out; + } + + h_sess = wd_aead_alloc_sess(&setup); + if (!h_sess) { + ret = -EINVAL; + goto out; + } + + /* should set key */ + dump_mem(WD_FLAT_BUF, (void *)tv->key, tv->klen); + if (setup.cmode == WD_CIPHER_CCM || setup.cmode == WD_CIPHER_GCM) { + ret = wd_aead_set_ckey(h_sess, (const __u8*)tv->key, tv->klen); + if (ret) { + SEC_TST_PRT("aead sess set key failed!\n"); + goto out_key; + } + } else { + // AEAD template's cipher key is the tail data + ret = wd_aead_set_ckey(h_sess, (__u8*)tv->key + 0x28, 0x10); + if (ret) { + SEC_TST_PRT("set cipher key fail!\n"); + goto out_key; + } + // AEAD template's auth key is the mid data + ret = wd_aead_set_akey(h_sess, (__u8*)tv->key + 0x08, 0x20); + if (ret) { + SEC_TST_PRT("set auth key fail!\n"); + goto out_key; + } + } + + auth_size = (__u16)(tv->clen - tv->plen); + mac_bytes = auth_size; + ret = wd_aead_set_authsize(h_sess, auth_size); + if (ret) { + SEC_TST_PRT("set auth size fail, authsize: %u\n", auth_size); + goto out_key; + } + + // test the auth size + ret = wd_aead_get_authsize(h_sess); + if (ret != auth_size) { + SEC_TST_PRT("get auth size fail!\n"); + goto out_key; + } + ret = wd_aead_get_maxauthsize(h_sess); + if (ret < auth_size) { + SEC_TST_PRT("get max auth size fail!\n"); + goto out_key; + } + SEC_TST_PRT("aead get max auth size: %u\n", ret); + if (setup.cmode == WD_CIPHER_CCM || setup.cmode == WD_CIPHER_GCM) + mac_bytes = 16; + + req.mac = malloc(mac_bytes); + if (!req.mac) { + SEC_TST_PRT("req iv mem malloc failed!\n"); + ret = -ENOMEM; + goto out_key; + } + memset(req.mac, 0, mac_bytes); + req.mac_bytes = mac_bytes; + + if (g_direction == 0) + req.op_type = WD_CIPHER_ENCRYPTION_DIGEST; + else + req.op_type = WD_CIPHER_DECRYPTION_DIGEST; + + // copy the assoc data in the front of in data + in_size = tv->alen + tv->plen + auth_size; + if (in_size > BUFF_SIZE) { + SEC_TST_PRT("alloc in buffer block size too small!\n"); + goto out_mac; + } + req.assoc_bytes = tv->alen; + unit_sz = cal_unit_sz(BUFF_SIZE, g_sgl_num); + req.src = create_buf(g_data_fmt, BUFF_SIZE, unit_sz); + if (!req.src) { + SEC_TST_PRT("req src in mem malloc failed!\n"); + ret = -ENOMEM; + goto out_src; + } + void *src = create_buf(WD_FLAT_BUF, BUFF_SIZE, unit_sz); + if (!src) { + SEC_TST_PRT("req src in mem malloc failed!\n"); + ret = -ENOMEM; + goto out_src; + } + + if (g_direction == 0) { + memcpy(src, tv->assoc, tv->alen); + memcpy((src + tv->alen), tv->ptext, tv->plen); + req.in_bytes = tv->plen; + } else { + memcpy(src, tv->assoc, tv->alen); + memcpy(src + tv->alen, tv->ctext, tv->clen - auth_size); + req.in_bytes = tv->clen - auth_size; + memcpy(req.mac, tv->ctext + tv->clen - auth_size, auth_size); + } + + copy_mem(g_data_fmt, req.src, WD_FLAT_BUF, src, + (size_t)(req.in_bytes + tv->alen)); + free(src); + SEC_TST_PRT("aead req alen---->: %u. in_bytes--->:%u\n", tv->alen, req.in_bytes); + dump_mem(g_data_fmt, req.src, tv->alen + req.in_bytes); + + // alloc out buffer memory + req.dst = create_buf(g_data_fmt, BUFF_SIZE, unit_sz); + if (!req.dst) { + ret = -ENOMEM; + goto out_dst; + } + + if (g_direction == 0) + req.out_bytes = tv->alen + tv->clen; + else + req.out_bytes = tv->alen + tv->plen; + + // set iv + req.iv = malloc(IV_SIZE); + if (!req.iv) { + SEC_TST_PRT("req iv mem malloc failed!\n"); + ret = -ENOMEM; + goto out_iv; + } + if (setup.cmode == WD_CIPHER_GCM) + iv_len = GCM_BLOCK_SIZE; + else + iv_len = AES_BLOCK_SIZE; + req.iv_bytes = iv_len; + memcpy(req.iv, tv->iv, iv_len); + + req.data_fmt = g_data_fmt; + + /* send thread */ + td_data.areq = &req; + td_data.h_sess = h_sess; + td_data.send_num = g_times; + td_data.recv_num = g_times * g_thread_num; + gettimeofday(&td_data.start_tval, NULL); + ret = pthread_create(&send_td, NULL, aead_send_thread, &td_data); + if (ret) { + SEC_TST_PRT("kthread create fail at %s", __func__); + goto out_thr; + } + + /* poll thread */ + ret = pthread_create(&poll_td, NULL, aead_poll_thread, &td_data); + if (ret) { + SEC_TST_PRT("kthread create fail at %s", __func__); + goto out_thr; + } + + ret = pthread_join(send_td, NULL); + if (ret) { + SEC_TST_PRT("pthread_join fail at %s", __func__); + goto out_thr; + } + + ret = pthread_join(poll_td, NULL); + if (ret) { + SEC_TST_PRT("pthread_join fail at %s", __func__); + goto out_thr; + } + + dump_mem(g_data_fmt, req.dst, req.out_bytes); +out_thr: + free(req.iv); +out_iv: + free_buf(g_data_fmt, req.dst); +out_dst: + free_buf(g_data_fmt, req.src); +out_src: +out_mac: + free(req.mac); +out_key: + wd_aead_free_sess(h_sess); +out: + aead_uninit_config(); + + return ret; +} + +static int sec_aead_sync_multi(void) +{ + struct wd_aead_sess_setup setup = {0}; + struct aead_testvec *tv = NULL; + handle_t h_sess = 0; + struct wd_aead_req req; + static pthread_t sendtd[64]; + thread_data_d td_data; + __u16 mac_bytes; + __u16 auth_size; + __u16 in_size; + __u16 iv_len; + int i, ret; + size_t unit_sz; + + /* config setup */ + ret = init_aead_ctx_config(CTX_TYPE_ENCRYPT, CTX_MODE_SYNC); + if (ret) { + SEC_TST_PRT("Fail to init sigle ctx config!\n"); + return ret; + } + + /* config arg */ + memset(&req, 0, sizeof(struct wd_aead_req)); + ret = get_aead_resource(&tv, (int *)&setup.calg, + (int *)&setup.cmode,(int *)&setup.dalg, (int *)&setup.dmode); + if (ret) { + SEC_TST_PRT("get aead resource fail!\n"); + goto out; + } + + h_sess = wd_aead_alloc_sess(&setup); + if (!h_sess) { + ret = -EINVAL; + goto out; + } + + /* should set key */ + dump_mem(WD_FLAT_BUF, (void *)tv->key, tv->klen); + if (setup.cmode == WD_CIPHER_CCM || setup.cmode == WD_CIPHER_GCM) { + ret = wd_aead_set_ckey(h_sess, (const __u8*)tv->key, tv->klen); + if (ret) { + SEC_TST_PRT("aead sess set key failed!\n"); + goto out_key; + } + } else { + // AEAD template's cipher key is the tail data + ret = wd_aead_set_ckey(h_sess, (__u8*)tv->key + 0x28, 0x10); + if (ret) { + SEC_TST_PRT("set cipher key fail!\n"); + goto out_key; + } + // AEAD template's auth key is the mid data + ret = wd_aead_set_akey(h_sess, (__u8*)tv->key + 0x08, 0x20); + if (ret) { + SEC_TST_PRT("set auth key fail!\n"); + goto out_key; + } + } + + auth_size = (__u16)(tv->clen - tv->plen); + mac_bytes = auth_size; + ret = wd_aead_set_authsize(h_sess, auth_size); + if (ret) { + SEC_TST_PRT("set auth size fail, authsize: %u\n", auth_size); + goto out_key; + } + + // test the auth size + ret = wd_aead_get_authsize(h_sess); + if (ret != auth_size) { + SEC_TST_PRT("get auth size fail!\n"); + goto out_key; + } + ret = wd_aead_get_maxauthsize(h_sess); + if (ret < auth_size) { + SEC_TST_PRT("get max auth size fail!\n"); + goto out_key; + } + SEC_TST_PRT("aead get max auth size: %u\n", ret); + + if (setup.cmode == WD_CIPHER_CCM || setup.cmode == WD_CIPHER_GCM) + mac_bytes = 16; + + req.mac = malloc(mac_bytes); + if (!req.mac) { + SEC_TST_PRT("req iv mem malloc failed!\n"); + ret = -ENOMEM; + goto out_key; + } + memset(req.mac, 0, mac_bytes); + req.mac_bytes = mac_bytes; + + if (g_direction == 0) + req.op_type = WD_CIPHER_ENCRYPTION_DIGEST; + else + req.op_type = WD_CIPHER_DECRYPTION_DIGEST; + + req.assoc_bytes = tv->alen; + // copy the assoc data in the front of in data + in_size = tv->alen + tv->plen + auth_size; + if (in_size > BUFF_SIZE) { + SEC_TST_PRT("alloc in buffer block size too small!\n"); + goto out_mac; + } + unit_sz = cal_unit_sz(BUFF_SIZE, g_sgl_num); + void *src = create_buf(WD_FLAT_BUF, BUFF_SIZE, unit_sz); + if (!src) { + ret = -ENOMEM; + goto out_src; + } + + if (g_direction == 0) { + memcpy(src, tv->assoc, tv->alen); + memcpy((src + tv->alen), tv->ptext, tv->plen); + req.in_bytes = tv->plen; + } else { + memcpy(src, tv->assoc, tv->alen); + memcpy(src + tv->alen, tv->ctext, tv->clen - auth_size); + req.in_bytes = tv->clen - auth_size; + memcpy(req.mac, tv->ctext + tv->clen - auth_size, auth_size); + } + + req.src = create_buf(g_data_fmt, in_size, unit_sz); + if (!req.src) { + ret = -ENOMEM; + goto out_src; + } + + copy_mem(g_data_fmt, req.src, WD_FLAT_BUF, src, + (size_t)(req.in_bytes + tv->alen)); + free(src); + + SEC_TST_PRT("aead req src in>: alen:%u, input len:%d\n", tv->alen, req.in_bytes); + dump_mem(g_data_fmt, req.src, tv->alen + req.in_bytes); + + // alloc out buffer memory + req.dst = create_buf(g_data_fmt, BUFF_SIZE, unit_sz); + if (!req.dst) { + ret = -ENOMEM; + goto out_dst; + } + + if (g_direction == 0) + req.out_bytes = tv->alen + tv->clen; + else + req.out_bytes = tv->alen + tv->plen; + + // set iv + req.iv = malloc(IV_SIZE); + if (!req.iv) { + SEC_TST_PRT("req iv mem malloc failed!\n"); + ret = -ENOMEM; + goto out_iv; + } + if (setup.cmode == WD_CIPHER_GCM) + iv_len = GCM_BLOCK_SIZE; + else + iv_len = AES_BLOCK_SIZE; + req.iv_bytes = iv_len; + memcpy(req.iv, tv->iv, iv_len); + req.data_fmt = g_data_fmt; + + td_data.h_sess = h_sess; + td_data.areq = &req; + /* send thread */ + td_data.send_num = g_times; + td_data.recv_num = g_times; + td_data.sum_perf = 0; + + printf("%s, req->in_bytes:%d\n", __func__, req.in_bytes); + for (i = 0; i < g_thread_num; i++) { + ret = pthread_create(&sendtd[i], NULL, aead_sync_send_thread, &td_data); + if (ret) { + SEC_TST_PRT("Create send thread fail!\n"); + goto out_thr; + } + } + + /* join thread */ + for (i = 0; i < g_thread_num; i++) { + ret = pthread_join(sendtd[i], NULL); + if (ret) { + SEC_TST_PRT("Join sendtd thread fail!\n"); + goto out_thr; + } + } + + dump_mem(g_data_fmt, req.dst, req.out_bytes); +out_thr: + free(req.iv); +out_iv: + free_buf(g_data_fmt, req.dst); +out_dst: + free_buf(g_data_fmt, req.src); +out_src: +out_mac: + free(req.mac); +out_key: + wd_aead_free_sess(h_sess); +out: + aead_uninit_config(); + + return ret; +} + +static int sec_aead_async_multi(void) +{ + struct wd_aead_sess_setup setup = {0}; + struct aead_testvec *tv = NULL; + handle_t h_sess = 0; + struct wd_aead_req req; + static pthread_t send_td[64]; + static pthread_t poll_td; + thread_data_d td_data; + __u16 mac_bytes; + __u16 auth_size; + __u16 in_size; + __u16 iv_len; + int i, ret; + size_t unit_sz; + + /* config setup */ + ret = init_aead_ctx_config(CTX_TYPE_ENCRYPT, CTX_MODE_ASYNC); + if (ret) { + SEC_TST_PRT("Fail to init sigle ctx config!\n"); + return ret; + } + + /* config arg */ + memset(&req, 0, sizeof(struct wd_aead_req)); + ret = get_aead_resource(&tv, (int *)&setup.calg, (int *)&setup.cmode, + (int *)&setup.dalg, (int *)&setup.dmode); + if (ret) { + SEC_TST_PRT("get aead resource fail!\n"); + return ret; + } + + h_sess = wd_aead_alloc_sess(&setup); + if (!h_sess) { + ret = -1; + goto out; + } + + /* should set key */ + dump_mem(WD_FLAT_BUF, (void *)tv->key, tv->klen); + if (setup.cmode == WD_CIPHER_CCM || setup.cmode == WD_CIPHER_GCM) { + ret = wd_aead_set_ckey(h_sess, (const __u8*)tv->key, tv->klen); + if (ret) { + SEC_TST_PRT("aead sess set key failed!\n"); + goto out; + } + } else { + // AEAD template's cipher key is the tail data + ret = wd_aead_set_ckey(h_sess, (__u8*)tv->key + 0x28, 0x10); + if (ret) { + SEC_TST_PRT("set cipher key fail!\n"); + goto out; + } + // AEAD template's auth key is the mid data + ret = wd_aead_set_akey(h_sess, (__u8*)tv->key + 0x08, 0x20); + if (ret) { + SEC_TST_PRT("set auth key fail!\n"); + goto out; + } + } + + auth_size = (__u16)(tv->clen - tv->plen); + mac_bytes = auth_size; + ret = wd_aead_set_authsize(h_sess, auth_size); + if (ret) { + SEC_TST_PRT("set auth size fail, authsize: %u\n", auth_size); + goto out; + } + + // test the auth size + ret = wd_aead_get_authsize(h_sess); + if (ret != auth_size) { + SEC_TST_PRT("get auth size fail!\n"); + goto out; + } + ret = wd_aead_get_maxauthsize(h_sess); + if (ret < auth_size) { + SEC_TST_PRT("get max auth size fail!\n"); + goto out; + } + SEC_TST_PRT("aead get max auth size: %u\n", ret); + + if (setup.cmode == WD_CIPHER_CCM || setup.cmode == WD_CIPHER_GCM) + mac_bytes = 16; + + req.mac = malloc(mac_bytes); + if (req.mac == NULL) + goto out; + memset(req.mac, 0, mac_bytes); + req.mac_bytes = mac_bytes; + + if (g_direction == 0) + req.op_type = WD_CIPHER_ENCRYPTION_DIGEST; + else + req.op_type = WD_CIPHER_DECRYPTION_DIGEST; + + req.assoc_bytes = tv->alen; + void *src = malloc(BUFF_SIZE); + if (!src) { + SEC_TST_PRT("src in mem malloc failed!\n"); + ret = -1; + goto out; + } + + unit_sz = cal_unit_sz(BUFF_SIZE, g_sgl_num); + req.src = create_buf(g_data_fmt, BUFF_SIZE, unit_sz); + if (!req.src) { + SEC_TST_PRT(" req src in mem malloc failed!\n"); + ret = -1; + goto out; + } + // copy the assoc data in the front of in data + in_size = tv->alen + tv->plen + auth_size; + if (in_size > BUFF_SIZE) { + SEC_TST_PRT("alloc in buffer block size too small!\n"); + goto out; + } + if (g_direction == 0) { + memcpy(src, tv->assoc, tv->alen); + memcpy((src + tv->alen), tv->ptext, tv->plen); + req.in_bytes = tv->plen; + } else { + memcpy(src, tv->assoc, tv->alen); + memcpy(src + tv->alen, tv->ctext, tv->clen - auth_size); + req.in_bytes = tv->clen - auth_size; + memcpy(req.mac, tv->ctext + (tv->clen - auth_size), auth_size); + } + + copy_mem(g_data_fmt, req.src, WD_FLAT_BUF, src, + (size_t)(req.in_bytes + tv->alen)); + free(src); + SEC_TST_PRT("aead req src in--------->: %u\n", tv->alen + req.in_bytes); + dump_mem(g_data_fmt, req.src, tv->alen + req.in_bytes); + + // alloc out buffer memory + req.dst = create_buf(g_data_fmt, BUFF_SIZE, unit_sz); + if (!req.dst) { + SEC_TST_PRT("req dst out mem malloc failed!\n"); + ret = -1; + goto out; + } + if (g_direction == 0) + req.out_bytes = tv->alen + tv->clen - auth_size; + else + req.out_bytes = tv->alen + tv->plen; + + // set iv + req.iv = malloc(IV_SIZE); + if (!req.iv) { + SEC_TST_PRT("req iv mem malloc failed!\n"); + ret = -1; + goto out; + } + if (setup.cmode == WD_CIPHER_GCM) + iv_len = GCM_BLOCK_SIZE; + else + iv_len = AES_BLOCK_SIZE; + req.iv_bytes = iv_len; + memcpy(req.iv, tv->iv, iv_len); + req.data_fmt = g_data_fmt; + + /* send thread */ + td_data.areq = &req; + td_data.h_sess = h_sess; + td_data.send_num = g_times; + td_data.recv_num = g_times * g_thread_num; + td_data.sum_perf = 0; + gettimeofday(&td_data.start_tval, NULL); + for (i = 0; i < g_thread_num; i++) { + ret = pthread_create(&send_td[i], NULL, aead_send_thread, &td_data); + if (ret) { + SEC_TST_PRT("kthread create fail at %s", __func__); + goto out; + } + } + + /* poll thread */ + ret = pthread_create(&poll_td, NULL, aead_poll_thread, &td_data); + if (ret) { + SEC_TST_PRT("kthread create fail at %s", __func__); + goto out; + } + for (i = 0; i < g_thread_num; i++) { + ret = pthread_join(send_td[i], NULL); + if (ret) { + SEC_TST_PRT("pthread_join fail at %s", __func__); + goto out; + } + } + + ret = pthread_join(poll_td, NULL); + if (ret) { + SEC_TST_PRT("pthread_join fail at %s", __func__); + goto out; + } + + dump_mem(g_data_fmt, req.dst, req.out_bytes); +out: + if (req.mac) + free(req.mac); + if (req.src) + free_buf(g_data_fmt, req.src); + if (req.dst) + free_buf(g_data_fmt, req.dst); + if (req.iv) + free(req.iv); + if (h_sess) + wd_aead_free_sess(h_sess); + aead_uninit_config(); + + return ret; +} + +/* --------------------------------------SVA perf test-------------------------------*/ +int init_bd_pool(thread_data_t *td) +{ + struct cipher_testvec *tv = &aes_cbc_tv_template_128[0]; + unsigned long step; + int i; + + td->bd_pool = malloc(sizeof(struct sva_bd_pool)); + if (!td->bd_pool) { + SEC_TST_PRT("init bd pool alloc thread failed!\n"); + free(td->bd_pool); + return -ENOMEM; + } + td->bd_pool->bds = malloc(g_blknum * sizeof(struct sva_bd)); + // make the block not align to 4K + step = sizeof(char) * g_block; + for (i = 0; i < g_blknum; i++) { + td->bd_pool->bds[i].src = (char *)malloc(step); + td->bd_pool->bds[i].dst = (char *)malloc(step); + memcpy(td->bd_pool->bds[i].src, tv->ptext, tv->len); + } + + return 0; +} + +void free_bd_pool(thread_data_t *td) +{ + int i; + + if (td->bd_pool) { + if (td->bd_pool->bds) { + for (i = 0; i < g_blknum; i++) { + free(td->bd_pool->bds[i].src); + free(td->bd_pool->bds[i].dst); + } + free(td->bd_pool->bds); + } + free(td->bd_pool); + } +} + +static void *sva_sec_cipher_async(void *arg) +{ + thread_data_t *pdata = (thread_data_t *)arg; + struct wd_cipher_sess_setup *setup = pdata->setup; + struct wd_cipher_req *req = pdata->req; + struct cipher_testvec *tv = NULL; + unsigned int count = 0; + int cnt = g_times; + handle_t h_sess; + int ret; + int j; + + /* get resource */ + ret = get_cipher_resource(&tv, (int *)&setup->alg, (int *)&setup->mode); + + h_sess = wd_cipher_alloc_sess(setup); + if (!h_sess) + return NULL; + + ret = wd_cipher_set_key(h_sess, (const __u8*)tv->key, tv->klen); + if (ret) { + SEC_TST_PRT("test sec cipher set key is failed!\n"); + goto out;; + } + + /* run task */ + do { +try_do_again: + j = count % g_blknum; + req->src = pdata->bd_pool->bds[j].src; + req->dst = pdata->bd_pool->bds[j].dst; + ret = wd_do_cipher_async(h_sess, req); + if (ret == -EBUSY) { // busy + usleep(100); + goto try_do_again; + } else if (ret) { + SEC_TST_PRT("test sec cipher send req is error!\n"); + goto out; + } + cnt--; + count++; // count means data block numbers + } while (cnt); + + ret = 0; +out: + wd_cipher_free_sess(h_sess); + return NULL; +} + +/* create poll threads */ +static void *sva_poll_func(void *arg) +{ + __u32 count = 0; + int ret; + + int expt = g_times * g_thread_num; + + do { + ret = wd_cipher_poll(expt, &count); + if (ret < 0 && ret != -EAGAIN) { + SEC_TST_PRT("poll ctx error: %d\n", ret); + break; + } + } while (expt - count); + + pthread_exit(NULL); + + return NULL; +} + +static int sva_async_create_threads(int thread_num, + thread_data_t *tds) +{ + int thread_id = (int)syscall(__NR_gettid); + struct timeval start_tval, cur_tval; + unsigned long Perf = 0; + float speed, time_used; + pthread_attr_t attr; + int i, ret; + + if (thread_num > SVA_THREADS) { + SEC_TST_PRT("can't creat %d threads", thread_num); + return -EINVAL; + } + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + gettimeofday(&start_tval, NULL); + for (i = 0; i < thread_num; i++) { + ret = pthread_create(&system_test_thrds[i], &attr, + sva_sec_cipher_async, &tds[i]); + if (ret) { + SEC_TST_PRT("Failed to create thread, ret:%d\n", ret); + return ret; + } + } + + ret = pthread_create(&system_test_thrds[i], &attr, sva_poll_func, NULL); + if (ret) { + SEC_TST_PRT("Failed to create poll thread, ret:%d\n", ret); + return ret; + } + pthread_attr_destroy(&attr); + for (i = 0; i < thread_num; i++) { + ret = pthread_join(system_test_thrds[i], NULL); + if (ret) { + SEC_TST_PRT("Join %dth thread fail!\n", i); + return ret; + } + } + // asyn_thread_exit = 1; + ret = pthread_join(system_test_thrds[i], NULL); + if (ret) { + SEC_TST_PRT("Join %dth thread fail!\n", i); + return ret; + } + + gettimeofday(&cur_tval, NULL); + time_used = (double)((cur_tval.tv_sec - start_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - start_tval.tv_usec); + SEC_TST_PRT("time_used:%0.0f us, send task num:%llu\n", time_used, g_times * g_thread_num); + speed = g_times * g_thread_num / time_used * 1000000; + Perf = speed * g_pktlen / 1024; //B->KB + SEC_TST_PRT("Async mode Pro-%d, thread_id-%d, speed:%f ops, Perf: %ld KB/s\n", + getpid(), thread_id, speed, Perf); + + return 0; +} + +static void *sva_sec_cipher_sync(void *arg) +{ + thread_data_t *pdata = (thread_data_t *)arg; + struct wd_cipher_sess_setup *setup = pdata->setup; + struct wd_cipher_req *req = pdata->req; + struct cipher_testvec *tv = NULL; + unsigned int count = 0; + handle_t h_sess; + int cnt = g_times; + int ret; + int j; + + ret = get_cipher_resource(&tv, (int *)&setup->alg, (int *)&setup->mode); + + h_sess = wd_cipher_alloc_sess(setup); + if (!h_sess) + return NULL; + + ret = wd_cipher_set_key(h_sess, (const __u8*)tv->key, tv->klen); + if (ret) { + SEC_TST_PRT("test sec cipher set key is failed!\n"); + goto out;; + } + + /* run task */ + while (cnt) { + j = count % g_blknum; + req->src = pdata->bd_pool->bds[j].src; + req->dst = pdata->bd_pool->bds[j].dst; + ret = wd_do_cipher_sync(h_sess, req); + cnt--; + pdata->send_task_num++; + count++; + } + +out: + wd_cipher_free_sess(h_sess); + return NULL; +} + +static int sva_sync_create_threads(int thread_num, thread_data_t *tds) +{ + int thread_id = (int)syscall(__NR_gettid); + struct timeval start_tval, cur_tval; + unsigned long Perf = 0; + float speed, time_used; + pthread_attr_t attr; + int i, ret; + + if (thread_num > SVA_THREADS) { + SEC_TST_PRT("can't creat %d threads", thread_num); + return -EINVAL; + } + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + gettimeofday(&start_tval, NULL); + for (i = 0; i < thread_num; i++) { + ret = pthread_create(&system_test_thrds[i], &attr, + sva_sec_cipher_sync, &tds[i]); + if (ret) { + SEC_TST_PRT("Failed to create thread, ret:%d\n", ret); + return ret; + } + } + + pthread_attr_destroy(&attr); + for (i = 0; i < thread_num; i++) { + ret = pthread_join(system_test_thrds[i], NULL); + } + + gettimeofday(&cur_tval, NULL); + time_used = (double)((cur_tval.tv_sec - start_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - start_tval.tv_usec); + SEC_TST_PRT("time_used:%0.0f us, send task num:%llu\n", time_used, g_times * g_thread_num); + speed = g_times * g_thread_num / time_used * 1000000; + Perf = speed * g_pktlen / 1024; //B->KB + SEC_TST_PRT("Sync mode avg Pro-%d, thread_id-%d, speed:%f ops, Perf: %ld KB/s\n", + getpid(), thread_id, speed, Perf); + + return 0; +} + +static int sec_sva_test(void) +{ + struct wd_cipher_req req[SVA_THREADS]; + struct wd_cipher_sess_setup setup[SVA_THREADS]; + thread_data_t datas[SVA_THREADS]; + struct cipher_testvec *tv = NULL; + int threads = g_thread_num; + int test_alg, test_mode; + void *src = NULL; + void *dst = NULL; + void *iv = NULL; + int i = 0; + int j = 0; + int step; + int cpsize; + int ret; + + memset(datas, 0, sizeof(thread_data_t) * g_thread_num); + memset(req, 0, sizeof(struct wd_cipher_req) * g_thread_num); + memset(setup, 0, sizeof(struct wd_cipher_sess_setup) * g_thread_num); + + if (g_syncmode == 0) + ret = init_ctx_config(CTX_TYPE_ENCRYPT, CTX_MODE_SYNC); + else + ret = init_ctx_config(CTX_TYPE_ENCRYPT, CTX_MODE_ASYNC); + if (ret) { + SEC_TST_PRT("fail to init ctx config!\n"); + goto out_thr; + } + + for (i = 0; i < threads; i++) { + ret = init_bd_pool(&datas[i]); + if (ret) + goto out_thr; + } + + ret = get_cipher_resource(&tv, &test_alg, &test_mode); + step = sizeof(char) * g_pktlen; + + src = malloc(step * g_thread_num); + if (!src) { + ret = -ENOMEM; + goto out_thr; + } + dst = malloc(step * g_thread_num); + if (!dst) { + ret = -ENOMEM; + goto out_thr; + } + iv = malloc(step * g_thread_num); + if (!iv) { + ret = -ENOMEM; + goto out_thr; + } + + cpsize = step; + if (step > BUFF_SIZE) + cpsize = BUFF_SIZE; + + for (i = 0; i < threads; i++) { + req[i].src = src + i * step; + memcpy(req[i].src, tv->ptext, cpsize); + req[i].in_bytes = step; + + req[i].dst = dst + i * step; + req[i].out_bytes = tv->len; + req[i].out_buf_bytes = step; + + req[i].iv = iv + i * step; + memset(req[i].iv, 0, step); + + req[i].iv_bytes = strlen(tv->iv); + if (tv->ivlen > 0) + req[i].iv_bytes = tv->ivlen; + memcpy(req[i].iv, tv->iv, req[i].iv_bytes); + + /* config arg */ + setup[i].alg = test_alg; + setup[i].mode = test_mode; + + if (g_direction == 0) + req[i].op_type = WD_CIPHER_ENCRYPTION; + else { + req[i].op_type = WD_CIPHER_DECRYPTION; + } + req[i].cb = async_cb; + req[i].cb_param = &datas[i]; + + datas[i].tid = i; + datas[i].req = &req[i]; + datas[i].setup = &setup[i]; + } + + if (g_syncmode == 0) + ret = sva_sync_create_threads(threads, datas); + else + ret = sva_async_create_threads(threads, datas); + if (ret < 0) + goto out_config; + +out_config: + uninit_config(); +out_thr: + for (j = i - 1; j >= 0; j--) { + free_bd_pool(&datas[j]); + } + + if (src) + free(src); + if (dst) + free(dst); + if (iv) + free(iv); + + return ret; +} + +static void print_help(void) +{ + SEC_TST_PRT("NAME\n"); + SEC_TST_PRT(" test_hisi_sec: test wd sec function,etc\n"); + SEC_TST_PRT("USAGE\n"); + SEC_TST_PRT(" test_hisi_sec [--cipher] [--digest] [--aead] [--perf]\n"); + SEC_TST_PRT(" test_hisi_sec [--optype] [--pktlen] [--keylen] [--times]\n"); + SEC_TST_PRT(" test_hisi_sec [--multi] [--sync] [--async] [--help]\n"); + SEC_TST_PRT(" test_hisi_sec [--block] [--blknum] [--ctxnum]\n"); + SEC_TST_PRT(" numactl --cpubind=0 --membind=0,1 ./test_hisi_sec xxxx\n"); + SEC_TST_PRT(" specify numa nodes for cpu and memory\n"); + SEC_TST_PRT("DESCRIPTION\n"); + SEC_TST_PRT(" [--cipher ]:\n"); + SEC_TST_PRT(" specify symmetric cipher algorithm\n"); + SEC_TST_PRT(" 0 : AES-ECB; 1 : AES-CBC; 2 : AES-XTS; 3 : AES-OFB\n"); + SEC_TST_PRT(" 4 : AES-CFB; 5 : 3DES-ECB; 6 : 3DES-CBC; 7 : SM4-CBC\n"); + SEC_TST_PRT(" 8 : SM4-XTS; 9 : SM4-OFB; 10 : SM4-CFB; 11 : SM4-ECB\n"); + SEC_TST_PRT(" 12 : AES-CBC_CS1; 13 : AES-CBC_CS2; 14 : AES-CBC_CS3\n"); + SEC_TST_PRT(" [--digest ]:\n"); + SEC_TST_PRT(" specify symmetric hash algorithm\n"); + SEC_TST_PRT(" 0 : SM3; 1 : MD5; 2 : SHA1; 3 : SHA256\n"); + SEC_TST_PRT(" 4 : SHA224; 5 : SHA384; 6 : SHA512; 7 : SHA512_224\n"); + SEC_TST_PRT(" 8 : SHA512_256; 9 : AES_CMAC; 10 : AES_GMAC_128\n"); + SEC_TST_PRT(" 11 : AES_GMAC_192; 12 : AES_GMAC_256; 13 : AES_XCBC_MAC_96\n"); + SEC_TST_PRT(" 14 : AES_XCBC_PRF_128\n"); + SEC_TST_PRT(" [--aead ]:\n"); + SEC_TST_PRT(" specify symmetric aead algorithm\n"); + SEC_TST_PRT(" 0 : AES-CCM; 1 : AES-GCM; 2 : Hmac(sha256),cbc(aes)\n"); + SEC_TST_PRT(" [--sync]: start synchronous mode test\n"); + SEC_TST_PRT(" [--async]: start asynchronous mode test\n"); + SEC_TST_PRT(" [--optype]:\n"); + SEC_TST_PRT(" 0 : encryption operation or normal mode for hash\n"); + SEC_TST_PRT(" 1 : decryption operation or hmac mode for hash\n"); + SEC_TST_PRT(" 3 : hmac mode for stream hash mode\n"); + SEC_TST_PRT(" [--pktlen]:\n"); + SEC_TST_PRT(" set the length of BD message in bytes\n"); + SEC_TST_PRT(" [--keylen]:\n"); + SEC_TST_PRT(" set the key length in bytes\n"); + SEC_TST_PRT(" [--times]:\n"); + SEC_TST_PRT(" set the number of sent messages\n"); + SEC_TST_PRT(" [--multi]:\n"); + SEC_TST_PRT(" set the number of threads\n"); + SEC_TST_PRT(" [--block]:\n"); + SEC_TST_PRT(" set the memory size allocated for each BD message\n"); + SEC_TST_PRT(" [--blknum]:\n"); + SEC_TST_PRT(" the number of memory blocks in the pre-allocated BD message memory pool\n"); + SEC_TST_PRT(" [--ctxnum]:\n"); + SEC_TST_PRT(" the number of QP queues used by the entire test task\n"); + SEC_TST_PRT(" [--stream]:\n"); + SEC_TST_PRT(" set the steam mode for digest\n"); + SEC_TST_PRT(" [--help] = usage\n"); + SEC_TST_PRT("Example\n"); + SEC_TST_PRT(" ./test_hisi_sec --cipher 0 --sync --optype 0\n"); + SEC_TST_PRT("--pktlen 16 --keylen 16 --times 1 --multi 1\n"); + SEC_TST_PRT(" ./test_hisi_sec --digest 0 --sync --optype 0\n"); + SEC_TST_PRT("--pktlen 16 --keylen 16 --times 1 --multi 2 --stream\n"); + SEC_TST_PRT(" ./test_hisi_sec --digest 1 --sync --optype 0\n"); + SEC_TST_PRT("--pktlen 16 --keylen 16 --times 1 --multi 2 --stream\n"); + SEC_TST_PRT(" ./test_hisi_sec --perf --sync --pktlen 1024 --block 1024\n"); + SEC_TST_PRT("--blknum 100000 --times 10000 --multi 1 --ctxnum 1\n"); + SEC_TST_PRT("UPDATE:2022-06-29\n"); +} + +static void test_sec_cmd_parse(int argc, char *argv[], struct test_sec_option *option) +{ + int option_index = 0; + int c; + + static struct option long_options[] = { + {"cipher", required_argument, 0, 1}, + {"digest", required_argument, 0, 2}, + {"aead", required_argument, 0, 3}, + {"perf", no_argument, 0, 4}, + {"optype", required_argument, 0, 5}, + {"pktlen", required_argument, 0, 6}, + {"keylen", required_argument, 0, 7}, + {"times", required_argument, 0, 8}, + {"sync", no_argument, 0, 9}, + {"async", no_argument, 0, 10}, + {"multi", required_argument, 0, 11}, + {"ctxnum", required_argument, 0, 12}, + {"block", required_argument, 0, 13}, + {"blknum", required_argument, 0, 14}, + {"stream", no_argument, 0, 15}, + {"sglnum", required_argument, 0, 16}, + {"use_env", no_argument, 0, 17}, + {"help", no_argument, 0, 18}, + {0, 0, 0, 0} + }; + + while (1) { + c = getopt_long(argc, argv, "", long_options, &option_index); + if (c == -1) + break; + + switch (c) { + case 1: + option->algclass = CIPHER_CLASS; + option->algtype = strtol(optarg, NULL, 0); + break; + case 2: + option->algclass = DIGEST_CLASS; + option->algtype = strtol(optarg, NULL, 0); + break; + case 3: + option->algclass = AEAD_CLASS; + option->algtype = strtol(optarg, NULL, 0); + break; + case 4: + option->algclass = PERF_CLASS; + break; + case 5: + option->optype = strtol(optarg, NULL, 0); + break; + case 6: + option->pktlen = strtol(optarg, NULL, 0); + break; + case 7: + option->keylen = strtol(optarg, NULL, 0); + break; + case 8: + option->times = strtol(optarg, NULL, 0); + break; + case 9: + option->syncmode = 0; + break; + case 10: + option->syncmode = 1; + break; + case 11: + option->xmulti = strtol(optarg, NULL, 0); + break; + case 12: + option->ctxnum = strtol(optarg, NULL, 0); + break; + case 13: + option->block = strtol(optarg, NULL, 0); + break; + case 14: + option->blknum = strtol(optarg, NULL, 0); + break; + case 15: + option->stream_mode = 1; + break; + case 16: + option->sgl_num = strtol(optarg, NULL, 0); + break; + case 17: + option->use_env = 1; + break; + case 18: + print_help(); + exit(-1); + default: + SEC_TST_PRT("bad input parameter, exit\n"); + print_help(); + exit(-1); + } + } +} + +static int test_sec_option_convert(struct test_sec_option *option) +{ + if (option->algclass > PERF_CLASS) { + print_help(); + return -EINVAL; + } + if (option->syncmode > 1) { + print_help(); + return -EINVAL; + } + + if (option->algclass == PERF_CLASS) { + g_testalg = 16; + g_pktlen = option->pktlen ? option->pktlen : BUFF_SIZE; + g_block = option->block; + if (g_pktlen > g_block) { + SEC_TST_PRT("block size too smaller, block set to: %u\n", g_pktlen); + g_block = g_pktlen; + } + g_keylen = 16; + g_times = option->times ? option->times : + (BUFF_SIZE * BUFF_SIZE); + + g_thread_num = option->xmulti ? option->xmulti : 1; + g_syncmode = option->syncmode; + g_ctxnum = option->ctxnum; + g_blknum = option->blknum > 0 ? + option->blknum : MIN_SVA_BD_NUM; + g_direction = 0; + return 0; + } + + g_testalg = option->algtype; + g_pktlen = option->pktlen; + g_keylen = option->keylen; + g_use_env = option->use_env; + g_times = option->times ? option->times : 1; + g_ctxnum = option->ctxnum ? option->ctxnum : 1; + g_data_fmt = option->sgl_num ? WD_SGL_BUF : WD_FLAT_BUF; + g_sgl_num = option->sgl_num; + g_stream = option->stream_mode; + + SEC_TST_PRT("set global times is %lld\n", g_times); + + g_thread_num = option->xmulti ? option->xmulti : 1; + g_direction = option->optype; + if (option->algclass == DIGEST_CLASS) { + //0 is normal mode, 1 is HMAC mode + g_alg_op_type = g_direction; + if (g_stream) + g_ivlen = 1; + } + + return 0; +} + +static int test_sec_default_case() +{ + g_ctxnum = 1; + g_testalg = 0; + g_times = 10; + g_pktlen = 16; + g_keylen = 16; + SEC_TST_PRT("Test sec Cipher parameter default, alg:ecb(aes), set_times:10," + "set_pktlen:16 bytes, set_keylen:128 bit.\n"); + return test_sec_cipher_sync_once(); +} + +static void long_hash_data_init(void) +{ + g_long_hash_tv.plaintext = malloc(g_pktlen); + if (g_long_hash_tv.plaintext == NULL) + return; + + g_long_hash_tv.psize = g_pktlen; + + g_long_hash_tv.key = malloc(16); + if (g_long_hash_tv.key == NULL) { + free(g_long_hash_tv.plaintext); + return; + } + g_long_hash_tv.ksize = 16; +} + +static void long_hash_data_uninit(void) +{ + free(g_long_hash_tv.plaintext); + free(g_long_hash_tv.key); +} + +static int test_sec_run(__u32 sync_mode, __u32 alg_class) +{ + int ret = 0; + + if (sync_mode == 0) { + if (alg_class == CIPHER_CLASS) { + if (g_thread_num > 1) { + SEC_TST_PRT("currently cipher test is synchronize multi -%d threads!\n", g_thread_num); + ret = sec_cipher_sync_test(); + } else { + ret = test_sec_cipher_sync_once(); + SEC_TST_PRT("currently cipher test is synchronize once, one thread!\n"); + } + } else if (alg_class == DIGEST_CLASS) { + SEC_TST_PRT("hisi_sec HMAC-digest mode.\n"); + long_hash_data_init(); + if (g_thread_num > 1 && g_direction != 3) { + SEC_TST_PRT("currently digest test is synchronize psize:%u, multi -%d threads!\n", g_pktlen, g_thread_num); + ret = sec_digest_sync_multi(); + } else if (g_thread_num > 1 && g_stream) { + ret = sec_digest_sync_stream_mode_multi(); + (void)sec_digest_sync_stream_cmp(); + SEC_TST_PRT("currently digest long hash mode, psize:%u, multi thread!\n", g_pktlen); + } else if (g_thread_num == 1 && g_stream) { + if (g_ivlen == 1) { + ret = sec_digest_sync_stream_mode(); + (void)sec_digest_sync_stream_cmp(); + SEC_TST_PRT("currently digest long hash mode, psize:%u, one thread!\n", g_pktlen); + } + } else { + ret = sec_digest_sync_once(); + SEC_TST_PRT("currently digest test is synchronize once, one thread!\n"); + } + long_hash_data_uninit(); + } else if (alg_class == AEAD_CLASS) { + if (g_thread_num > 1) { + SEC_TST_PRT("currently aead test is synchronize multi -%d threads!\n", g_thread_num); + ret = sec_aead_sync_multi(); + } else { + ret = sec_aead_sync_once(); + SEC_TST_PRT("currently aead test is synchronize once, one thread!\n"); + } + } + } else { + if (alg_class == CIPHER_CLASS) { + if (g_thread_num > 1) { + SEC_TST_PRT("currently cipher test is asynchronous multi -%d threads!\n", g_thread_num); + ret = sec_cipher_async_test(); + } else { + ret = test_sec_cipher_async_once(); + SEC_TST_PRT("currently cipher test is asynchronous one, one thread!\n"); + } + } else if (alg_class == DIGEST_CLASS) { + if (g_thread_num > 1) { + SEC_TST_PRT("currently digest test is asynchronous multi -%d threads!\n", g_thread_num); + ret = sec_digest_async_multi(); + } else { + ret = sec_digest_async_once(); + SEC_TST_PRT("currently digest test is asynchronous one, one thread!\n"); + } + } else if (alg_class == AEAD_CLASS) { + if (g_thread_num > 1) { + SEC_TST_PRT("currently adad test is asynchronous multi -%d threads!\n", g_thread_num); + ret = sec_aead_async_multi(); + } else { + ret = sec_aead_async_once(); + SEC_TST_PRT("currently adad test is asynchronous one, one thread!\n"); + } + } + } + + return ret; +} + +int main(int argc, char *argv[]) +{ + struct test_sec_option option = {0}; + int ret = 0; + + SEC_TST_PRT("this is a hisi sec test.\n"); + + g_thread_num = 1; + if (!argv[1]) { + return test_sec_default_case(); + } + + test_sec_cmd_parse(argc, argv, &option); + ret = test_sec_option_convert(&option); + if (ret) + return ret; + if (option.algclass == PERF_CLASS) + return sec_sva_test(); + + pthread_mutex_init(&test_sec_mutex, NULL); + + return test_sec_run(option.syncmode, option.algclass); +} diff --git a/uadk/test/hisi_sec_test/test_hisi_sec.h b/uadk/test/hisi_sec_test/test_hisi_sec.h new file mode 100644 index 0000000..8e21681 --- /dev/null +++ b/uadk/test/hisi_sec_test/test_hisi_sec.h @@ -0,0 +1,1843 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. */ + +#ifndef TEST_HISI_SEC_H_ +#define TEST_HISI_SEC_H + +enum alg_class { + CIPHER_CLASS, + AEAD_CLASS, + DIGEST_CLASS, + PERF_CLASS, +}; + +enum cipher_op_type { + ENCRYPTION, + DECRYPTION, +}; +enum cipher_alg { + CIPHER_SM4, + CIPHER_AES, + CIPHER_DES, + CIPHER_3DES, +}; + +enum cipher_mode { + ECB, + CBC, + CTR, + XTS, +}; + +struct cipher_testvec { + const char *key; + int klen; + const char *iv; + int ivlen; + const char *iv_out; + const char *ptext; + const char *ctext; + int len; +}; + +struct hash_testvec { + char *key; + char *plaintext; + char *iv; + const char *digest; + unsigned int psize; + unsigned short ksize; + unsigned int dsize; +}; + +struct aead_testvec { + const char *key; + const char *iv; + const char *ptext; + const char *assoc; + const char *ctext; + unsigned char novrfy; + unsigned char wk; + unsigned char klen; + unsigned int plen; + unsigned int clen; + unsigned int alen; + int setkey_error; + int setauthsize_error; + int crypt_error; +}; + +struct hash_testvec sm3_tv_template[] = { + { + .plaintext = "abcdefghijklmnopqrstuvwxyz", + .psize = 26, + .digest = "\xB8\x0F\xE9\x7A\x4D\xA2\x4A\xFC" + "\x27\x75\x64\xF6\x6A\x35\x9E\xF4" + "\x40\x46\x2A\xD2\x8D\xCC\x6D\x63" + "\xAD\xB2\x4D\x5C\x20\xA6\x15\x95", + } +}; + +struct hash_testvec hmac_sm3_tv_template[] = { + { + .key = "Jefe", + .ksize = 4, + .plaintext = "what do ya want for nothing?", + .psize = 28, + .digest = "\x2e\x87\xf1\xd1\x68\x62\xe6\xd9" + "\x64\xb5\x0a\x52\x00\xbf\x2b\x10" + "\xb7\x64\xfa\xa9\x68\x0a\x29\x6a" + "\x24\x05\xf2\x4b\xec\x39\xf8\x82", + }, +}; + +struct hash_testvec md5_tv_template[] = { + { + .plaintext = "abcdefghijklmnopqrstuvwxyz", + .psize = 26, + .digest = "\xc3\xfc\xd3\xd7\x61\x92\xe4\x00" + "\x7d\xfb\x49\x6c\xca\x67\xe1\x3b", + } +}; + +struct hash_testvec hmac_md5_tv_template[] = +{ + { + .key = "Jefe", + .ksize = 4, + .plaintext = "what do ya want for nothing?", + .psize = 28, + .digest = "\x75\x0C\x78\x3E\x6A\xB0\xB5\x03" + "\xEA\xA8\x6E\x31\x0A\x5D\xB7\x38" + }, +}; + +struct hash_testvec sha1_tv_template[] = { + { + .plaintext = "abc", + .psize = 3, + .digest = "\xa9\x99\x3e\x36\x47\x06\x81\x6a\xba\x3e" + "\x25\x71\x78\x50\xc2\x6c\x9c\xd0\xd8\x9d", + } +}; + +struct hash_testvec hmac_sha1_tv_template[] = { + { + .key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", + .ksize = 20, + .plaintext = "Hi There", + .psize = 8, + .digest = "\xb6\x17\x31\x86\x55\x05\x72\x64" + "\xe2\x8b\xc0\xb6\xfb\x37\x8c\x8e" + "\xf1\x46\xbe", + } +}; + +struct hash_testvec sha256_tv_template[] = { + { + .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-", + .psize = 64, + .digest = "\xb5\xfe\xad\x56\x7d\xff\xcb\xa4" + "\x2c\x32\x29\x32\x19\xbb\xfb\xfa" + "\xd6\xff\x94\xa3\x72\x91\x85\x66" + "\x3b\xa7\x87\x77\x58\xa3\x40\x3a", + } +}; + +struct hash_testvec hmac_sha256_tv_template[] = { + { + .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa", + .ksize = 32, + .plaintext = "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd", + .psize = 50, + .digest = "\xcd\xcb\x12\x20\xd1\xec\xcc\xea" + "\x91\xe5\x3a\xba\x30\x92\xf9\x62" + "\xe5\x49\xfe\x6c\xe9\xed\x7f\xdc" + "\x43\x19\x1f\xbd\xe4\x5c\x30\xb0", + } +}; + +struct hash_testvec sha224_tv_template[] = { + { + .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-", + .psize = 64, + .digest = "\xc4\xdb\x2b\x3a\x58\xc3\x99\x01" + "\x42\xfd\x10\x92\xaa\x4e\x04\x08" + "\x58\xbb\xbb\xe8\xf8\x14\xa7\x0c" + "\xef\x3b\xcb\x0e", + } +}; + +struct hash_testvec hmac_sha224_tv_template[] = { + { + .key = "Jefe", + .ksize = 4, + /* ("what do ya want for nothing?") */ + .plaintext = "\x77\x68\x61\x74\x20\x64\x6f\x20" + "\x79\x61\x20\x77\x61\x6e\x74\x20" + "\x66\x6f\x72\x20\x6e\x6f\x74\x68" + "\x69\x6e\x67\x3f", + .psize = 28, + .digest = "\xa3\x0e\x01\x09\x8b\xc6\xdb\xbf" + "\x45\x69\x0f\x3a\x7e\x9e\x6d\x0f" + "\x8b\xbe\xa2\xa3\x9e\x61\x48\x00" + "\x8f\xd0\x5e\x44", + } +}; + +struct hash_testvec sha384_tv_template[] = { + { + .plaintext = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" + "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + .psize = 112, + .digest = "\x09\x33\x0c\x33\xf7\x11\x47\xe8" + "\x3d\x19\x2f\xc7\x82\xcd\x1b\x47" + "\x53\x11\x1b\x17\x3b\x3b\x05\xd2" + "\x2f\xa0\x80\x86\xe3\xb0\xf7\x12" + "\xfc\xc7\xc7\x1a\x55\x7e\x2d\xb9" + "\x66\xc3\xe9\xfa\x91\x74\x60\x39", + } +}; + +struct hash_testvec hmac_sha384_tv_template[] = { + { + .key = "Jefe", + .ksize = 4, + .plaintext = "what do ya want for nothing?", + .psize = 28, + .digest = "\xaf\x45\xd2\xe3\x76\x48\x40\x31" + "\x61\x7f\x78\xd2\xb5\x8a\x6b\x1b" + "\x9c\x7e\xf4\x64\xf5\xa0\x1b\x47" + "\xe4\x2e\xc3\x73\x63\x22\x44\x5e" + "\x8e\x22\x40\xca\x5e\x69\xe2\xc7" + "\x8b\x32\x39\xec\xfa\xb2\x16\x49", + } +}; + +struct hash_testvec sha512_tv_template[] = { + { + .plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + .psize = 56, + .digest = "\x20\x4a\x8f\xc6\xdd\xa8\x2f\x0a" + "\x0c\xed\x7b\xeb\x8e\x08\xa4\x16" + "\x57\xc1\x6e\xf4\x68\xb2\x28\xa8" + "\x27\x9b\xe3\x31\xa7\x03\xc3\x35" + "\x96\xfd\x15\xc1\x3b\x1b\x07\xf9" + "\xaa\x1d\x3b\xea\x57\x78\x9c\xa0" + "\x31\xad\x85\xc7\xa7\x1d\xd7\x03" + "\x54\xec\x63\x12\x38\xca\x34\x45", + } +}; + +struct hash_testvec hmac_sha512_tv_template[] = { + { + .key = "Jefe", + .ksize = 4, + .plaintext = "what do ya want for nothing?", + .psize = 28, + .digest = "\x16\x4b\x7a\x7b\xfc\xf8\x19\xe2" + "\xe3\x95\xfb\xe7\x3b\x56\xe0\xa3" + "\x87\xbd\x64\x22\x2e\x83\x1f\xd6" + "\x10\x27\x0c\xd7\xea\x25\x05\x54" + "\x97\x58\xbf\x75\xc0\x5a\x99\x4a" + "\x6d\x03\x4f\x65\xf8\xf0\xe6\xfd" + "\xca\xea\xb1\xa3\x4d\x4a\x6b\x4b" + "\x63\x6e\x07\x0a\x38\xbc\xe7\x37", + } +}; + +struct hash_testvec sha512_224_tv_template[] = { + { + .plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + .psize = 56, + .digest = "\xe5\x30\x2d\x6d\x54\xbb\x24\x22" + "\x75\xd1\xe7\x62\x2d\x68\xdf\x6e" + "\xb0\x2d\xed\xd1\x3f\x56\x4c\x13" + "\xdb\xda\x21\x74", + } +}; + +struct hash_testvec hmac_sha512_224_tv_template[] = { + { + .key = "Jefe", + .ksize = 4, + .plaintext = "what do ya want for nothing?", + .psize = 28, + .digest = "\x4a\x53\x0b\x31\xa7\x9e\xbc\xce" + "\x36\x91\x65\x46\x31\x7c\x45\xf2" + "\x47\xd8\x32\x41\xdf\xb8\x18\xfd" + "\x37\x25\x4b\xde", + }, +}; + +struct hash_testvec sha512_256_tv_template[] = { + { + .plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + .psize = 56, + .digest = "\xbd\xe8\xe1\xf9\xf1\x9b\xb9\xfd" + "\x34\x06\xc9\x0e\xc6\xbc\x47\xbd" + "\x36\xd8\xad\xa9\xf1\x18\x80\xdb" + "\xc8\xa2\x2a\x70\x78\xb6\xa4\x61", + } +}; + +struct hash_testvec hmac_sha512_256_tv_template[] = { + { + .key = "Jefe", + .ksize = 4, + .plaintext = "what do ya want for nothing?", + .psize = 28, + .digest = "\x6d\xf7\xb2\x46\x30\xd5\xcc\xb2" + "\xee\x33\x54\x07\x08\x1a\x87\x18" + "\x8c\x22\x14\x89\x76\x8f\xa2\x02" + "\x05\x13\xb2\xd5\x93\x35\x94\x56", + }, +}; + +struct hash_testvec aes_cmac_tv_template[] = { + { + .key = "\x11\x11\x11\x11\x11\x11\x11\x11" + "\x11\x11\x11\x11\x11\x11\x11\x11", + .ksize = 16, + .plaintext = "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44", + .psize = 32, + } +}; + +struct hash_testvec aes_gmac_128_tv_template[] = { + { + .key = "\x11\x11\x11\x11\x11\x11\x11\x11" + "\x11\x11\x11\x11\x11\x11\x11\x11", + .ksize = 16, + .plaintext = "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44", + .psize = 32, + .iv = "\x33\x33\x33\x33\x33\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00", + } +}; + +struct hash_testvec aes_gmac_192_tv_template[] = { + { + .key = "\x11\x11\x11\x11\x11\x11\x11\x11" + "\x11\x11\x11\x11\x11\x11\x11\x11" + "\x22\x22\x22\x22\x22\x22\x22\x22", + .ksize = 24, + .plaintext = "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44", + .psize = 32, + .iv = "\x33\x33\x33\x33\x33\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00", + } +}; + +struct hash_testvec aes_gmac_256_tv_template[] = { + { + .key = "\x11\x11\x11\x11\x11\x11\x11\x11" + "\x11\x11\x11\x11\x11\x11\x11\x11" + "\x22\x22\x22\x22\x22\x22\x22\x22" + "\x22\x22\x22\x22\x22\x22\x22\x22", + .ksize = 32, + .plaintext = "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44", + .psize = 32, + .iv = "\x33\x33\x33\x33\x33\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00", + } +}; + +struct hash_testvec aes_xcbc_mac_96_tv_template[] = { + { + .key = "\x11\x11\x11\x11\x11\x11\x11\x11" + "\x11\x11\x11\x11\x11\x11\x11\x11", + .ksize = 16, + .plaintext = "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44", + .psize = 32, + } +}; + +struct hash_testvec aes_xcbc_prf_128_tv_template[] = { + { + .key = "\x11\x11\x11\x11\x11\x11\x11\x11" + "\x11\x11\x11\x11\x11\x11\x11\x11", + .ksize = 16, + .plaintext = "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44", + .psize = 32, + } +}; + +struct hash_testvec long_hash_tv_template[] = { + { +/* +md5 (stdin)= 1a1d3a4b00e14b570e404dcfbdd44ebb +sha1 (stdin)= 8c4a63b8a50f28326ee8f251b81d3d114a86c0fc +sha256 (stdin)= 8bdfe2beb94b2cdbd6e1c45a17b36001d694bca2159977ee829466c3c5a34e69 +sha224 (stdin)= 29f0b80a1e5a109b2981cd531978d99254d9c12268e8d3cd193db4d8 +sha384 (stdin)= 0b76ef17eb1c1cec2d896c23576b8dbc2b634afc5dacc18ed8aa48259d02cb91 + ef778e30da2f797c5c7794e456ff8776 + */ + .key = "Jefe", + .ksize = 4, + .plaintext = "\x08\x9f\x13\xaa\x41\xd8\x4c\xe3" + "\x7a\x11\x85\x1c\xb3\x27\xbe\x55" + "\xec\x60\xf7\x8e\x02\x99\x30\xc7" + "\x3b\xd2\x69\x00\x74\x0b\xa2\x16" + "\xad\x44\xdb\x4f\xe6\x7d\x14\x88" + "\x1f\xb6\x2a\xc1\x58\xef\x63\xfa" + "\x91\x05\x9c\x33\xca\x3e\xd5\x6c" + "\x03\x77\x0e\xa5\x19\xb0\x47\xde" + "\x52\xe9\x80\x17\x8b\x22\xb9\x2d" + "\xc4\x5b\xf2\x66\xfd\x94\x08\x9f" + "\x36\xcd\x41\xd8\x6f\x06\x7a\x11" + "\xa8\x1c\xb3\x4a\xe1\x55\xec\x83" + "\x1a\x8e\x25\xbc\x30\xc7\x5e\xf5" + "\x69\x00\x97\x0b\xa2\x39\xd0\x44" + "\xdb\x72\x09\x7d\x14\xab\x1f\xb6" + "\x4d\xe4\x58\xef\x86\x1d\x91\x28" + "\xbf\x33\xca\x61\xf8\x6c\x03\x9a" + "\x0e\xa5\x3c\xd3\x47\xde\x75\x0c" + "\x80\x17\xae\x22\xb9\x50\xe7\x5b" + "\xf2\x89\x20\x94\x2b\xc2\x36\xcd" + "\x64\xfb\x6f\x06\x9d\x11\xa8\x3f" + "\xd6\x4a\xe1\x78\x0f\x83\x1a\xb1" + "\x25\xbc\x53\xea\x5e\xf5\x8c\x00" + "\x97\x2e\xc5\x39\xd0\x67\xfe\x72" + "\x09\xa0\x14\xab\x42\xd9\x4d\xe4" + "\x7b\x12\x86\x1d\xb4\x28\xbf\x56" + "\xed\x61\xf8\x8f\x03\x9a\x31\xc8" + "\x3c\xd3\x6a\x01\x75\x0c\xa3\x17" + "\xae\x45\xdc\x50\xe7\x7e\x15\x89" + "\x20\xb7\x2b\xc2\x59\xf0\x64\xfb" + "\x92\x06\x9d\x34\xcb\x3f\xd6\x6d" + "\x04\x78\x0f\xa6\x1a\xb1\x48\xdf" + "\x53\xea\x81\x18\x8c\x23\xba\x2e" + "\xc5\x5c\xf3\x67\xfe\x95\x09\xa0" + "\x37\xce\x42\xd9\x70\x07\x7b\x12" + "\xa9\x1d\xb4\x4b\xe2\x56\xed\x84" + "\x1b\x8f\x26\xbd\x31\xc8\x5f\xf6" + "\x6a\x01\x98\x0c\xa3\x3a\xd1\x45" + "\xdc\x73\x0a\x7e\x15\xac\x20\xb7" + "\x4e\xe5\x59\xf0\x87\x1e\x92\x29" + "\xc0\x34\xcb\x62\xf9\x6d\x04\x9b" + "\x0f\xa6\x3d\xd4\x48\xdf\x76\x0d" + "\x81\x18\xaf\x23\xba\x51\xe8\x5c" + "\xf3\x8a\x21\x95\x2c\xc3\x37\xce" + "\x65\xfc\x70\x07\x9e\x12\xa9\x40" + "\xd7\x4b\xe2\x79\x10\x84\x1b\xb2" + "\x26\xbd\x54\xeb\x5f\xf6\x8d\x01" + "\x98\x2f\xc6\x3a\xd1\x68\xff\x73" + "\x0a\xa1\x15\xac\x43\xda\x4e\xe5" + "\x7c\x13\x87\x1e\xb5\x29\xc0\x57" + "\xee\x62\xf9\x90\x04\x9b\x32\xc9" + "\x3d\xd4\x6b\x02\x76\x0d\xa4\x18" + "\xaf\x46\xdd\x51\xe8\x7f\x16\x8a" + "\x21\xb8\x2c\xc3\x5a\xf1\x65\xfc" + "\x93\x07\x9e\x35\xcc\x40\xd7\x6e" + "\x05\x79\x10\xa7\x1b\xb2\x49\xe0" + "\x54\xeb\x82\x19\x8d\x24\xbb\x2f" + "\xc6\x5d\xf4\x68\xff\x96\x0a\xa1" + "\x38\xcf\x43\xda\x71\x08\x7c\x13" + "\xaa\x1e\xb5\x4c\xe3\x57\xee\x85" + "\x1c\x90\x27\xbe\x32\xc9\x60\xf7" + "\x6b\x02\x99\x0d\xa4\x3b\xd2\x46" + "\xdd\x74\x0b\x7f\x16\xad\x21\xb8" + "\x4f\xe6\x5a\xf1\x88\x1f\x93\x2a" + "\xc1\x35\xcc\x63\xfa\x6e\x05\x9c" + "\x10\xa7\x3e\xd5\x49\xe0\x77\x0e" + "\x82\x19\xb0\x24\xbb\x52\xe9\x5d" + "\xf4\x8b\x22\x96\x2d\xc4\x38\xcf" + "\x66\xfd\x71\x08\x9f\x13\xaa\x41" + "\xd8\x4c\xe3\x7a\x11\x85\x1c\xb3" + "\x27\xbe\x55\xec\x60\xf7\x8e\x02" + "\x99\x30\xc7\x3b\xd2\x69\x00\x74" + "\x0b\xa2\x16\xad\x44\xdb\x4f\xe6" + "\x7d\x14\x88\x1f\xb6\x2a\xc1\x58" + "\xef\x63\xfa\x91\x05\x9c\x33\xca" + "\x3e\xd5\x6c\x03\x77\x0e\xa5\x19" + "\xb0\x47\xde\x52\xe9\x80\x17\x8b" + "\x22\xb9\x2d\xc4\x5b\xf2\x66\xfd" + "\x94\x08\x9f\x36\xcd\x41\xd8\x6f" + "\x06\x7a\x11\xa8\x1c\xb3\x4a\xe1" + "\x55\xec\x83\x1a\x8e\x25\xbc\x30" + "\xc7\x5e\xf5\x69\x00\x97\x0b\xa2" + "\x39\xd0\x44\xdb\x72\x09\x7d\x14" + "\xab\x1f\xb6\x4d\xe4\x58\xef\x86" + "\x1d\x91\x28\xbf\x33\xca\x61\xf8" + "\x6c\x03\x9a\x0e\xa5\x3c\xd3\x47" + "\xde\x75\x0c\x80\x17\xae\x22\xb9" + "\x50\xe7\x5b\xf2\x89\x20\x94\x2b" + "\xc2\x36\xcd\x64\xfb\x6f\x06\x9d" + "\x11\xa8\x3f\xd6\x4a\xe1\x78\x0f" + "\x83\x1a\xb1\x25\xbc\x53\xea\x5e" + "\xf5\x8c\x00\x97\x2e\xc5\x39\xd0" + "\x67\xfe\x72\x09\xa0\x14\xab\x42" + "\xd9\x4d\xe4\x7b\x12\x86\x1d\xb4" + "\x28\xbf\x56\xed\x61\xf8\x8f\x03" + "\x9a\x31\xc8\x3c\xd3\x6a\x01\x75" + "\x0c\xa3\x17\xae\x45\xdc\x50\xe7" + "\x7e\x15\x89\x20\xb7\x2b\xc2\x59" + "\xf0\x64\xfb\x92\x06\x9d\x34\xcb" + "\x3f\xd6\x6d\x04\x78\x0f\xa6\x1a" + "\xb1\x48\xdf\x53\xea\x81\x18\x8c" + "\x23\xba\x2e\xc5\x5c\xf3\x67\xfe" + "\x95\x09\xa0\x37\xce\x42\xd9\x70" + "\x07\x7b\x12\xa9\x1d\xb4\x4b\xe2" + "\x56\xed\x84\x1b\x8f\x26\xbd\x31" + "\xc8\x5f\xf6\x6a\x01\x98\x0c\xa3" + "\x3a\xd1\x45\xdc\x73\x0a\x7e\x15" + "\xac\x20\xb7\x4e\xe5\x59\xf0\x87" + "\x1e\x92\x29\xc0\x34\xcb\x62\xf9" + "\x6d\x04\x9b\x0f\xa6\x3d\xd4\x48" + "\xdf\x76\x0d\x81\x18\xaf\x23\xba" + "\x51\xe8\x5c\xf3\x8a\x21\x95\x2c" + "\xc3\x37\xce\x65\xfc\x70\x07\x9e" + "\x12\xa9\x40\xd7\x4b\xe2\x79\x10" + "\x84\x1b\xb2\x26\xbd\x54\xeb\x5f" + "\xf6\x8d\x01\x98\x2f\xc6\x3a\xd1" + "\x68\xff\x73\x0a\xa1\x15\xac\x43" + "\xda\x4e\xe5\x7c\x13\x87\x1e\xb5" + "\x29\xc0\x57\xee\x62\xf9\x90\x04" + "\x9b\x32\xc9\x3d\xd4\x6b\x02\x76" + "\x0d\xa4\x18\xaf\x46\xdd\x51\xe8" + "\x7f\x16\x8a\x21\xb8\x2c\xc3\x5a" + "\xf1\x65\xfc\x93\x07\x9e\x35\xcc" + "\x40\xd7\x6e\x05\x79\x10\xa7\x1b" + "\xb2\x49\xe0\x54\xeb\x82\x19\x8d" + "\x24\xbb\x2f\xc6\x5d\xf4\x68\xff" + "\x96\x0a\xa1\x38\xcf\x43\xda\x71" + "\x08\x7c\x13\xaa\x1e\xb5\x4c", + .psize = 1023, + } +}; + +struct hash_testvec hmac_abnormal1024_tv_template[] = { + { + .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa", + .ksize = 131, + .plaintext = "Test Using Large" + "r Than Block-Siz" + "e Key - Hash Key" + " First", + .psize = 54, + } +}; + +struct hash_testvec hmac_abnormal512_tv_template[] = { + { + .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa", + .ksize = 67, + .plaintext = "Test Using Large" + "r Than Block-Siz" + "e Key - Hash Key" + " First", + .psize = 54, + } +}; + +/* 192bit */ +struct cipher_testvec des3_ecb_tv_template_192[] = { + { + .key = "\x10\x46\x10\x34\x89\x98\x80\x20" + "\x91\x07\xd0\x15\x89\x19\x01\x01" + "\x19\x07\x92\x10\x98\x1a\x01\x01", + .klen = 24, + .ptext = "\x00\x00\x00\x00\x00\x00\x00\x00", + .ctext = "\xe1\xef\x62\xc3\x32\xfe\x82\x5b", + .len = 8, + } +}; + +/* 128bit */ +struct cipher_testvec des3_ecb_tv_template_128[] = { + { + .key = "\x10\x46\x10\x34\x89\x98\x80\x20" + "\x91\x07\xd0\x15\x89\x19\x01\x01", + .klen = 16, + .ptext = "\x00\x00\x00\x00\x00\x00\x00\x00", + .ctext = "\x8C\x78\x59\xEB\x1B\xD7\x4F\x0C", + .len = 8, + } +}; + +/* 192bit */ +struct cipher_testvec des3_cbc_tv_template_192[] = { + { + .key = "\xE9\xC0\xFF\x2E\x76\x0B\x64\x24" + "\x44\x4D\x99\x5A\x12\xD6\x40\xC0" + "\xEA\xC2\x84\xE8\x14\x95\xDB\xE8", + .klen = 24, + .iv = "\x7D\x33\x88\x93\x0F\x93\xB2\x42", + .iv_out = "\x6b\xfa\xb1\x91\x13\xb0\xd9\x19", + .ptext = "\x6f\x54\x20\x6f\x61\x4d\x79\x6e" + "\x53\x20\x63\x65\x65\x72\x73\x74" + "\x54\x20\x6f\x6f\x4d\x20\x6e\x61" + "\x20\x79\x65\x53\x72\x63\x74\x65" + "\x20\x73\x6f\x54\x20\x6f\x61\x4d" + "\x79\x6e\x53\x20\x63\x65\x65\x72" + "\x73\x74\x54\x20\x6f\x6f\x4d\x20" + "\x6e\x61\x20\x79\x65\x53\x72\x63" + "\x74\x65\x20\x73\x6f\x54\x20\x6f" + "\x61\x4d\x79\x6e\x53\x20\x63\x65" + "\x65\x72\x73\x74\x54\x20\x6f\x6f" + "\x4d\x20\x6e\x61\x20\x79\x65\x53" + "\x72\x63\x74\x65\x20\x73\x6f\x54" + "\x20\x6f\x61\x4d\x79\x6e\x53\x20" + "\x63\x65\x65\x72\x73\x74\x54\x20" + "\x6f\x6f\x4d\x20\x6e\x61\x0a\x79", + .ctext = "\x0e\x2d\xb6\x97\x3c\x56\x33\xf4" + "\x67\x17\x21\xc7\x6e\x8a\xd5\x49" + "\x74\xb3\x49\x05\xc5\x1c\xd0\xed" + "\x12\x56\x5c\x53\x96\xb6\x00\x7d" + "\x90\x48\xfc\xf5\x8d\x29\x39\xcc" + "\x8a\xd5\x35\x18\x36\x23\x4e\xd7" + "\x76\xd1\xda\x0c\x94\x67\xbb\x04" + "\x8b\xf2\x03\x6c\xa8\xcf\xb6\xea" + "\x22\x64\x47\xaa\x8f\x75\x13\xbf" + "\x9f\xc2\xc3\xf0\xc9\x56\xc5\x7a" + "\x71\x63\x2e\x89\x7b\x1e\x12\xca" + "\xe2\x5f\xaf\xd8\xa4\xf8\xc9\x7a" + "\xd6\xf9\x21\x31\x62\x44\x45\xa6" + "\xd6\xbc\x5a\xd3\x2d\x54\x43\xcc" + "\x9d\xde\xa5\x70\xe9\x42\x45\x8a" + "\x6b\xfa\xb1\x91\x13\xb0\xd9\x19", + .len = 128, + } +}; + +/* 128bit */ +struct cipher_testvec des3_cbc_tv_template_128[] = { + { + .key = "\xE9\xC0\xFF\x2E\x76\x0B\x64\x24" + "\x44\x4D\x99\x5A\x12\xD6\x40\xC0", + .klen = 16, + .iv = "\x7D\x33\x88\x93\x0F\x93\xB2\x42", + .iv_out = "\x6b\xfa\xb1\x91\x13\xb0\xd9\x19", + .ptext = "\x6f\x54\x20\x6f\x61\x4d\x79\x6e" + "\x53\x20\x63\x65\x65\x72\x73\x74" + "\x54\x20\x6f\x6f\x4d\x20\x6e\x61" + "\x20\x79\x65\x53\x72\x63\x74\x65" + "\x20\x73\x6f\x54\x20\x6f\x61\x4d" + "\x79\x6e\x53\x20\x63\x65\x65\x72" + "\x73\x74\x54\x20\x6f\x6f\x4d\x20" + "\x6e\x61\x20\x79\x65\x53\x72\x63" + "\x74\x65\x20\x73\x6f\x54\x20\x6f" + "\x61\x4d\x79\x6e\x53\x20\x63\x65" + "\x65\x72\x73\x74\x54\x20\x6f\x6f" + "\x4d\x20\x6e\x61\x20\x79\x65\x53" + "\x72\x63\x74\x65\x20\x73\x6f\x54" + "\x20\x6f\x61\x4d\x79\x6e\x53\x20" + "\x63\x65\x65\x72\x73\x74\x54\x20" + "\x6f\x6f\x4d\x20\x6e\x61\x0a\x79", + .ctext = "\xC2\x3D\x49\x51\x0B\x2E\xA7\x4C" + "\x8D\x71\x42\x0F\xDD\xFF\xA0\x2D" + "\x5A\xBD\x2F\x0A\xD5\xAF\xEA\xA3" + "\x25\x5A\x22\x99\x71\xB0\xE6\x66" + "\x51\xC2\x31\x79\x82\xEE\x23\xE7" + "\x98\xCD\xFE\x11\x47\x29\xE3\x01" + "\x3F\x8F\xCC\x87\x37\x90\xC3\xA9" + "\x86\xAC\x98\x5C\x2B\x97\xA4\x1E" + "\xE2\xFD\x51\xEA\xBC\x9F\x20\x4A" + "\x80\xFC\xA1\xE8\xDE\x93\x34\x01" + "\xB5\xBF\x6D\xDC\x81\x3E\x71\xB4" + "\x90\x16\x20\xF0\x4E\x4D\xBC\x95" + "\x62\xC1\x89\x91\x72\xEB\xF6\xF6" + "\x58\x4E\x7C\x5B\x73\x17\xD0\x96" + "\xAF\x15\x97\x0D\x6D\xAB\xD0\xFB" + "\x2E\xCD\x07\xF2\xF6\xE6\xB0\x75", + .len = 128, + } +}; + +/* 128bit */ +struct cipher_testvec aes_ecb_tv_template_128[] = { + { + .key = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .klen = 16, + .ptext = "\x00\x11\x22\x33\x44\x55\x66\x77" + "\x88\x99\xaa\xbb\xcc\xdd\xee\xff", + .ctext = "\x69\xc4\xe0\xd8\x6a\x7b\x04\x30" + "\xd8\xcd\xb7\x80\x70\xb4\xc5\x5a", + .len = 16, + } +}; + +/* 192bit */ +struct cipher_testvec aes_ecb_tv_template_192[] = { + { + .key = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17", + .klen = 24, + .ptext = "\x00\x11\x22\x33\x44\x55\x66\x77" + "\x88\x99\xaa\xbb\xcc\xdd\xee\xff", + .ctext = "\xdd\xa9\x7c\xa4\x86\x4c\xdf\xe0" + "\x6e\xaf\x70\xa0\xec\x0d\x71\x91", + .len = 16, + } +}; + +/* 128bit */ +struct cipher_testvec sm4_cbc_tv_template[] = { + { + .key = "\x01\x23\x45\x67\x89\xAB\xCD\xEF" + "\xFE\xDC\xBA\x98\x76\x54\x32\x10", + .klen = 16, + .ptext = "\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb" + "\xcc\xcc\xcc\xcc\xdd\xdd\xdd\xdd" + "\xee\xee\xee\xee\xff\xff\xff\xff" + "\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb", + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", + .iv_out = "\x4C\xB7\x01\x69\x51\x90\x92\x26" + "\x97\x9B\x0D\x15\xDC\x6A\x8F\x6D", + .ctext = "\x78\xEB\xB1\x1C\xC4\x0B\x0A\x48" + "\x31\x2A\xAE\xB2\x04\x02\x44\xCB" + "\x4C\xB7\x01\x69\x51\x90\x92\x26" + "\x97\x9B\x0D\x15\xDC\x6A\x8F\x6D", + .len = 32, + } +}; + +/* 256bit */ +struct cipher_testvec sm4_xts_tv_template[] = { + { + .key = "\x11\x11\x11\x11\x11\x11\x11\x11" + "\x11\x11\x11\x11\x11\x11\x11\x11" + "\x22\x22\x22\x22\x22\x22\x22\x22" + "\x22\x22\x22\x22\x22\x22\x22\x22", + .klen = 32, + .iv = "\x33\x33\x33\x33\x33\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00", + .ptext = "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44", + .ctext = "\xA7\x4D\x72\x6C\x11\x19\x6A\x32" + "\xBE\x04\xE0\x01\xFF\x29\xD0\xC7" + "\x93\x2F\x9F\x3E\xC2\x9B\xFC\xB6" + "\x4D\xD1\x7F\x63\xCB\xD3\xEA\x31", + .len = 32, + } +}; + +/* 256bit */ +struct cipher_testvec aes_ecb_tv_template_256[] = { + { + .key = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", + .klen = 32, + .ptext = "\x00\x11\x22\x33\x44\x55\x66\x77" + "\x88\x99\xaa\xbb\xcc\xdd\xee\xff", + .ctext = "\x8e\xa2\xb7\xca\x51\x67\x45\xbf" + "\xea\xfc\x49\x90\x4b\x49\x60\x89", + .len = 16, + } +}; + +/* 256bit */ +struct cipher_testvec aes_xts_tv_template_256[] = { + { + .key = "\x11\x11\x11\x11\x11\x11\x11\x11" + "\x11\x11\x11\x11\x11\x11\x11\x11" + "\x22\x22\x22\x22\x22\x22\x22\x22" + "\x22\x22\x22\x22\x22\x22\x22\x22", + .klen = 32, + .iv = "\x33\x33\x33\x33\x33\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00", + .ptext = "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44", + .ctext = "\xc4\x54\x18\x5e\x6a\x16\x93\x6e" + "\x39\x33\x40\x38\xac\xef\x83\x8b" + "\xfb\x18\x6f\xff\x74\x80\xad\xc4" + "\x28\x93\x82\xec\xd6\xd3\x94\xf0", + .len = 32, + } +}; + +/* 512bit */ +struct cipher_testvec aes_xts_tv_template_512[] = { + { + .key = "\x27\x18\x28\x18\x28\x45\x90\x45" + "\x23\x53\x60\x28\x74\x71\x35\x26" + "\x62\x49\x77\x57\x24\x70\x93\x69" + "\x99\x59\x57\x49\x66\x96\x76\x27" + "\x31\x41\x59\x26\x53\x58\x97\x93" + "\x23\x84\x62\x64\x33\x83\x27\x95" + "\x02\x88\x41\x97\x16\x93\x99\x37" + "\x51\x05\x82\x09\x74\x94\x45\x92", + .klen = 64, + .iv = "\xff\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00", + .ptext = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + "\x20\x21\x22\x23\x24\x25\x26\x27" + "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" + "\x30\x31\x32\x33\x34\x35\x36\x37" + "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" + "\x40\x41\x42\x43\x44\x45\x46\x47" + "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f" + "\x50\x51\x52\x53\x54\x55\x56\x57" + "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f" + "\x60\x61\x62\x63\x64\x65\x66\x67" + "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f" + "\x70\x71\x72\x73\x74\x75\x76\x77" + "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f" + "\x80\x81\x82\x83\x84\x85\x86\x87" + "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" + "\x90\x91\x92\x93\x94\x95\x96\x97" + "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" + "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7" + "\xa8\xa9\xaa\xab\xac\xad\xae\xaf" + "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7" + "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" + "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" + "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" + "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7" + "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" + "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7" + "\xe8\xe9\xea\xeb\xec\xed\xee\xef" + "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7" + "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff" + "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + "\x20\x21\x22\x23\x24\x25\x26\x27" + "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" + "\x30\x31\x32\x33\x34\x35\x36\x37" + "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" + "\x40\x41\x42\x43\x44\x45\x46\x47" + "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f" + "\x50\x51\x52\x53\x54\x55\x56\x57" + "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f" + "\x60\x61\x62\x63\x64\x65\x66\x67" + "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f" + "\x70\x71\x72\x73\x74\x75\x76\x77" + "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f" + "\x80\x81\x82\x83\x84\x85\x86\x87" + "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" + "\x90\x91\x92\x93\x94\x95\x96\x97" + "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" + "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7" + "\xa8\xa9\xaa\xab\xac\xad\xae\xaf" + "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7" + "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" + "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" + "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" + "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7" + "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" + "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7" + "\xe8\xe9\xea\xeb\xec\xed\xee\xef" + "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7" + "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff", + .ctext = "\x1c\x3b\x3a\x10\x2f\x77\x03\x86" + "\xe4\x83\x6c\x99\xe3\x70\xcf\x9b" + "\xea\x00\x80\x3f\x5e\x48\x23\x57" + "\xa4\xae\x12\xd4\x14\xa3\xe6\x3b" + "\x5d\x31\xe2\x76\xf8\xfe\x4a\x8d" + "\x66\xb3\x17\xf9\xac\x68\x3f\x44" + "\x68\x0a\x86\xac\x35\xad\xfc\x33" + "\x45\xbe\xfe\xcb\x4b\xb1\x88\xfd" + "\x57\x76\x92\x6c\x49\xa3\x09\x5e" + "\xb1\x08\xfd\x10\x98\xba\xec\x70" + "\xaa\xa6\x69\x99\xa7\x2a\x82\xf2" + "\x7d\x84\x8b\x21\xd4\xa7\x41\xb0" + "\xc5\xcd\x4d\x5f\xff\x9d\xac\x89" + "\xae\xba\x12\x29\x61\xd0\x3a\x75" + "\x71\x23\xe9\x87\x0f\x8a\xcf\x10" + "\x00\x02\x08\x87\x89\x14\x29\xca" + "\x2a\x3e\x7a\x7d\x7d\xf7\xb1\x03" + "\x55\x16\x5c\x8b\x9a\x6d\x0a\x7d" + "\xe8\xb0\x62\xc4\x50\x0d\xc4\xcd" + "\x12\x0c\x0f\x74\x18\xda\xe3\xd0" + "\xb5\x78\x1c\x34\x80\x3f\xa7\x54" + "\x21\xc7\x90\xdf\xe1\xde\x18\x34" + "\xf2\x80\xd7\x66\x7b\x32\x7f\x6c" + "\x8c\xd7\x55\x7e\x12\xac\x3a\x0f" + "\x93\xec\x05\xc5\x2e\x04\x93\xef" + "\x31\xa1\x2d\x3d\x92\x60\xf7\x9a" + "\x28\x9d\x6a\x37\x9b\xc7\x0c\x50" + "\x84\x14\x73\xd1\xa8\xcc\x81\xec" + "\x58\x3e\x96\x45\xe0\x7b\x8d\x96" + "\x70\x65\x5b\xa5\xbb\xcf\xec\xc6" + "\xdc\x39\x66\x38\x0a\xd8\xfe\xcb" + "\x17\xb6\xba\x02\x46\x9a\x02\x0a" + "\x84\xe1\x8e\x8f\x84\x25\x20\x70" + "\xc1\x3e\x9f\x1f\x28\x9b\xe5\x4f" + "\xbc\x48\x14\x57\x77\x8f\x61\x60" + "\x15\xe1\x32\x7a\x02\xb1\x40\xf1" + "\x50\x5e\xb3\x09\x32\x6d\x68\x37" + "\x8f\x83\x74\x59\x5c\x84\x9d\x84" + "\xf4\xc3\x33\xec\x44\x23\x88\x51" + "\x43\xcb\x47\xbd\x71\xc5\xed\xae" + "\x9b\xe6\x9a\x2f\xfe\xce\xb1\xbe" + "\xc9\xde\x24\x4f\xbe\x15\x99\x2b" + "\x11\xb7\x7c\x04\x0f\x12\xbd\x8f" + "\x6a\x97\x5a\x44\xa0\xf9\x0c\x29" + "\xa9\xab\xc3\xd4\xd8\x93\x92\x72" + "\x84\xc5\x87\x54\xcc\xe2\x94\x52" + "\x9f\x86\x14\xdc\xd2\xab\xa9\x91" + "\x92\x5f\xed\xc4\xae\x74\xff\xac" + "\x6e\x33\x3b\x93\xeb\x4a\xff\x04" + "\x79\xda\x9a\x41\x0e\x44\x50\xe0" + "\xdd\x7a\xe4\xc6\xe2\x91\x09\x00" + "\x57\x5d\xa4\x01\xfc\x07\x05\x9f" + "\x64\x5e\x8b\x7e\x9b\xfd\xef\x33" + "\x94\x30\x54\xff\x84\x01\x14\x93" + "\xc2\x7b\x34\x29\xea\xed\xb4\xed" + "\x53\x76\x44\x1a\x77\xed\x43\x85" + "\x1a\xd7\x7f\x16\xf5\x41\xdf\xd2" + "\x69\xd5\x0d\x6a\x5f\x14\xfb\x0a" + "\xab\x1c\xbb\x4c\x15\x50\xbe\x97" + "\xf7\xab\x40\x66\x19\x3c\x4c\xaa" + "\x77\x3d\xad\x38\x01\x4b\xd2\x09" + "\x2f\xa7\x55\xc8\x24\xbb\x5e\x54" + "\xc4\xf3\x6f\xfd\xa9\xfc\xea\x70" + "\xb9\xc6\xe6\x93\xe1\x48\xc1\x51", + .len = 512, + } +}; + +/* 128bit */ +struct cipher_testvec aes_cbc_tv_template_128[] = { + { + .key = "\x06\xa9\x21\x40\x36\xb8\xa1\x5b" + "\x51\x2e\x03\xd5\x34\x12\x00\x06", + .klen = 16, + .iv = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30" + "\xb4\x22\xda\x80\x2c\x9f\xac\x41", + .iv_out = "\xe3\x53\x77\x9c\x10\x79\xae\xb8" + "\x27\x08\x94\x2d\xbe\x77\x18\x1a", + .ptext = "Single block msg", + .ctext = "\xe3\x53\x77\x9c\x10\x79\xae\xb8" + "\x27\x08\x94\x2d\xbe\x77\x18\x1a", + .len = 16, + } +}; + +struct cipher_testvec aes_cbc_cs1_tv_template_128[] = { + { + .key = "\x11\x11\x11\x11\x11\x11\x11\x11" + "\x11\x11\x11\x11\x11\x11\x11\x11", + .klen = 16, + .iv = "\x33\x33\x33\x33\x33\x11\x11\x11" + "\x11\x11\x11\x11\x11\x11\x11\x11", + .ptext = "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44", + .ctext = "\x4d\xe5\xc3\xd2\x9e\xe1\x29\x73" + "\x8b\x10\x7b\xde\x5e\x6c\xdb\x36" + "\x95\x35\x5e\x0c\x42\xc8\x33\x7a" + "\x17\x36\xa4\x34\xfd\xb1\x12\xbf", + .len = 32, + } +}; + +struct cipher_testvec aes_cbc_cs1_tv_template_192[] = { + { + .key = "\x11\x11\x11\x11\x11\x11\x11\x11" + "\x11\x11\x11\x11\x11\x11\x11\x11" + "\x22\x22\x22\x22\x22\x22\x22\x22", + .klen = 24, + .iv = "\x33\x33\x33\x33\x33\x11\x11\x11" + "\x11\x11\x11\x11\x11\x11\x11\x11", + .ptext = "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44", + .len = 32, + } +}; + +struct cipher_testvec aes_cbc_cs1_tv_template_256[] = { + { + .key = "\x11\x11\x11\x11\x11\x11\x11\x11" + "\x11\x11\x11\x11\x11\x11\x11\x11" + "\x22\x22\x22\x22\x22\x22\x22\x22" + "\x22\x22\x22\x22\x22\x22\x22\x22", + .klen = 32, + .iv = "\x33\x33\x33\x33\x33\x11\x11\x11" + "\x11\x11\x11\x11\x11\x11\x11\x11", + .ptext = "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44", + .len = 32, + } +}; + +struct cipher_testvec aes_cbc_perf_128[] = { + { + .key = "\x06\xa9\x21\x40\x36\xb8\xa1\x5b" + "\x51\x2e\x03\xd5\x34\x12\x00\x06", + .klen = 16, + .iv = "\xE7\x82\x1D\xB8\x53\x11\xAC\x47" + "\xE2\x7D\x18\xD6\x71\x0C\xA7\x42", + .iv_out = "\xf4\x91\xcc\x1a\xd9\x90\x2b\x02" + "\x89\x1b\x19\x5c\x5b\x5c\x94\x93", + .ptext = "\x50\xB9\x22\xAE\x17\x80\x0C\x75" + "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03" + "\x6C\xF8\x61\xCA\x33\xBF\x28\x91" + "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F" + "\xAB\x14\x7D\x09\x72\xDB\x44\xD0" + "\x39\xA2\x0B\x97\x00\x69\xF5\x5E" + "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC" + "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A" + "\x06\x6F\xD8\x41\xCD\x36\x9F\x08" + "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9" + "\x22\x8B\x17\x80\xE9\x52\xDE\x47" + "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5" + "\x3E\xCA\x33\x9C\x05\x91\xFA\x63" + "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14" + "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2" + "\x0B\x74\x00\x69\xD2\x3B\xC7\x30" + "\x99\x02\x8E\xF7\x60\xEC\x55\xBE" + "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C" + "\x06\xa9\x21\x40\x36\xb8\xa1\x5b" + "\x66\xCF\x38\xC4\x2D\x96\x22\x8B" + "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19" + "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7" + "\x10\x9C\x05\x6E\xFA\x63\xCC\x35" + "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6" + "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74" + "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02" + "\x6B\xF7\x60\xC9\x32\xBE\x27\x90" + "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E" + "\xAA\x13\x7C\x08\x71\xDA\x43\xCF" + "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D" + "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB" + "\x54\xE0\x49\xB2\x1B\xA7\x10\x79" + "\x05\x6E\x35\x40\xCC\x35\x9E\x07" + "\x93\xFC\x65\xF1\x5A\xC3\x2C\xB8" + "\x21\x8A\x16\x7F\xE8\x51\xDD\x46" + "\xAF\x18\xA4\x0D\x76\x02\x6B\xD4" + "\x3D\xC9\x32\x9B\x04\x90\xF9\x62" + "\xEE\x57\xC0\x29\xB5\x1E\x87\x13" + "\x7C\xE5\x4E\xDA\x43\xAC\x15\xA1" + "\x0A\x73\xFF\x68\xD1\x3A\xC6\x2F" + "\x98\x01\x8D\xF6\x5F\xEB\x54\xBD" + "\x26\xB2\x1B\x84\x10\x79\xE2\x4B" + "\xD7\x40\xA9\x12\x9E\x07\x70\xFC" + "\x65\xCE\x37\xC3\x2C\x95\x21\x8A" + "\xF3\x5C\xE8\x51\xBA\x23\xAF\x18" + "\x81\x0D\x76\xDF\x48\xD4\x3D\xA6" + "\x0F\x9B\x0d\x67\xF9\x62\xCB\x34" + "\xC0\x29\x92\x1E\x87\xF0\x59\xE5" + "\x4E\xB7\x20\xAC\x15\x7E\x0A\x73" + "\xDC\x45\xD1\x3A\xA3\x0C\x98\x01" + "\x6A\xF6\x5F\xC8\x31\xBD\x26\x8F" + "\x1B\x84\xED\x56\xE2\x4B\xB4\x1D" + "\xA9\x12\x7B\x07\x70\xD9\x42\xCE" + "\x37\xA0\x09\x95\xFE\x67\xF3\x5C" + "\xC5\x2E\xBA\x23\x8C\x18\x81\xEA" + "\x53\xDF\x48\xB1\x1A\xA6\x0F\x78" + "\x04\x6D\xD6\x3F\xCB\x34\x9D\x06" + "\x92\xFB\x64\x0f\x59\xC2\x2B\xB7" + "\x20\x89\x15\x7E\xE7\x50\xDC\x45" + "\xAE\x17\xA3\x0C\x75\x0f\x6A\xD3" + "\x3C\xC8\x31\x9A\x03\x8F\xF8\x61" + "\xED\x56\xBF\x28\xB4\x1D\x86\x12" + "\xEA\x65\x8A\x19\xB0\x66\xC1\x3F" + "\xCE\xF1\x97\x75\xC1\xFD\xB5\xAF" + "\x52\x65\xF7\xFF\xBC\xD8\x2D\x9F" + "\x2F\xB9\x26\x9B\x6F\x10\xB7\xB8" + "\x26\xA1\x02\x46\xA2\xAD\xC6\xC0" + "\x11\x15\xFF\x6D\x1E\x82\x04\xA6" + "\xB1\x74\xD1\x08\x13\xFD\x90\x7C" + "\xF5\xED\xD3\xDB\x5A\x0A\x0C\x2F" + "\x0A\x70\xF1\x88\x07\xCF\x21\x26" + "\x40\x90\x8A\xF5\x53\xF7\x24\x4F" + "\x83\x38\x43\x5F\x08\x99\xEB\xE3" + "\xDC\x02\x64\x67\x50\x6E\x15\xC3" + "\x01\x1A\xA0\x81\x13\x65\xA6\x73" + "\x71\xA6\x3B\x91\x83\x77\xBE\xFA" + "\xDB\x71\x73\xA6\xC1\xAE\x43\xC3" + "\x36\xCE\xD6\xEB\xF9\x30\x1C\x4F" + "\x80\x38\x5E\x9C\x6E\xAB\x98\x2F" + "\x53\xAF\xCF\xC8\x9A\xB8\x86\x43" + "\x3E\x86\xE7\xA1\xF4\x2F\x30\x40" + "\x03\xA8\x6C\x50\x42\x9F\x77\x59" + "\x89\xA0\xC5\xEC\x9A\xB8\xDD\x99" + "\x16\x24\x02\x07\x48\xAE\xF2\x31" + "\x34\x0E\xC3\x85\xFE\x1C\x95\x99" + "\x87\x58\x98\x8B\xE7\xC6\xC5\x70" + "\x73\x81\x07\x7C\x56\x2F\xD8\x1B" + "\xB7\xB9\x2B\xAB\xE3\x01\x87\x0F" + "\xD8\xBB\xC0\x78\xAC\x2C\x2F\x98" + "\x3C\x0B\xA2\x99\x4A\x8C\xF7\x04" + "\xE0\xE0\xCF\xD1\x81\x5B\xFE\xF5" + "\x24\x04\xFD\xB8\xDF\x13\xD8\xCD" + "\xF1\xE3\x3D\x98\x50\x02\x77\x9E" + "\xBC\x22\xAB\xFA\xC2\x43\x1F\x66" + "\x20\x02\x23\xDA\xDF\xA0\x89\xF6" + "\xD8\xF3\x45\x24\x53\x6F\x16\x77" + "\x02\x3E\x7B\x36\x5F\xA0\x3B\x78" + "\x63\xA2\xBD\xB5\xA4\xCA\x1E\xD3" + "\x57\xBC\x0B\x9F\x43\x51\x28\x4F" + "\x07\x50\x6C\x68\x12\x07\xCF\xFA" + "\x6B\x72\x0B\xEB\xF8\x88\x90\x2C" + "\x7E\xF5\x91\xD1\x03\xD8\xD5\xBD" + "\x22\x39\x7B\x16\x03\x01\x69\xAF" + "\x3D\x38\x66\x28\x0C\xBE\x5B\xC5" + "\x03\xB4\x2F\x51\x8A\x56\x17\x2B" + "\x88\x42\x56\x40\x68\x8F\xD0\x11" + "\x19\xF9\x1F\x43\x79\x95\x31\xFA" + "\x28\x7A\x3D\xF7\x66\xEB\xEF\xAC" + "\x06\xB2\x01\xAD\xDB\x68\xDB\xEC" + "\x8D\x53\x6E\x72\x68\xA3\xC7\x63" + "\x43\x2B\x78\xE0\x04\x29\x8F\x72" + "\xB2\x2C\xE6\x84\x03\x30\x6D\xCD" + "\x26\x92\x37\xE1\x2F\xBB\x8B\x9D" + "\xE4\x4C\xF6\x93\xBC\xD9\xAD\x44" + "\x52\x65\xC7\xB0\x0E\x3F\x0E\x61" + "\x56\x5D\x1C\x6D\xA7\x05\x2E\xBC" + "\x58\x08\x15\xAB\x12\xAB\x17\x4A" + "\x5E\x1C\xF2\xCD\xB8\xA2\xAE\xFB" + "\x9B\x2E\x0E\x85\x34\x80\x0E\x3F" + "\x4C\xB8\xDB\xCE\x1C\x90\xA1\x61" + "\x6C\x69\x09\x35\x9E\xD4\xF4\xAD" + "\xBC\x06\x41\xE3\x01\xB4\x4E\x0A" + "\xE0\x1F\x91\xF8\x82\x96\x2D\x65" + "\xA3\xAA\x13\xCC\x50\xFF\x7B\x02" + "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" + "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" + "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" + "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + .ctext = "\xaf\x7c\xf0\xfb\xe0\xc2\x4c\xd4" + "\x59\x84\x69\x3c\x33\x11\xb6\x4b" + "\x20\x18\x8a\x4d\x7f\x4a\xf8\xf4" + "\xca\xf6\x1d\x0b\x50\x5b\x99\x25" + "\x76\xc6\xea\x65\x58\x8a\xab\xab" + "\x58\xb0\xb3\x60\x60\x69\xf6\x6f" + "\x36\x04\x01\x3e\x1e\x79\x3d\x2f" + "\xb9\x87\x74\xcb\x7c\x21\xb7\x37" + "\x00\xfe\x52\xd8\x20\xf8\x63\x5e" + "\x7a\xd1\x62\xe4\x84\xf8\x52\x90" + "\x54\xa1\x17\x04\xa6\x8a\x12\xa4" + "\x04\x78\x84\x3d\xd2\x34\x42\xd9" + "\x21\xd0\xaa\x18\x5e\xf0\x00\x62" + "\x16\x0e\x72\x6f\x9a\x8e\xc2\x10" + "\x57\x68\x70\xa2\x2e\x4c\x00\xcf" + "\x78\x35\x44\x73\xf8\xde\xa5\x75" + "\xec\x15\x55\xc9\xbe\x44\xd4\x8d" + "\x82\x31\x0a\x28\xaf\x06\x07\x8e" + "\x52\xf2\xf6\x69\x75\x35\x2e\xd6" + "\xbc\x8d\x7d\x54\x1e\xad\xd1\x65" + "\x33\x6e\xee\x85\x77\xed\x12\xcb" + "\x98\x3c\x82\x92\xb9\x0c\x58\x1f" + "\x66\x05\x33\x1c\x02\x08\x96\xf9" + "\x78\x36\x8a\xd5\x68\x90\x1d\x19" + "\x1c\xe1\x36\xbb\xce\x06\x8e\xdf" + "\x27\xd1\xa9\x7f\x37\xf1\x7b\x65" + "\x6a\xdd\x0a\x77\x0c\x19\x71\x7f" + "\xd7\x62\x65\x60\x1b\x2f\xb2\xce" + "\x2f\xa1\xed\x28\xc9\x3c\x8c\xa0" + "\x91\x17\x4d\xa3\xd8\x5f\x3d\x6a" + "\x9d\x3c\xc4\xc8\x7d\x72\xac\xba" + "\xb9\x5c\xfe\x7d\x03\x30\x64\x76" + "\x87\x27\xe8\x1e\xb1\xab\x18\x2d" + "\x48\x63\x8a\xce\xf4\xa6\x3a\xb6" + "\x0d\x01\x09\xdf\x61\xd4\xed\xb5" + "\xdb\x1d\xe1\x23\x43\x70\x03\x28" + "\x25\xc5\x19\xb0\x7d\xa7\x57\xf1" + "\x02\xc2\x94\x65\xaa\xb5\x44\x52" + "\x22\xc9\x9a\x1e\x7d\x8c\x9a\xb0" + "\x74\x32\xba\xec\xe9\xb5\xb3\x25" + "\x8b\xc7\xe9\x26\xaa\x3d\xf8\xe7" + "\x57\x84\xa2\x2e\x3e\x15\x41\x26" + "\x91\xa5\x71\x1f\xdd\x2d\xe3\x7a" + "\x40\xd9\xc9\xba\x6f\xd1\xff\xc6" + "\x4a\x18\x8d\xdb\x08\x0d\x04\x56" + "\xca\x02\xbe\xea\xe7\x02\x83\xc6" + "\x1d\xcd\x3c\xd0\xaa\x89\x8b\xb6" + "\x68\x29\x17\x41\xb3\x6c\x49\x66" + "\xe8\xe4\x71\xf4\xc2\x2c\x0b\x52" + "\x60\x4e\x3e\x16\x24\x9c\x95\xd2" + "\x54\x4e\x1e\xc8\xf3\x26\xf5\x83" + "\xad\x8e\xb7\x06\x97\xd8\x92\x9f" + "\xa3\x9e\x3b\x24\xc2\x03\x5d\xdb" + "\x01\xc0\x17\xd1\xe8\x63\x50\x1a" + "\x0b\xb8\x6c\x3a\x50\x50\x69\xbc" + "\xa1\x19\xb8\x28\xb1\xd3\x93\xd4" + "\x6e\x1d\x01\xcd\xd3\x1e\xc8\xe4" + "\xbf\x56\xe8\x7e\xf3\xf0\xa2\x96" + "\xa2\x12\xea\xfd\x83\x4d\x6d\xef" + "\x49\xd4\xaa\x31\xe1\x2e\x6a\x2c" + "\x7d\xcf\xa4\xdb\xf8\xb1\x1e\xbf" + "\x1d\x86\x43\x6a\x77\x44\x9e\x95" + "\xf0\xa3\xe5\x43\x50\xc7\xb8\xa7" + "\xb4\xe0\x58\x4d\x8b\xed\x96\x7c" + "\x06\x72\x81\x67\x54\x14\x2c\x00" + "\xae\x18\x65\xf4\x62\x4c\x44\x3b" + "\x53\xd0\xee\x0a\xf2\x94\x64\xa5" + "\xd7\x87\xb4\x56\xce\xa6\x27\xb3" + "\xdd\x22\xc9\x5d\xb2\xaf\x4d\xa4" + "\x65\x39\x52\xde\x76\x11\x04\xbc" + "\x24\x4e\x92\xcc\x59\x2f\x34\xaa" + "\x7a\xbd\x9f\xfd\x38\x2a\x2c\xca" + "\x26\xc6\xa0\x20\xf0\xcd\x77\xae" + "\x18\xed\x5e\x09\x26\x7f\xc3\x17" + "\x36\xc9\xad\xed\xd6\xb4\xe4\x0c" + "\x1b\x68\x08\xc2\x37\xb9\x46\xcf" + "\xbd\x22\x0a\x31\x1d\xb6\x84\x4e" + "\xa1\xbe\xb8\x90\xe6\x69\xb9\x3e" + "\x11\x0a\x14\x05\x7a\x56\x95\x06" + "\xfd\x3d\x5c\x74\x98\xb0\xb9\x5c" + "\x0b\x11\x83\xd1\x0c\x36\x7b\x0e" + "\x79\xef\xdf\xf5\xf2\x19\x8d\x3e" + "\x32\x3b\x21\x74\x9f\x97\xba\xd5" + "\x50\x80\x49\x58\x61\x9b\x34\x2a" + "\x5d\xb3\x2e\xdb\xa9\x5f\x36\x1e" + "\x01\xac\xed\xc2\xe5\x05\xdb\x14" + "\x60\xbe\x2e\xd4\xbb\xa0\x76\xbe" + "\x0f\xbe\xaf\xf2\xff\x89\x2b\x47" + "\xed\xef\xe8\x37\x63\xcf\x27\x9f" + "\x74\x37\xc9\x5e\x53\xce\xc6\xfb" + "\x10\xd9\x32\x5b\x39\x8b\x52\x2c" + "\x79\xce\xe5\xad\xb9\xa2\x67\xe0" + "\xb6\x1f\x85\x68\x80\x9b\x29\xf0" + "\x2e\x20\x27\x1e\xbe\xaf\x2c\x50" + "\x33\x6e\x93\x02\x90\x4d\x26\x0c" + "\x01\x0c\x73\x13\x77\x90\x2f\x7c" + "\x74\x05\x03\x21\xf3\x15\x27\xfa" + "\xb5\xdd\x1e\xbb\xf5\xd7\xac\x7e" + "\x2b\xdb\x62\xe7\x5b\xb7\x43\x7a" + "\x82\x97\x21\x83\x4f\x2a\xa9\x7c" + "\xf3\xd7\xf8\x7e\x9f\xf5\x5f\x26" + "\x2b\xd6\x64\x7b\xec\xa6\x6e\x8f" + "\xc4\x2e\x1c\xf6\x69\xf0\x8b\x85" + "\x3e\xf8\xe6\x08\x28\x55\xa6\xb5" + "\x86\x48\xbe\x87\xfb\x3e\x7a\x69" + "\x32\xde\x69\x53\x16\x7c\x80\xb7" + "\x49\x90\xf1\x9f\x96\x90\xb7\xaf" + "\x31\xce\x4f\xfd\x7e\xa8\xb3\x57" + "\xf1\x11\x2e\xa5\x8d\x74\x42\x32" + "\xb4\x5a\x87\x1a\x1a\x41\xa8\x9e" + "\x01\x7e\x0a\xab\x4c\xd7\x09\x52" + "\x92\xfb\xb3\x45\xe7\x2c\x17\x3d" + "\x17\x25\xa7\x63\x9e\x02\xcd\x3f" + "\x5e\x2e\x55\xb0\xc6\x07\x28\x61" + "\x9c\x50\xe1\xa2\x03\xec\x21\x9e" + "\x49\x2c\x3a\xb7\x56\x36\x1b\x02" + "\xfc\x84\x96\xc5\x40\x8d\x35\x39" + "\x22\x94\xb5\x0a\x97\xb7\xc6\x50" + "\x55\xf0\x3b\xf1\x80\xf1\xdf\x44" + "\xb7\x05\x1b\xdb\x7c\x57\xca\xb9" + "\x50\x2e\x9f\x35\x8b\x7f\x9e\xd8" + "\x8b\xee\xee\xe7\xc1\xac\xf5\xd2" + "\x41\xfb\x5c\x8f\x89\x57\x9d\x54" + "\x05\x1f\xa5\x29\x8d\x05\x42\x24" + "\xba\x7a\xe2\x6d\x67\x90\x9b\x5e" + "\x6b\x4a\x71\x1c\x60\x1e\xd8\x93" + "\xf4\x91\xcc\x1a\xd9\x90\x2b\x02" + "\x89\x1b\x19\x5c\x5b\x5c\x94\x93", + .len = 1024, + } +}; + +/* 192bit */ +struct cipher_testvec aes_cbc_tv_template_192[] = { + /* From NIST SP800-38A */ + { + .key = "\x8e\x73\xb0\xf7\xda\x0e\x64\x52" + "\xc8\x10\xf3\x2b\x80\x90\x79\xe5" + "\x62\xf8\xea\xd2\x52\x2c\x6b\x7b", + .klen = 24, + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .iv_out = "\x08\xb0\xe2\x79\x88\x59\x88\x81" + "\xd9\x20\xa9\xe6\x4f\x56\x15\xcd", + .ptext = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" + "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" + "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" + "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" + "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" + "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + .ctext = "\x4f\x02\x1d\xb2\x43\xbc\x63\x3d" + "\x71\x78\x18\x3a\x9f\xa0\x71\xe8" + "\xb4\xd9\xad\xa9\xad\x7d\xed\xf4" + "\xe5\xe7\x38\x76\x3f\x69\x14\x5a" + "\x57\x1b\x24\x20\x12\xfb\x7a\xe0" + "\x7f\xa9\xba\xac\x3d\xf1\x02\xe0" + "\x08\xb0\xe2\x79\x88\x59\x88\x81" + "\xd9\x20\xa9\xe6\x4f\x56\x15\xcd", + .len = 64, + } +}; +/* 256bit */ +struct cipher_testvec aes_cbc_tv_template_256[] = { + { + .key = "\x60\x3d\xeb\x10\x15\xca\x71\xbe" + "\x2b\x73\xae\xf0\x85\x7d\x77\x81" + "\x1f\x35\x2c\x07\x3b\x61\x08\xd7" + "\x2d\x98\x10\xa3\x09\x14\xdf\xf4", + .klen = 32, + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .iv_out = "\xb2\xeb\x05\xe2\xc3\x9b\xe9\xfc" + "\xda\x6c\x19\x07\x8c\x6a\x9d\x1b", + .ptext = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" + "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" + "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" + "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" + "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" + "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + .ctext = "\xf5\x8c\x4c\x04\xd6\xe5\xf1\xba" + "\x77\x9e\xab\xfb\x5f\x7b\xfb\xd6" + "\x9c\xfc\x4e\x96\x7e\xdb\x80\x8d" + "\x67\x9f\x77\x7b\xc6\x70\x2c\x7d" + "\x39\xf2\x33\x69\xa9\xd9\xba\xcf" + "\xa5\x30\xe2\x63\x04\x23\x14\x61" + "\xb2\xeb\x05\xe2\xc3\x9b\xe9\xfc" + "\xda\x6c\x19\x07\x8c\x6a\x9d\x1b", + .len = 64, + } +}; + +struct cipher_testvec aes_ofb_tv_template_128[] = { + { + .key = "\x2b\x7e\x15\x16\x28\xae\xd2\xa6" + "\xab\xf7\x15\x88\x09\xcf\x4f\x3c", + .klen = 16, + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .ptext = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" + "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" + "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" + "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" + "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" + "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + .ctext = "\x3b\x3f\xd9\x2e\xb7\x2d\xad\x20" + "\x33\x34\x49\xf8\xe8\x3c\xfb\x4a" + "\x77\x89\x50\x8d\x16\x91\x8f\x03" + "\xf5\x3c\x52\xda\xc5\x4e\xd8\x25" + "\x97\x40\x05\x1e\x9c\x5f\xec\xf6" + "\x43\x44\xf7\xa8\x22\x60\xed\xcc" + "\x30\x4c\x65\x28\xf6\x59\xc7\x78" + "\x66\xa5\x10\xd9\xc1\xd6\xae\x5e", + .len = 64, + } +}; + +//openssl create +struct cipher_testvec aes_ofb_tv_template_192[] = { + { + .key = "\x2b\x7e\x15\x16\x28\xae\xd2\xa6" + "\xab\xf7\x15\x88\x09\xcf\x4f\x3c" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .klen = 24, + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .ptext = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" + "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" + "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" + "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" + "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" + "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + .ctext = "\x6e\x29\x6a\xb1\x64\x8b\x7b\x81" + "\xfa\x62\x8f\xfa\xc6\x9f\x48\x6f" + "\x32\xe2\xaa\x04\x6a\x81\x04\xb8" + "\xc1\xe4\xe5\x1b\xb0\xc1\x89\xca" + "\x41\x6d\x43\xf1\x83\xf4\x9d\x90" + "\xbf\x68\xe6\xea\xd5\xed\x83\x1c" + "\xff\xf2\xf9\xfa\xf8\x3e\xba\x82" + "\x7e\xca\x94\x72\x64\x3f\x72\xdf", + .len = 64, + } +}; + +struct cipher_testvec aes_ofb_tv_template_256[] = { + { + .key = "\x2b\x7e\x15\x16\x28\xae\xd2\xa6" + "\xab\xf7\x15\x88\x09\xcf\x4f\x3c" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x00\x01\x02\x03\x04\x05\x06\x07", + .klen = 32, + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .ptext = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" + "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" + "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" + "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" + "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" + "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + .ctext = "\x36\x7d\xf9\x01\x2f\x31\xde\x8c" + "\x7f\xc1\x26\x1a\xbc\x8a\x35\xe5" + "\x00\x24\xad\xcb\x60\x5d\xb9\xea" + "\x12\xdd\x0b\xd2\x44\x2a\x24\x51" + "\x4f\x13\x1e\x7c\xa2\xad\xe9\x8c" + "\x55\x80\x75\xc6\x4d\xf2\x24\xde" + "\x30\xa0\xbb\xe7\x6d\xf8\xd1\x23" + "\x9d\x9f\xad\xd2\x9f\x87\x4f\x1c", + .len = 64, + } +}; + + +struct cipher_testvec aes_cfb_tv_template_128[] = { + { /* From NIST SP800-38A */ + .key = "\x2b\x7e\x15\x16\x28\xae\xd2\xa6" + "\xab\xf7\x15\x88\x09\xcf\x4f\x3c", + .klen = 16, + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .ptext = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" + "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" + "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" + "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" + "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" + "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + .ctext = "\x3b\x3f\xd9\x2e\xb7\x2d\xad\x20" + "\x33\x34\x49\xf8\xe8\x3c\xfb\x4a" + "\xc8\xa6\x45\x37\xa0\xb3\xa9\x3f" + "\xcd\xe3\xcd\xad\x9f\x1c\xe5\x8b" + "\x26\x75\x1f\x67\xa3\xcb\xb1\x40" + "\xb1\x80\x8c\xf1\x87\xa4\xf4\xdf" + "\xc0\x4b\x05\x35\x7c\x5d\x1c\x0e" + "\xea\xc4\xc6\x6f\x9f\xf7\xf2\xe6", + .len = 64, + } +}; + +struct cipher_testvec aes_cfb_tv_template_192[] = { + { + .key = "\x8e\x73\xb0\xf7\xda\x0e\x64\x52" + "\xc8\x10\xf3\x2b\x80\x90\x79\xe5" + "\x62\xf8\xea\xd2\x52\x2c\x6b\x7b", + .klen = 24, + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .ptext = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" + "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" + "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" + "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" + "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" + "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + .ctext = "\xcd\xc8\x0d\x6f\xdd\xf1\x8c\xab" + "\x34\xc2\x59\x09\xc9\x9a\x41\x74" + "\x67\xce\x7f\x7f\x81\x17\x36\x21" + "\x96\x1a\x2b\x70\x17\x1d\x3d\x7a" + "\x2e\x1e\x8a\x1d\xd5\x9b\x88\xb1" + "\xc8\xe6\x0f\xed\x1e\xfa\xc4\xc9" + "\xc0\x5f\x9f\x9c\xa9\x83\x4f\xa0" + "\x42\xae\x8f\xba\x58\x4b\x09\xff", + .len = 64, + } +}; + +struct cipher_testvec aes_cfb_tv_template_256[] = { + { + .key = "\x60\x3d\xeb\x10\x15\xca\x71\xbe" + "\x2b\x73\xae\xf0\x85\x7d\x77\x81" + "\x1f\x35\x2c\x07\x3b\x61\x08\xd7" + "\x2d\x98\x10\xa3\x09\x14\xdf\xf4", + .klen = 32, + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .ptext = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" + "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" + "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" + "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" + "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" + "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + .ctext = "\xdc\x7e\x84\xbf\xda\x79\x16\x4b" + "\x7e\xcd\x84\x86\x98\x5d\x38\x60" + "\x39\xff\xed\x14\x3b\x28\xb1\xc8" + "\x32\x11\x3c\x63\x31\xe5\x40\x7b" + "\xdf\x10\x13\x24\x15\xe5\x4b\x92" + "\xa1\x3e\xd0\xa8\x26\x7a\xe2\xf9" + "\x75\xa3\x85\x74\x1a\xb9\xce\xf8" + "\x20\x31\x62\x3d\x55\xb1\xe4\x71", + .len = 64, + } +}; + +struct cipher_testvec sm4_ecb_tv_template_128[] = { + { /* A.2.1.1 SM4-ECB Example 1 */ + .key = "\x01\x23\x45\x67\x89\xAB\xCD\xEF" + "\xFE\xDC\xBA\x98\x76\x54\x32\x10", + .klen = 16, + .ptext = "\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb" + "\xcc\xcc\xcc\xcc\xdd\xdd\xdd\xdd" + "\xee\xee\xee\xee\xff\xff\xff\xff" + "\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb", + .ctext = "\x5e\xc8\x14\x3d\xe5\x09\xcf\xf7" + "\xb5\x17\x9f\x8f\x47\x4b\x86\x19" + "\x2f\x1d\x30\x5a\x7f\xb1\x7d\xf9" + "\x85\xf8\x1c\x84\x82\x19\x23\x04", + .len = 32, + } +}; + +//openssl create sm4_ofb template +struct cipher_testvec sm4_ofb_tv_template_128[] = { + { /* From NIST SP800-38A */ + .key = "\x2b\x7e\x15\x16\x28\xae\xd2\xa6" + "\xab\xf7\x15\x88\x09\xcf\x4f\x3c", + .klen = 16, + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .ptext = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a", + .ctext = "\xbc\x71\x0d\x76\x2d\x07\x0b\x26" + "\x36\x1d\xa8\x2b\x54\x56\x5e\x46", + .len = 16, + } +}; +//openssl create sm4_cfb template +struct cipher_testvec sm4_cfb_tv_template_128[] = { + { /* From NIST SP800-38A */ + .key = "\x2b\x7e\x15\x16\x28\xae\xd2\xa6" + "\xab\xf7\x15\x88\x09\xcf\x4f\x3c", + .klen = 16, + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .ptext = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a", + .ctext = "\xbc\x71\x0d\x76\x2d\x07\x0b\x26" + "\x36\x1d\xa8\x2b\x54\x56\x5e\x46", + .len = 16, + } +}; + +/* 128bit */ +struct aead_testvec aes_ccm_tv_template_128[] = { + { + .key = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" + "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf", + .klen = 16, + .iv = "\x01\x00\x00\x00\x03\x02\x01\x00" + "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00", + .assoc = "\x00\x01\x02\x03\x04\x05\x06\x07", + .alen = 8, + .ptext = "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e", + .plen = 23, + .ctext = "\x58\x8c\x97\x9a\x61\xc6\x63\xd2" + "\xf0\x66\xd0\xc2\xc0\xf9\x89\x80" + "\x6d\x5f\x6b\x61\xda\xc3\x84\x17" + "\xe8\xd1\x2c\xfd\xf9\x26\xe0", + .clen = 31, + } +}; + +/* 192bit */ +struct aead_testvec aes_ccm_tv_template_192[] = { + { + .key = "\x56\xdf\x5c\x8f\x26\x3f\x0e\x42" + "\xef\x7a\xd3\xce\xfc\x84\x60\x62" + "\xca\xb4\x40\xaf\x5f\xc9\xc9\x01", + .klen = 24, + .iv = "\x03\xd6\x3c\x8c\x86\x84\xb6\xcd" + "\xef\x09\x2e\x94\x00\x00\x00\x00", + .assoc = "\x02\x65\x78\x3c\xe9\x21\x30\x91" + "\xb1\xb9\xda\x76\x9a\x78\x6d\x95" + "\xf2\x88\x32\xa3\xf2\x50\xcb\x4c" + "\xe3\x00\x73\x69\x84\x69\x87\x79", + .alen = 32, + .ptext = "\x9f\xd2\x02\x4b\x52\x49\x31\x3c" + "\x43\x69\x3a\x2d\x8e\x70\xad\x7e" + "\xe0\xe5\x46\x09\x80\x89\x13\xb2" + "\x8c\x8b\xd9\x3f\x86\xfb\xb5\x6b", + .plen = 32, + .ctext = "\x39\xdf\x7c\x3c\x5a\x29\xb9\x62" + "\x5d\x51\xc2\x16\xd8\xbd\x06\x9f" + "\x9b\x6a\x09\x70\xc1\x51\x83\xc2" + "\x66\x88\x1d\x4f\x9a\xda\xe0\x1e" + "\xc7\x79\x11\x58\xe5\x6b\x20\x40" + "\x7a\xea\x46\x42\x8b\xe4\x6f\xe1", + .clen = 48, + } +}; + +/* 256bit */ +struct aead_testvec aes_ccm_tv_template_256[] = { + { + .key = "\xe0\x8d\x99\x71\x60\xd7\x97\x1a" + "\xbd\x01\x99\xd5\x8a\xdf\x71\x3a" + "\xd3\xdf\x24\x4b\x5e\x3d\x4b\x4e" + "\x30\x7a\xb9\xd8\x53\x0a\x5e\x2b", + .klen = 32, + .iv = "\x03\x1e\x29\x91\xad\x8e\xc1\x53" + "\x0a\xcf\x2d\xbe\x00\x00\x00\x00", + .assoc = "\x19\xb6\x1f\x57\xc4\xf3\xf0\x8b" + "\x78\x2b\x94\x02\x29\x0f\x42\x27" + "\x6b\x75\xcb\x98\x34\x08\x7e\x79" + "\xe4\x3e\x49\x0d\x84\x8b\x22\x87", + .alen = 32, + .ptext = "\xe1\xd9\xd8\x13\xeb\x3a\x75\x3f" + "\x9d\xbd\x5f\x66\xbe\xdc\xbb\x66" + "\xbf\x17\x99\x62\x4a\x39\x27\x1f" + "\x1d\xdc\x24\xae\x19\x2f\x98\x4c", + .plen = 32, + .ctext = "\x19\xb8\x61\x33\x45\x2b\x43\x96" + "\x6f\x51\xd0\x20\x30\x7d\x9b\xc6" + "\x26\x3d\xf8\xc9\x65\x16\xa8\x9f" + "\xf0\x62\x17\x34\xf2\x1e\x8d\x75" + "\x4e\x13\xcc\xc0\xc3\x2a\x54\x2d", + .clen = 40, + } +}; + +/* 128bit */ +struct aead_testvec aes_gcm_tv_template_128[] = { + { + .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c" + "\x6d\x6a\x8f\x94\x67\x30\x83\x08", + .klen = 16, + .iv = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad" + "\xde\xca\xf8\x88", + .ptext = "\xd9\x31\x32\x25\xf8\x84\x06\xe5" + "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" + "\x86\xa7\xa9\x53\x15\x34\xf7\xda" + "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" + "\x1c\x3c\x0c\x95\x95\x68\x09\x53" + "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" + "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57" + "\xba\x63\x7b\x39\x1a\xaf\xd2\x55", + .plen = 64, + .ctext = "\x42\x83\x1e\xc2\x21\x77\x74\x24" + "\x4b\x72\x21\xb7\x84\xd0\xd4\x9c" + "\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0" + "\x35\xc1\x7e\x23\x29\xac\xa1\x2e" + "\x21\xd5\x14\xb2\x54\x66\x93\x1c" + "\x7d\x8f\x6a\x5a\xac\x84\xaa\x05" + "\x1b\xa3\x0b\x39\x6a\x0a\xac\x97" + "\x3d\x58\xe0\x91\x47\x3f\x59\x85" + "\x4d\x5c\x2a\xf3\x27\xcd\x64\xa6" + "\x2c\xf3\x5a\xbd\x2b\xa6\xfa\xb4", + .clen = 80, + } +}; + +/* 192bit */ +struct aead_testvec aes_gcm_tv_template_192[] = { + { + .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c" + "\x6d\x6a\x8f\x94\x67\x30\x83\x08" + "\xfe\xff\xe9\x92\x86\x65\x73\x1c", + .klen = 24, + .iv = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad" + "\xde\xca\xf8\x88", + .ptext = "\xd9\x31\x32\x25\xf8\x84\x06\xe5" + "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" + "\x86\xa7\xa9\x53\x15\x34\xf7\xda" + "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" + "\x1c\x3c\x0c\x95\x95\x68\x09\x53" + "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" + "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57" + "\xba\x63\x7b\x39\x1a\xaf\xd2\x55", + .plen = 64, + .ctext = "\x39\x80\xca\x0b\x3c\x00\xe8\x41" + "\xeb\x06\xfa\xc4\x87\x2a\x27\x57" + "\x85\x9e\x1c\xea\xa6\xef\xd9\x84" + "\x62\x85\x93\xb4\x0c\xa1\xe1\x9c" + "\x7d\x77\x3d\x00\xc1\x44\xc5\x25" + "\xac\x61\x9d\x18\xc8\x4a\x3f\x47" + "\x18\xe2\x44\x8b\x2f\xe3\x24\xd9" + "\xcc\xda\x27\x10\xac\xad\xe2\x56" + "\x99\x24\xa7\xc8\x58\x73\x36\xbf" + "\xb1\x18\x02\x4d\xb8\x67\x4a\x14", + .clen = 80, + } +}; + +/* 256bit */ +struct aead_testvec aes_gcm_tv_template_256[] = { + { + .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c" + "\x6d\x6a\x8f\x94\x67\x30\x83\x08" + "\xfe\xff\xe9\x92\x86\x65\x73\x1c" + "\x6d\x6a\x8f\x94\x67\x30\x83\x08", + .klen = 32, + .iv = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad" + "\xde\xca\xf8\x88", + .ptext = "\xd9\x31\x32\x25\xf8\x84\x06\xe5" + "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" + "\x86\xa7\xa9\x53\x15\x34\xf7\xda" + "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" + "\x1c\x3c\x0c\x95\x95\x68\x09\x53" + "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" + "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57" + "\xba\x63\x7b\x39", + .plen = 60, + .assoc = "\xfe\xed\xfa\xce\xde\xad\xbe\xef" + "\xfe\xed\xfa\xce\xde\xad\xbe\xef" + "\xab\xad\xda\xd2", + .alen = 20, + .ctext = "\x52\x2d\xc1\xf0\x99\x56\x7d\x07" + "\xf4\x7f\x37\xa3\x2a\x84\x42\x7d" + "\x64\x3a\x8c\xdc\xbf\xe5\xc0\xc9" + "\x75\x98\xa2\xbd\x25\x55\xd1\xaa" + "\x8c\xb0\x8e\x48\x59\x0d\xbb\x3d" + "\xa7\xb0\x8b\x10\x56\x82\x88\x38" + "\xc5\xf6\x1e\x63\x93\xba\x7a\x0a" + "\xbc\xc9\xf6\x62" + "\x76\xfc\x6e\xce\x0f\x4e\x17\x68" + "\xcd\xdf\x88\x53\xbb\x2d\x55\x1b", + .clen = 76, + } +}; + +struct aead_testvec hmac_sha256_aes_cbc_tv_temp[] = { + { +#ifdef __LITTLE_ENDIAN + .key = "\x08\x00" /* rta length */ + "\x01\x00" /* rta type */ +#else + .key = "\x00\x08" /* rta length */ + "\x00\x01" /* rta type */ +#endif + "\x00\x00\x00\x10" /* enc key length */ + "\x20\x21\x22\x23\x24\x25\x26\x27" + "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" + "\x30\x31\x32\x33\x34\x35\x36\x37" + "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" + "\xc2\x86\x69\x6d\x88\x7c\x9a\xa0" + "\x61\x1b\xbb\x3e\x20\x25\xa4\x5a", + .klen = 8 + 32 + 16, + .iv = "\x56\x2e\x17\x99\x6d\x09\x3d\x28" + "\xdd\xb3\xba\x69\x5a\x2e\x6f\x58", + .assoc = "\x56\x2e\x17\x99\x6d\x09\x3d\x28" + "\xdd\xb3\xba\x69\x5a\x2e\x6f\x58", + .alen = 16, + .ptext = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", + .plen = 32, + .ctext = "\xd2\x96\xcd\x94\xc2\xcc\xcf\x8a" + "\x3a\x86\x30\x28\xb5\xe1\xdc\x0a" + "\x75\x86\x60\x2d\x25\x3c\xff\xf9" + "\x1b\x82\x66\xbe\xa6\xd6\x1a\xb1" + "\xf5\x33\x53\xf3\x68\x85\x2a\x99" + "\x0e\x06\x58\x8f\xba\xf6\x06\xda" + "\x49\x69\x0d\x5b\xd4\x36\x06\x62" + "\x35\x5e\x54\x58\x53\x4d\xdf\xbf", + .clen = 32 + 32, + } +}; + +/* 128bit */ +struct aead_testvec sm4_ccm_tv_template_128[] = { + { + .key = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" + "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf", + .klen = 16, + .iv = "\x01\x00\x00\x00\x03\x02\x01\x00" + "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00", + .assoc = "\x00\x01\x02\x03\x04\x05\x06\x07", + .alen = 8, + .ptext = "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e", + .plen = 23, + .ctext = "\x7B\xFF\x4A\x15\xF5\x73\xCE\x82" + "\x6E\xC2\x31\x1D\xE2\x53\x02\xAC" + "\xA4\x48\xF9\xE4\xF5\x1F\x81\x70" + "\x18\xBC\xB6\x84\x01\xB8\xAE", + .clen = 31, + } +}; + +/* 128bit */ +struct aead_testvec sm4_gcm_tv_template_128[] = { + { + .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c" + "\x6d\x6a\x8f\x94\x67\x30\x83\x08", + .klen = 16, + .iv = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad" + "\xde\xca\xf8\x88", + .ptext = "\xd9\x31\x32\x25\xf8\x84\x06\xe5" + "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" + "\x86\xa7\xa9\x53\x15\x34\xf7\xda" + "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" + "\x1c\x3c\x0c\x95\x95\x68\x09\x53" + "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" + "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57" + "\xba\x63\x7b\x39\x1a\xaf\xd2\x55", + .plen = 64, + .ctext = "\xe4\x11\x0f\xf1\xc1\x41\x97\xe6" + "\x76\x21\x6a\x33\x83\x10\x41\xeb" + "\x09\x58\x00\x11\x7b\xdc\x3f\x75" + "\x1a\x49\x6e\xfc\xf2\xbb\xdf\xdb" + "\x3a\x2e\x13\xfd\xc5\xc1\x9d\x07" + "\x1a\xe5\x48\x3f\xed\xde\x98\x5d" + "\x3f\x2d\x5b\x4e\xee\x0b\xb6\xdf" + "\xe3\x63\x36\x83\x23\xf7\x5b\x80" + "\x7d\xfe\x77\xef\x71\xb1\x5e\xc9" + "\x52\x6b\x09\xab\x84\x28\x4b\x8a", + .clen = 80, + } +}; + +#endif /* TEST_HISI_SEC_H_ */ diff --git a/uadk/test/hisi_zip_test/Makefile.am b/uadk/test/hisi_zip_test/Makefile.am new file mode 100644 index 0000000..0782ef7 --- /dev/null +++ b/uadk/test/hisi_zip_test/Makefile.am @@ -0,0 +1,23 @@ +AM_CFLAGS=-Wall -Werror -fno-strict-aliasing -I$(top_srcdir)/include +AUTOMAKE_OPTIONS = subdir-objects + +bin_PROGRAMS=zip_sva_perf + +zip_sva_perf_SOURCES=test_sva_perf.c test_lib.c testsuit.c + +if WD_STATIC_DRV +zip_sva_perf_LDADD=../../.libs/libwd.a ../../.libs/libwd_comp.a \ + ../../.libs/libhisi_zip.a -lpthread -lnuma $(libcrypto_LIBS) +else +zip_sva_perf_LDADD=-L../../.libs -l:libwd.so.2 -l:libwd_comp.so.2 \ + -lpthread -lnuma $(libcrypto_LIBS) +endif +zip_sva_perf_LDFLAGS=-Wl,-rpath,'/usr/local/lib' + +# For statistics +zip_sva_perf_LDADD+=-lm + +if HAVE_ZLIB +zip_sva_perf_LDADD+=-lz +zip_sva_perf_CPPFLAGS=-DUSE_ZLIB +endif diff --git a/uadk/test/hisi_zip_test/test_lib.c b/uadk/test/hisi_zip_test/test_lib.c new file mode 100644 index 0000000..5918699 --- /dev/null +++ b/uadk/test/hisi_zip_test/test_lib.c @@ -0,0 +1,1875 @@ +// SPDX-License-Identifier: Apache-2.0 +/* + * Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. + * Copyright 2020-2021 Linaro ltd. + */ + +#include +#include +#include +#include +#include + +#include "hisi_qm_udrv.h" +#include "test_lib.h" + +#define SCHED_RR_NAME "sched_rr" + +struct check_rand_ctx { + int off; + unsigned long global_off; + __u32 last; + unsigned short state[3]; +}; + +#define dbg(msg, ...) fprintf(stderr, msg, ##__VA_ARGS__) + +static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_spinlock_t lock; +static int count = 0; + +static struct wd_ctx_config *g_conf; + +int sum_pend = 0, sum_thread_end = 0; + +__attribute__((constructor)) +void lock_constructor(void) +{ + if (pthread_spin_init(&lock, PTHREAD_PROCESS_SHARED) != 0) + exit(1); +} + +__attribute__((destructor)) +void lock_destructor(void) +{ + if (pthread_spin_destroy(&lock) != 0) + exit(1); +} + +void *mmap_alloc(size_t len) +{ + void *p; + long page_size = sysconf(_SC_PAGESIZE); + + if (len % page_size) + return malloc(len); + + p = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, + -1, 0); + if (p == MAP_FAILED) + WD_ERR("Failed to allocate %zu bytes\n", len); + + return p == MAP_FAILED ? NULL : p; +} + +int mmap_free(void *addr, size_t len) +{ + long page_size = sysconf(_SC_PAGESIZE); + + if (len % page_size) { + free(addr); + return 0; + } + + return munmap(addr, len); +} + +static int hizip_check_rand(unsigned char *buf, unsigned int size, void *opaque) +{ + int i; + int *j; + __u32 n; + struct check_rand_ctx *rand_ctx = opaque; + + j = &rand_ctx->off; + for (i = 0; i < size; i += 4) { + if (*j) { + /* Something left from a previous run */ + n = rand_ctx->last; + } else { + n = nrand48(rand_ctx->state); + rand_ctx->last = n; + } + for (; *j < 4 && i + *j < size; (*j)++) { + char expected = (n >> (8 * *j)) & 0xff; + char actual = buf[i + *j]; + + if (expected != actual) { + WD_ERR("Invalid decompressed char at offset %lu: expected 0x%x != 0x%x\n", + rand_ctx->global_off + i + *j, expected, + actual); + return -EINVAL; + } + } + if (*j == 4) + *j = 0; + } + rand_ctx->global_off += size; + return 0; +} + +static struct wd_datalist *get_datalist(void *addr, __u32 size) +{ + int count = (int)ceil((double)size / SGE_SIZE); + struct wd_datalist *head, *cur, *tmp; + int i; + + head = calloc(1, sizeof(struct wd_datalist)); + if (!head) { + WD_ERR("failed to alloc datalist head\n"); + return NULL; + } + + cur = head; + + for (i = 0; i < count; i++) { + cur->data = addr; + cur->len = (size > SGE_SIZE) ? SGE_SIZE : size; + addr += SGE_SIZE; + size -= SGE_SIZE; + if (i != count - 1) { + tmp = calloc(1, sizeof(struct wd_datalist)); + cur->next = tmp; + cur = tmp; + } + } + + return head; +} + +/** + * compress() - compress memory buffer. + * @alg_type: alg_type. + * + * This function compress memory buffer. + */ +int hw_blk_compress(int alg_type, int blksize, __u8 data_fmt, void *priv, + unsigned char *dst, __u32 *dstlen, + unsigned char *src, __u32 srclen) +{ + handle_t h_sess; + struct wd_comp_sess_setup setup; + struct sched_params param = {0}; + struct wd_datalist *list; + struct wd_comp_req req; + int ret = 0; + + setup.alg_type = alg_type; + setup.op_type = WD_DIR_COMPRESS; + setup.comp_lv = WD_COMP_L8; + setup.win_sz = WD_COMP_WS_8K; + param.type = setup.op_type; + param.numa_id = 0; + setup.sched_param = ¶m; + h_sess = wd_comp_alloc_sess(&setup); + if (!h_sess) { + fprintf(stderr,"fail to alloc comp sess!\n"); + return -EINVAL; + } + + if (data_fmt) { + WD_ERR("now sge size is %u\n", SGE_SIZE); + list = get_datalist(src, (__u32)srclen); + req.list_src = list; + list = get_datalist(dst, (__u32)*dstlen); + req.list_dst = list; + } else { + req.src = src; + req.dst = dst; + } + + req.src_len = srclen; + req.dst_len = *dstlen; + req.op_type = WD_DIR_COMPRESS; + req.cb = NULL; + req.data_fmt = data_fmt; + req.priv = priv; + + dbg("%s:input req: src_len: %d, dst_len:%d, data_fmt:%d\n", + __func__, req.src_len, req.dst_len, req.data_fmt); + + ret = wd_do_comp_sync(h_sess, &req); + if (ret < 0) { + fprintf(stderr,"fail to do comp sync(ret = %d)!\n", ret); + return ret; + } + + if (req.status) { + fprintf(stderr,"fail to do comp sync(status = %d)!\n", + req.status); + wd_comp_free_sess(h_sess); + return req.status; + } + *dstlen = req.dst_len; + + dbg("%s:input req: src_len: %d, dst_len:%d, data_fmt:%d\n", + __func__, req.src_len, req.dst_len, req.data_fmt); + + wd_comp_free_sess(h_sess); + + return ret; +} + +int hw_blk_decompress(int alg_type, int blksize, __u8 data_fmt, + unsigned char *dst, __u32 *dstlen, + unsigned char *src, __u32 srclen) +{ + handle_t h_sess; + struct wd_comp_sess_setup setup; + struct sched_params param = {0}; + struct wd_datalist *list; + struct wd_comp_req req; + int ret = 0; + + setup.alg_type = alg_type; + setup.op_type = WD_DIR_DECOMPRESS; + param.type = setup.op_type; + param.numa_id = 0; + setup.sched_param = ¶m; + h_sess = wd_comp_alloc_sess(&setup); + if (!h_sess) { + fprintf(stderr,"fail to alloc comp sess!\n"); + return -EINVAL; + } + + if (data_fmt) { + WD_ERR("now sge size is %u\n", SGE_SIZE); + list = get_datalist(src, (__u32)srclen); + req.list_src = list; + list = get_datalist(dst, (__u32)*dstlen); + req.list_dst = list; + } else { + req.src = src; + req.dst = dst; + } + + req.src_len = srclen; + req.dst_len = *dstlen; + req.op_type = WD_DIR_DECOMPRESS; + req.cb = NULL; + req.data_fmt = data_fmt; + + dbg("%s:input req: src:%p, dst:%p,src_len: %d, dst_len:%d\n", + __func__, req.src, req.dst, req.src_len, req.dst_len); + + + ret = wd_do_comp_sync(h_sess, &req); + if (ret < 0) { + fprintf(stderr,"fail to do comp sync(ret = %d)!\n", ret); + return ret; + } + + if (req.status) { + fprintf(stderr,"fail to do comp sync(status = %d)!\n", + req.status); + wd_comp_free_sess(h_sess); + return req.status; + } + *dstlen = req.dst_len; + + dbg("%s:output req: src:%p, dst:%p,src_len: %d, dst_len:%d\n", + __func__, req.src, req.dst, req.src_len, req.dst_len); + + wd_comp_free_sess(h_sess); + + return ret; +} + +int hw_stream_compress(int alg_type, int blksize, __u8 data_fmt, + unsigned char *dst, __u32 *dstlen, + unsigned char *src, __u32 srclen) +{ + handle_t h_sess; + struct wd_comp_sess_setup setup; + struct sched_params param = {0}; + struct wd_comp_req req; + int ret = 0; + + setup.alg_type = alg_type; + setup.op_type = WD_DIR_COMPRESS; + setup.comp_lv = WD_COMP_L8; + setup.win_sz = WD_COMP_WS_8K; + param.type = setup.op_type; + param.numa_id = 0; + setup.sched_param = ¶m; + h_sess = wd_comp_alloc_sess(&setup); + if (!h_sess) { + fprintf(stderr,"fail to alloc comp sess!\n"); + return -EINVAL; + } + req.src = src; + req.src_len = srclen; + req.dst = dst; + req.dst_len = *dstlen; + req.op_type = WD_DIR_COMPRESS; + req.cb = NULL; + req.data_fmt = data_fmt; + + dbg("%s:input req: src:%p, dst:%p,src_len: %d, dst_len:%d\n", + __func__, req.src, req.dst, req.src_len, req.dst_len); + + ret = wd_do_comp_sync2(h_sess, &req); + if (ret < 0) { + fprintf(stderr,"fail to do comp sync(ret = %d)!\n", ret); + return ret; + } + + if (req.status) { + fprintf(stderr,"fail to do comp sync(status = %d)!\n", + req.status); + wd_comp_free_sess(h_sess); + return req.status; + } + *dstlen = req.dst_len; + + dbg("%s:output req: src:%p, dst:%p,src_len: %d, dst_len:%d\n", + __func__, req.src, req.dst, req.src_len, req.dst_len); + + wd_comp_free_sess(h_sess); + + return ret; +} + + +int hw_stream_decompress(int alg_type, int blksize, __u8 data_fmt, + unsigned char *dst, __u32 *dstlen, + unsigned char *src, __u32 srclen) +{ + handle_t h_sess; + struct wd_comp_sess_setup setup; + struct sched_params param = {0}; + struct wd_comp_req req; + int ret = 0; + + + setup.alg_type = alg_type; + setup.op_type = WD_DIR_DECOMPRESS; + param.type = setup.op_type; + param.numa_id = 0; + setup.sched_param = ¶m; + h_sess = wd_comp_alloc_sess(&setup); + if (!h_sess) { + fprintf(stderr,"fail to alloc comp sess!\n"); + return -EINVAL; + } + req.src = src; + req.src_len = srclen; + req.dst = dst; + req.dst_len = *dstlen; + req.op_type = WD_DIR_DECOMPRESS; + req.cb = NULL; + req.data_fmt = data_fmt; + + dbg("%s:input req: src:%p, dst:%p,src_len: %d, dst_len:%d\n", + __func__, req.src, req.dst, req.src_len, req.dst_len); + + + ret = wd_do_comp_sync2(h_sess, &req); + if (ret < 0) { + fprintf(stderr,"fail to do comp sync(ret = %d)!\n", ret); + return ret; + } + + if (req.status) { + fprintf(stderr,"fail to do comp sync(status = %d)!\n", + req.status); + wd_comp_free_sess(h_sess); + return req.status; + } + *dstlen = req.dst_len; + + dbg("%s:output req: src:%p, dst:%p,src_len: %d, dst_len:%d\n", + __func__, req.src, req.dst, req.src_len, req.dst_len); + + wd_comp_free_sess(h_sess); + + return ret; +} + +void hizip_prepare_random_input_data(char *buf, size_t len, size_t block_size) +{ + __u32 seed = 0; + unsigned short rand_state[3] = {(seed >> 16) & 0xffff, seed & 0xffff, 0x330e}; + + unsigned long remain_size; + __u32 size; + size_t i, j; + + /* + * TODO: change state for each buffer, to make sure there is no TLB + * aliasing. + */ + remain_size = len; + + while (remain_size > 0) { + if (remain_size > block_size) + size = block_size; + else + size = remain_size; + /* + * Prepare the input buffer with a reproducible sequence of + * numbers. nrand48() returns a pseudo-random number in the + * interval [0; 2^31). It's not really possible to compress a + * pseudo-random stream using deflate, since it can't find any + * string repetition. As a result the output size is bigger, + * with a ratio of 1.041. + */ + for (i = 0; i < size; i += 4) { + __u64 n = nrand48(rand_state); + + for (j = 0; j < 4 && i + j < size; j++) + buf[i + j] = (n >> (8 * j)) & 0xff; + } + + buf += size; + remain_size -= size; + } +} + +int hizip_prepare_random_compressed_data(char *buf, size_t out_len, size_t in_len, + size_t *produced, + struct test_options *opts) +{ + off_t off; + int ret = -EINVAL; + void *init_buf = mmap_alloc(in_len); + size_t in_block_size = opts->block_size; + size_t out_block_size = 2 * in_block_size; + + if (!init_buf) + return -ENOMEM; + + hizip_prepare_random_input_data(init_buf, in_len, opts->block_size); + + /* Compress each chunk separately since we're working in stateless mode */ + for (off = 0; off < in_len; off += in_block_size) { + ret = zlib_deflate(buf, out_block_size, init_buf + off, + in_block_size, produced, opts->alg_type); + if (ret) + break; + buf += out_block_size; + } + + munmap(init_buf, in_len); + return ret; +} + +int hizip_verify_random_output(struct test_options *opts, + struct hizip_test_info *info, + size_t out_sz) +{ + int ret; + int seed = 0; + off_t off = 0; + size_t checked = 0; + size_t total_checked = 0; + struct check_rand_ctx rand_ctx = { + .state = {(seed >> 16) & 0xffff, seed & 0xffff, 0x330e}, + }; + + if (!opts->verify) + return 0; + + if (opts->op_type == WD_DIR_DECOMPRESS) + /* Check plain output */ + return hizip_check_rand((void *)info->out_buf, out_sz, + &rand_ctx); + + do { + ret = hizip_check_output(info->out_buf + off, out_sz, + &checked, hizip_check_rand, &rand_ctx); + if (ret) { + WD_ERR("Check output failed with %d\n", ret); + return ret; + } + total_checked += checked; + off += opts->block_size * EXPANSION_RATIO; + } while (!ret && total_checked < opts->total_len); + + if (rand_ctx.global_off != opts->total_len) { + WD_ERR("Invalid output size %lu != %lu\n", + rand_ctx.global_off, opts->total_len); + return -EINVAL; + } + return 0; +} + +static void *async_cb(struct wd_comp_req *req, void *data) +{ + return NULL; +} + +void *send_thread_func(void *arg) +{ + thread_data_t *tdata = (thread_data_t *)arg; + struct hizip_test_info *info = tdata->info; + struct test_options *opts = info->opts; + size_t src_block_size, dst_block_size; + struct wd_comp_sess_setup setup; + struct sched_params param = {0}; + handle_t h_sess; + int j, ret; + size_t left; + + if (opts->op_type == WD_DIR_COMPRESS) { + src_block_size = opts->block_size; + dst_block_size = opts->block_size * EXPANSION_RATIO; + } else { + src_block_size = opts->block_size * EXPANSION_RATIO; + dst_block_size = opts->block_size; + } + + memset(&setup, 0, sizeof(struct wd_comp_sess_setup)); + setup.alg_type = opts->alg_type; + setup.op_type = opts->op_type; + setup.comp_lv = WD_COMP_L8; + setup.win_sz = WD_COMP_WS_8K; + param.type = setup.op_type; + param.numa_id = 0; + setup.sched_param = ¶m; + h_sess = wd_comp_alloc_sess(&setup); + if (!h_sess) + return NULL; + + for (j = 0; j < opts->compact_run_num; j++) { + if (opts->option & TEST_ZLIB) { + ret = zlib_deflate(info->out_buf, info->out_size, + info->in_buf, info->in_size, + &tdata->sum, opts->alg_type); + continue; + } + /* not TEST_ZLIB */ + left = opts->total_len; + tdata->req.op_type = opts->op_type; + tdata->req.src = info->in_buf; + tdata->req.dst = info->out_buf; + tdata->sum = 0; + while (left > 0) { + tdata->req.src_len = src_block_size; + tdata->req.dst_len = dst_block_size; + tdata->req.cb_param = &tdata->req; + if (opts->sync_mode) { + tdata->req.cb = async_cb; + count++; + ret = wd_do_comp_async(h_sess, &tdata->req); + } else { + tdata->req.cb = NULL; + ret = wd_do_comp_sync(h_sess, &tdata->req); + if (info->opts->faults & INJECT_SIG_WORK) + kill(getpid(), SIGTERM); + } + if (ret < 0) { + WD_ERR("do comp test fail with %d\n", ret); + return (void *)(uintptr_t)ret; + } else if (tdata->req.status) { + return (void *)(uintptr_t)tdata->req.status; + } + if (opts->op_type == WD_DIR_COMPRESS) + left -= src_block_size; + else + left -= dst_block_size; + tdata->req.src += src_block_size; + /* + * It's BLOCK (STATELESS) mode, so user needs to + * combine output buffer by himself. + */ + tdata->req.dst += dst_block_size; + tdata->sum += tdata->req.dst_len; + if (tdata->sum > info->out_size) { + fprintf(stderr, + "%s: exceed OUT limits (%ld > %ld)\n", + __func__, + tdata->sum, info->out_size); + break; + } + } + /* info->total_out are accessed by multiple threads */ + __atomic_add_fetch(&info->total_out, tdata->sum, + __ATOMIC_RELEASE); + } + wd_comp_free_sess(h_sess); + return NULL; +} + +int lib_poll_func(__u32 pos, __u32 expect, __u32 *count) +{ + int ret; + + ret = wd_comp_poll_ctx(pos, expect, count); + if (ret < 0) + return ret; + return 0; +} + +void *poll_thread_func(void *arg) +{ + struct hizip_test_info *info = (struct hizip_test_info *)arg; + int ret = 0, total = 0; + __u32 expected = 0, received; + + if (!info->opts->sync_mode) + return NULL; + while (1) { + if (info->opts->faults & INJECT_SIG_WORK) + kill(getpid(), SIGTERM); + + pthread_mutex_lock(&mutex); + if (!expected) + expected = 1; + if (count == 0) { + pthread_mutex_unlock(&mutex); + usleep(10); + continue; + } + expected = 1; + received = 0; + ret = wd_comp_poll(expected, &received); + if (ret == 0) + total += received; + if (count == total) { + pthread_mutex_unlock(&mutex); + break; + } else { + if (count > total) + expected = count - total; + pthread_mutex_unlock(&mutex); + usleep(10); + } + } + pthread_exit(NULL); +} + +int create_send_threads(struct test_options *opts, + struct hizip_test_info *info, + void *(*send_thread_func)(void *arg)) +{ + pthread_attr_t attr; + thread_data_t *tdatas; + int i, j, num, ret; + + num = opts->thread_num; + info->send_tds = calloc(1, sizeof(pthread_t) * num); + if (!info->send_tds) + return -ENOMEM; + info->send_tnum = num; + tdatas = calloc(1, sizeof(thread_data_t) * num); + if (!tdatas) { + ret = -ENOMEM; + goto out; + } + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + for (i = 0; i < num; i++) { + tdatas[i].info = info; + ret = pthread_create(&info->send_tds[i], &attr, + send_thread_func, &tdatas[i]); + if (ret < 0) { + fprintf(stderr, "Fail to create send thread %d (%d)\n", + i, ret); + goto out_thd; + } + } + pthread_attr_destroy(&attr); + g_conf = &info->ctx_conf; + return 0; +out_thd: + for (j = 0; j < i; j++) + pthread_cancel(info->send_tds[j]); + free(tdatas); +out: + free(info->send_tds); + return ret; +} + +int create_poll_threads(struct hizip_test_info *info, + void *(*poll_thread_func)(void *arg), + int num) +{ + struct test_options *opts = info->opts; + pthread_attr_t attr; + int i, ret; + + if (!opts->sync_mode) + return 0; + info->poll_tds = calloc(1, sizeof(pthread_t) * num); + if (!info->poll_tds) + return -ENOMEM; + info->poll_tnum = num; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + for (i = 0; i < num; i++) { + ret = pthread_create(&info->poll_tds[i], &attr, + poll_thread_func, info); + if (ret < 0) { + fprintf(stderr, "Fail to create send thread %d (%d)\n", + i, ret); + goto out; + } + } + pthread_attr_destroy(&attr); + count = 0; + return 0; +out: + free(info->poll_tds); + return ret; +} + +void free_threads(struct hizip_test_info *info) +{ + if (info->send_tds) + free(info->send_tds); + if (info->poll_tds) + free(info->poll_tds); +} + +int attach_threads(struct test_options *opts, struct hizip_test_info *info) +{ + int i, ret; + void *tret; + + if (opts->sync_mode) { + for (i = 0; i < info->poll_tnum; i++) { + ret = pthread_join(info->poll_tds[i], NULL); + if (ret < 0) + fprintf(stderr, "Fail on poll thread with %d\n", + ret); + } + } + for (i = 0; i < info->send_tnum; i++) { + ret = pthread_join(info->send_tds[i], &tret); + if (ret < 0) + fprintf(stderr, "Fail on send thread with %d\n", ret); + } + return (int)(uintptr_t)tret; +} + +void gen_random_data(void *buf, size_t len) +{ + int i; + uint32_t seed = 0; + unsigned short rand_state[3] = {(seed >> 16) & 0xffff, + seed & 0xffff, + 0x330e}; + + for (i = 0; i < len >> 3; i++) + *((uint64_t *)buf + i) = nrand48(rand_state); +} + +int calculate_md5(comp_md5_t *md5, const void *buf, size_t len) +{ + if (!md5 || !buf || !len) + return -EINVAL; + MD5_Init(&md5->md5_ctx); + MD5_Update(&md5->md5_ctx, buf, len); + MD5_Final(md5->md, &md5->md5_ctx); + return 0; +} + +void dump_md5(comp_md5_t *md5) +{ + int i; + + for (i = 0; i < MD5_DIGEST_LENGTH - 1; i++) + printf("%02x-", md5->md[i]); + printf("%02x\n", md5->md[i]); +} + +int cmp_md5(comp_md5_t *orig, comp_md5_t *final) +{ + int i; + + if (!orig || !final) + return -EINVAL; + for (i = 0; i < MD5_DIGEST_LENGTH; i++) { + if (orig->md[i] != final->md[i]) { + printf("Original MD5: "); + dump_md5(orig); + printf("Final MD5: "); + dump_md5(final); + return -EINVAL; + } + } + return 0; +} + +static void *async2_cb(struct wd_comp_req *req, void *data) +{ + sem_t *sem = (sem_t *)data; + + if (sem) + sem_post(sem); + return NULL; +} + +/* used in BATCH mode */ +static void *async5_cb(struct wd_comp_req *req, void *data) +{ + thread_data_t *tdata = (thread_data_t *)data; + + pthread_spin_lock(&lock); + tdata->pcnt++; + if (tdata->batch_flag && (tdata->pcnt == tdata->bcnt)) { + tdata->pcnt = 0; + tdata->bcnt = 0; + tdata->batch_flag = 0; + pthread_spin_unlock(&lock); + sem_post(&tdata->sem); + } else + pthread_spin_unlock(&lock); + return NULL; +} + +void init_chunk_list(chunk_list_t *list, void *buf, size_t buf_sz, + size_t chunk_sz) +{ + chunk_list_t *p = NULL; + int i, count; + size_t sum; + + count = (buf_sz + chunk_sz - 1) / chunk_sz; + for (i = 0, sum = 0, p = list; i < count && sum <= buf_sz; i++, p++) { + p->addr = buf + sum; + p->size = MIN(buf_sz - sum, chunk_sz); + if (i == count - 1) + p->next = NULL; + else + p->next = p + 1; + sum += p->size; + } +} + +chunk_list_t *create_chunk_list(void *buf, size_t buf_sz, size_t chunk_sz) +{ + chunk_list_t *list; + int count; + + count = (buf_sz + chunk_sz - 1) / chunk_sz; + if (count > HIZIP_CHUNK_LIST_ENTRIES) + count = HIZIP_CHUNK_LIST_ENTRIES; + if (buf_sz / chunk_sz > count) + return NULL; + /* allocate entries with additional one */ + list = malloc(sizeof(chunk_list_t) * (count + 1)); + if (!list) + return NULL; + init_chunk_list(list, buf, buf_sz, chunk_sz); + return list; +} + +void free_chunk_list(chunk_list_t *list) +{ + free(list); +} + +/* + * Deflate a data block with compressed header. + */ +static int chunk_deflate2(void *in, size_t in_sz, void *out, size_t *out_sz, + struct test_options *opts) +{ + int alg_type = opts->alg_type; + z_stream strm; + int windowBits; + int ret; + + switch (alg_type) { + case WD_ZLIB: + windowBits = 15; + break; + case WD_DEFLATE: + windowBits = -15; + break; + case WD_GZIP: + windowBits = 15 + 16; + break; + default: + printf("algorithm %d unsupported by zlib\n", alg_type); + return -EINVAL; + } + memset(&strm, 0, sizeof(z_stream)); + strm.next_in = in; + strm.avail_in = in_sz; + strm.next_out = out; + strm.avail_out = *out_sz; + + ret = deflateInit2(&strm, Z_BEST_SPEED, Z_DEFLATED, windowBits, + 8, Z_DEFAULT_STRATEGY); + if (ret != Z_OK) { + printf("deflateInit2: %d\n", ret); + return -EINVAL; + } + + do { + ret = deflate(&strm, Z_FINISH); + if ((ret == Z_STREAM_ERROR) || (ret == Z_BUF_ERROR)) { + printf("defalte error %d - %s\n", ret, strm.msg); + ret = -ENOSR; + break; + } else if (!strm.avail_in) { + if (ret != Z_STREAM_END) + printf("deflate unexpected return: %d\n", ret); + ret = 0; + break; + } else if (!strm.avail_out) { + printf("deflate out of memory\n"); + ret = -ENOSPC; + break; + } + } while (ret == Z_OK); + + deflateEnd(&strm); + *out_sz = *out_sz - strm.avail_out; + return ret; +} + + +/* + * This function is used in BLOCK mode. Each compressing in BLOCK mode + * produces compression header. + */ +static int chunk_inflate2(void *in, size_t in_sz, void *out, size_t *out_sz, + struct test_options *opts) +{ + z_stream strm; + int ret; + + memset(&strm, 0, sizeof(z_stream)); + /* Window size of 15, +32 for auto-decoding gzip/zlib */ + ret = inflateInit2(&strm, 15 + 32); + if (ret != Z_OK) { + printf("zlib inflateInit: %d\n", ret); + return -EINVAL; + } + + strm.next_in = in; + strm.avail_in = in_sz; + strm.next_out = out; + strm.avail_out = *out_sz; + do { + ret = inflate(&strm, Z_NO_FLUSH); + if ((ret < 0) || (ret == Z_NEED_DICT)) { + printf("zlib error %d - %s\n", ret, strm.msg); + goto out; + } + if (!strm.avail_out) { + if (!strm.avail_in || (ret == Z_STREAM_END)) + break; + printf("%s: avail_out is empty!\n", __func__); + goto out; + } + } while (strm.avail_in && (ret != Z_STREAM_END)); + inflateEnd(&strm); + *out_sz = *out_sz - strm.avail_out; + return 0; +out: + inflateEnd(&strm); + ret = -EINVAL; + return ret; +} + +/* + * Compress a list of chunk data and produce a list of chunk data by software. + * in_list & out_list should be formated first. + */ +int sw_deflate2(chunk_list_t *in_list, + chunk_list_t *out_list, + struct test_options *opts) +{ + chunk_list_t *p, *q; + int ret = -EINVAL; + + for (p = in_list, q = out_list; p && q; p = p->next, q = q->next) { + ret = chunk_deflate2(p->addr, p->size, q->addr, &q->size, + opts); + if (ret) + return ret; + } + return ret; +} + +/* + * Compress a list of chunk data and produce a list of chunk data by software. + * in_list & out_list should be formated first. + */ +int sw_inflate2(chunk_list_t *in_list, chunk_list_t *out_list, + struct test_options *opts) +{ + chunk_list_t *p, *q; + int ret = -EINVAL; + + for (p = in_list, q = out_list; p && q; p = p->next, q = q->next) { + ret = chunk_inflate2(p->addr, p->size, q->addr, &q->size, + opts); + if (ret) + return ret; + } + return ret; +} + +int hw_deflate4(handle_t h_dfl, + chunk_list_t *in_list, + chunk_list_t *out_list, + struct test_options *opts, + sem_t *sem) +{ + struct wd_comp_req *reqs; + chunk_list_t *p = in_list, *q = out_list; + int i, ret; + + if (!in_list || !out_list || !opts || !sem) + return -EINVAL; + /* reqs array could make async operations in parallel */ + reqs = malloc(sizeof(struct wd_comp_req) * HIZIP_CHUNK_LIST_ENTRIES); + if (!reqs) + return -ENOMEM; + + for (i = 0; p && q; p = p->next, q = q->next, i++) { + reqs[i].src = p->addr; + reqs[i].src_len = p->size; + reqs[i].dst = q->addr; + reqs[i].dst_len = q->size; + reqs[i].op_type = WD_DIR_COMPRESS; + + if (opts->sync_mode) { + reqs[i].cb = async2_cb; + reqs[i].cb_param = sem; + } + do { + if (opts->sync_mode) { + ret = wd_do_comp_async(h_dfl, &reqs[i]); + if (!ret) { + __atomic_add_fetch(&sum_pend, 1, + __ATOMIC_ACQ_REL); + sem_wait(sem); + } + } else + ret = wd_do_comp_sync(h_dfl, &reqs[i]); + } while (ret == -WD_EBUSY); + if (ret) + goto out; + q->size = reqs[i].dst_len; + /* make sure olist has the same length with ilist */ + if (!p->next) + q->next = NULL; + i++; + } + free(reqs); + return 0; +out: + free(reqs); + return ret; +} + +int hw_inflate4(handle_t h_ifl, + chunk_list_t *in_list, + chunk_list_t *out_list, + struct test_options *opts, + sem_t *sem) +{ + struct wd_comp_req *reqs; + chunk_list_t *p, *q; + int i = 0, ret; + + /* reqs array could make async operations in parallel */ + reqs = calloc(1, sizeof(struct wd_comp_req) * HIZIP_CHUNK_LIST_ENTRIES); + if (!reqs) + return -ENOMEM; + for (p = in_list, q = out_list; p && q; p = p->next, q = q->next) { + reqs[i].src = p->addr; + reqs[i].src_len = p->size; + reqs[i].dst = q->addr; + reqs[i].dst_len = q->size; + reqs[i].op_type = WD_DIR_DECOMPRESS; + if (opts->sync_mode) { + reqs[i].cb = async2_cb; + reqs[i].cb_param = sem; + } + do { + if (opts->sync_mode) { + ret = wd_do_comp_async(h_ifl, &reqs[i]); + if (!ret) { + __atomic_add_fetch(&sum_pend, 1, + __ATOMIC_ACQ_REL); + sem_wait(sem); + } + } else + ret = wd_do_comp_sync(h_ifl, &reqs[i]); + } while (ret == -WD_EBUSY); + if (ret) + goto out; + q->size = reqs[i].dst_len; + /* make sure olist has the same length with ilist */ + if (!p->next) + q->next = NULL; + i++; + } + free(reqs); + return 0; +out: + free(reqs); + return ret; +} + +/* used in BATCH mode */ +int hw_deflate5(handle_t h_dfl, + chunk_list_t *in_list, + chunk_list_t *out_list, + thread_data_t *tdata) +{ + struct hizip_test_info *info = tdata->info; + struct test_options *opts = info->opts; + struct wd_comp_req *reqs = tdata->reqs; + chunk_list_t *p = in_list, *q = out_list; + int i = 0, ret = 0; + + if (!in_list || !out_list || !opts) + return -EINVAL; + for (p = in_list, q = out_list; p && q; p = p->next, q = q->next) { + reqs[i].src = p->addr; + reqs[i].src_len = p->size; + reqs[i].dst = q->addr; + reqs[i].dst_len = q->size; + reqs[i].op_type = WD_DIR_COMPRESS; + reqs[i].data_fmt = opts->data_fmt; + if (opts->sync_mode) { + reqs[i].cb = async5_cb; + reqs[i].cb_param = tdata; + } else { + reqs[i].cb = NULL; + reqs[i].cb_param = NULL; + } + if (opts->sync_mode) { + do { + ret = wd_do_comp_async(h_dfl, &reqs[i]); + } while (ret == -WD_EBUSY); + if (ret < 0) + goto out; + __atomic_add_fetch(&sum_pend, 1, __ATOMIC_ACQ_REL); + pthread_spin_lock(&lock); + tdata->bcnt++; + if (((i + 1) == opts->batch_num) || !p->next) { + tdata->batch_flag = 1; + pthread_spin_unlock(&lock); + sem_wait(&tdata->sem); + } else + pthread_spin_unlock(&lock); + } else { + do { + ret = wd_do_comp_sync(h_dfl, &reqs[i]); + } while (ret == -WD_EBUSY); + if (ret) + goto out; + } + q->size = reqs[i].dst_len; + i = (i + 1) % opts->batch_num; + /* make sure olist has the same length with ilist */ + if (!p->next) + q->next = NULL; + } + return 0; +out: + return ret; +} + +/* used in BATCH mode */ +int hw_inflate5(handle_t h_ifl, + chunk_list_t *in_list, + chunk_list_t *out_list, + thread_data_t *tdata) +{ + struct hizip_test_info *info = tdata->info; + struct test_options *opts = info->opts; + struct wd_comp_req *reqs = tdata->reqs; + chunk_list_t *p = in_list, *q = out_list; + int ret = 0, i = 0; + + if (!in_list || !out_list || !opts) + return -EINVAL; + for (p = in_list, q = out_list; p && q; p = p->next, q = q->next) { + reqs[i].src = p->addr; + reqs[i].src_len = p->size; + reqs[i].dst = q->addr; + reqs[i].dst_len = q->size; + reqs[i].op_type = WD_DIR_DECOMPRESS; + reqs[i].data_fmt = opts->data_fmt; + if (opts->sync_mode) { + reqs[i].cb = async5_cb; + reqs[i].cb_param = tdata; + } else { + reqs[i].cb = NULL; + reqs[i].cb_param = NULL; + } + if (opts->sync_mode) { + do { + ret = wd_do_comp_async(h_ifl, &reqs[i]); + } while (ret == -WD_EBUSY); + if (ret < 0) + goto out; + __atomic_add_fetch(&sum_pend, 1, __ATOMIC_ACQ_REL); + pthread_spin_lock(&lock); + tdata->bcnt++; + if (((i + 1) == opts->batch_num) || !p->next) { + tdata->batch_flag = 1; + pthread_spin_unlock(&lock); + sem_wait(&tdata->sem); + } else + pthread_spin_unlock(&lock); + } else { + do { + ret = wd_do_comp_sync(h_ifl, &reqs[i]); + } while (ret == -WD_EBUSY); + if (ret) + goto out; + } + q->size = reqs[i].dst_len; + i = (i + 1) % opts->batch_num; + /* make sure olist has the same length with ilist */ + if (!p->next) + q->next = NULL; + } + return 0; +out: + return ret; +} + +/* + * info->in_buf & info->out_buf should be allocated first. + * Thread 0 shares info->out_buf. Other threads need to create its own + * dst buffer. + */ +int create_send_tdata(struct test_options *opts, + struct hizip_test_info *info) +{ + thread_data_t *tdata; + chunk_list_t *in_list, *out_list; + int i, j, num, ret; + + if (!opts || !info || !info->in_chunk_sz || !info->out_chunk_sz) + return -EINVAL; + num = opts->thread_num; + info->send_tds = calloc(1, sizeof(pthread_t) * num); + if (!info->send_tds) + return -ENOMEM; + info->send_tnum = num; + info->tdatas = calloc(1, sizeof(thread_data_t) * num); + if (!info->tdatas) { + ret = -ENOMEM; + goto out; + } + if (!opts->batch_num) + opts->batch_num = 1; + else if (opts->batch_num > HIZIP_CHUNK_LIST_ENTRIES) + opts->batch_num = HIZIP_CHUNK_LIST_ENTRIES; + if (opts->is_stream) { + in_list = create_chunk_list(info->in_buf, info->in_size, + info->in_size); + } else { + in_list = create_chunk_list(info->in_buf, info->in_size, + info->in_chunk_sz); + } + if (!in_list) { + ret = -EINVAL; + goto out_in; + } + if (opts->option & TEST_THP) { + ret = madvise(info->in_buf, info->in_size, MADV_HUGEPAGE); + if (ret) { + printf("madvise(MADV_HUGEPAGE)"); + goto out_in; + } + } + for (i = 0; i < num; i++) { + tdata = &info->tdatas[i]; + /* src address is shared among threads */ + tdata->tid = i; + tdata->src_sz = info->in_size; + tdata->src = info->in_buf; + tdata->in_list = in_list; + tdata->dst_sz = info->out_size; + tdata->dst = mmap_alloc(tdata->dst_sz); + if (!tdata->dst) { + ret = -ENOMEM; + goto out_dst; + } + if (opts->option & TEST_THP) { + ret = madvise(tdata->dst, tdata->dst_sz, MADV_HUGEPAGE); + if (ret) { + printf("madvise(MADV_HUGEPAGE)"); + goto out_dst; + } + } + /* + * Without memset, valgrind reports uninitialized buf + * for writing to file. + */ + memset(tdata->dst, 0, tdata->dst_sz); + if (opts->is_stream) { + out_list = create_chunk_list(tdata->dst, + tdata->dst_sz, + tdata->dst_sz); + } else { + out_list = create_chunk_list(tdata->dst, + tdata->dst_sz, + info->out_chunk_sz); + } + tdata->out_list = out_list; + if (!tdata->out_list) { + ret = -EINVAL; + goto out_list; + } + calculate_md5(&tdata->md5, tdata->src, tdata->src_sz); + tdata->reqs = malloc(sizeof(struct wd_comp_req) * + opts->batch_num); + if (!tdata->reqs) + goto out_list; + sem_init(&tdata->sem, 0, 0); + tdata->info = info; + } + return 0; +out_list: + mmap_free(tdata->dst, tdata->dst_sz); +out_dst: + for (j = 0; j < i; j++) { + pthread_cancel(info->send_tds[j]); + free_chunk_list(info->tdatas[j].out_list); + mmap_free(info->tdatas[j].dst, info->tdatas[j].dst_sz); + } + free_chunk_list(in_list); +out_in: + free(info->tdatas); +out: + free(info->send_tds); + return ret; +} + +int create_poll_tdata(struct test_options *opts, + struct hizip_test_info *info, + int poll_num) +{ + thread_data_t *tdatas; + int i, ret; + + if (opts->sync_mode == 0) + return 0; + else if (poll_num <= 0) + return -EINVAL; + info->poll_tnum = poll_num; + info->poll_tds = calloc(1, sizeof(pthread_t) * poll_num); + if (!info->poll_tds) + return -ENOMEM; + info->p_tdatas = calloc(1, sizeof(thread_data_t) * poll_num); + if (!info->p_tdatas) { + ret = -ENOMEM; + goto out; + } + tdatas = info->p_tdatas; + for (i = 0; i < poll_num; i++) { + tdatas[i].tid = i; + tdatas[i].info = info; + } + return 0; +out: + free(info->poll_tds); + return ret; +} + +/* + * Free source and destination buffer contained in sending threads. + * Free sending threads and polling threads. + */ +void free2_threads(struct hizip_test_info *info) +{ + thread_data_t *tdatas = info->tdatas; + int i; + + if (info->send_tds) + free(info->send_tds); + if (info->poll_tds) { + free(info->poll_tds); + free(info->p_tdatas); + } + free_chunk_list(tdatas[0].in_list); + for (i = 0; i < info->send_tnum; i++) { + free_chunk_list(tdatas[i].out_list); + free(tdatas[i].reqs); + } + /* info->out_buf is bound to tdatas[0].dst */ + for (i = 0; i < info->send_tnum; i++) + mmap_free(tdatas[i].dst, tdatas[i].dst_sz); + free(info->tdatas); + mmap_free(info->in_buf, info->in_size); +} + +int attach2_threads(struct test_options *opts, + struct hizip_test_info *info, + void *(*send_thread_func)(void *arg), + void *(*poll_thread_func)(void *arg)) +{ + int i, j, ret, num; + void *tret; + pthread_attr_t attr; + + num = opts->thread_num; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + for (i = 0; i < num; i++) { + ret = pthread_create(&info->send_tds[i], &attr, + send_thread_func, &info->tdatas[i]); + if (ret < 0) { + printf("Fail to create send thread %d (%d)\n", i, ret); + goto out; + } + } + if (opts->sync_mode && !opts->use_env) { + for (i = 0; i < opts->poll_num; i++) { + ret = pthread_create(&info->poll_tds[i], &attr, + poll_thread_func, + &info->tdatas[i]); + if (ret < 0) { + printf("Fail to create poll thread %d (%d)\n", + i, ret); + goto out_poll; + } + } + for (i = 0; i < info->poll_tnum; i++) { + ret = pthread_join(info->poll_tds[i], &tret); + if (ret < 0) { + fprintf(stderr, "Fail on poll thread with %d\n", + ret); + goto out_poll; + } + } + } + for (i = 0; i < info->send_tnum; i++) { + ret = pthread_join(info->send_tds[i], &tret); + if (ret < 0) { + fprintf(stderr, "Fail on send thread with %d\n", ret); + goto out_poll; + } + } + pthread_attr_destroy(&attr); + return (int)(uintptr_t)tret; +out_poll: + for (j = 0; j < i; j++) + pthread_cancel(info->poll_tds[j]); + i = opts->thread_num; +out: + for (j = 0; j < i; j++) + pthread_cancel(info->send_tds[j]); + pthread_attr_destroy(&attr); + return ret; +} + +void *poll2_thread_func(void *arg) +{ + thread_data_t *tdata = (thread_data_t *)arg; + struct hizip_test_info *info = tdata->info; + __u32 received; + int ret = 0; + struct timeval start_tvl, end_tvl; + int pending; + int end_threads; + + gettimeofday(&start_tvl, NULL); + while (1) { + end_threads = __atomic_load_n(&sum_thread_end, + __ATOMIC_ACQUIRE); + pending = __atomic_load_n(&sum_pend, __ATOMIC_ACQUIRE); + if ((end_threads == info->send_tnum) && (pending == 0)) + break; + else if (pending == 0) + continue; + received = 0; + ret = wd_comp_poll(pending, &received); + if (ret == 0) { + __atomic_sub_fetch(&sum_pend, + received, + __ATOMIC_ACQ_REL); + } + } + gettimeofday(&end_tvl, NULL); + timersub(&end_tvl, &start_tvl, &start_tvl); + pthread_exit(NULL); +} + +/* + * Choose a device and check whether it can afford the requested contexts. + * Return a list whose the first device is chosen. + */ +struct uacce_dev_list *get_dev_list(struct test_options *opts, + int children) +{ + struct uacce_dev_list *list, *p, *head = NULL, *prev = NULL; + int max_q_num; + + list = wd_get_accel_list("zlib"); + if (!list) + return NULL; + + p = list; + /* Find one device matching the requested contexts. */ + while (p) { + max_q_num = wd_get_avail_ctx(p->dev); + /* + * Check whether there's enough contexts. + * There may be multiple taskes running together. + * The number of multiple taskes is specified in children. + */ + if (max_q_num < 4 * opts->q_num * children) { + if (!head) + head = p; + prev = p; + p = p->next; + } else + break; + } + + if (!p) { + WD_ERR("Request too much contexts: %d\n", + opts->q_num * 4 * children); + goto out; + } + + /* Adjust p to the head of list if p is in the middle. */ + if (p && (p != list)) { + prev->next = p->next; + p->next = head; + return p; + } + return list; +out: + wd_free_list_accels(list); + return NULL; +} + +/* + * Initialize context numbers by the four times of opts->q_num. + * [sync, async] * [compress, decompress] = 4 + */ +int init_ctx_config(struct test_options *opts, void *priv, + struct wd_sched **sched) +{ + struct hizip_test_info *info = priv; + struct wd_ctx_config *ctx_conf = &info->ctx_conf; + struct sched_params param; + int i, j, ret = -EINVAL; + int q_num = opts->q_num; + + + __atomic_store_n(&sum_pend, 0, __ATOMIC_RELEASE); + __atomic_store_n(&sum_thread_end, 0, __ATOMIC_RELEASE); + *sched = wd_sched_rr_alloc(SCHED_POLICY_RR, 2, 2, lib_poll_func); + if (!*sched) { + WD_ERR("wd_sched_rr_alloc fail\n"); + goto out_sched; + } + + (*sched)->name = SCHED_RR_NAME; + + memset(ctx_conf, 0, sizeof(struct wd_ctx_config)); + ctx_conf->ctx_num = q_num * 4; + ctx_conf->ctxs = calloc(1, q_num * 4 * sizeof(struct wd_ctx)); + if (!ctx_conf->ctxs) { + WD_ERR("Not enough memory to allocate contexts.\n"); + ret = -ENOMEM; + goto out_ctx; + } + for (i = 0; i < ctx_conf->ctx_num; i++) { + ctx_conf->ctxs[i].ctx = wd_request_ctx(info->list->dev); + if (!ctx_conf->ctxs[i].ctx) { + WD_ERR("Fail to allocate context #%d\n", i); + ret = -EINVAL; + goto out_req; + } + } + /* + * All contexts for 2 modes & 2 types. + * The test only uses one kind of contexts at the same time. + */ + for (i = 0; i < q_num; i++) { + ctx_conf->ctxs[i].ctx_mode = 0; + ctx_conf->ctxs[i].op_type = 0; + } + param.numa_id = 0; + param.mode = 0; + param.type = 0; + param.begin = 0; + param.end = q_num - 1; + ret = wd_sched_rr_instance((const struct wd_sched *)*sched, ¶m); + if (ret < 0) { + WD_ERR("Fail to fill sched region.\n"); + goto out_fill; + } + for (i = q_num; i < q_num * 2; i++) { + ctx_conf->ctxs[i].ctx_mode = 0; + ctx_conf->ctxs[i].op_type = 1; + } + param.mode = 0; + param.type = 1; + param.begin = q_num; + param.end = q_num * 2 - 1; + ret = wd_sched_rr_instance((const struct wd_sched *)*sched, ¶m); + if (ret < 0) { + WD_ERR("Fail to fill sched region.\n"); + goto out_fill; + } + for (i = q_num * 2; i < q_num * 3; i++) { + ctx_conf->ctxs[i].ctx_mode = 1; + ctx_conf->ctxs[i].op_type = 0; + } + param.mode = 1; + param.type = 0; + param.begin = q_num * 2; + param.end = q_num * 3 - 1; + ret = wd_sched_rr_instance((const struct wd_sched *)*sched, ¶m); + if (ret < 0) { + WD_ERR("Fail to fill sched region.\n"); + goto out_fill; + } + for (i = q_num * 3; i < q_num * 4; i++) { + ctx_conf->ctxs[i].ctx_mode = 1; + ctx_conf->ctxs[i].op_type = 1; + } + param.mode = 1; + param.type = 1; + param.begin = q_num * 3; + param.end = q_num * 4 - 1; + ret = wd_sched_rr_instance((const struct wd_sched *)*sched, ¶m); + if (ret < 0) { + WD_ERR("Fail to fill sched region.\n"); + goto out_fill; + } + + ret = wd_comp_init(ctx_conf, *sched); + if (ret) + goto out_fill; + return ret; + +out_fill: + for (i = 0; i < ctx_conf->ctx_num; j++) + wd_release_ctx(ctx_conf->ctxs[i].ctx); +out_req: + free(ctx_conf->ctxs); +out_ctx: + wd_sched_rr_release(*sched); +out_sched: + return ret; +} + +void uninit_config(void *priv, struct wd_sched *sched) +{ + struct hizip_test_info *info = priv; + struct wd_ctx_config *ctx_conf = &info->ctx_conf; + int i; + + wd_comp_uninit(); + for (i = 0; i < ctx_conf->ctx_num; i++) + wd_release_ctx(ctx_conf->ctxs[i].ctx); + free(ctx_conf->ctxs); + wd_sched_rr_release(sched); +} + + +int parse_common_option(const char opt, const char *optarg, + struct test_options *opts) +{ + switch (opt) { + case 'b': + opts->block_size = strtol(optarg, NULL, 0); + if (opts->block_size <= 0) + return 1; + break; + case 'l': + opts->compact_run_num = strtol(optarg, NULL, 0); + if (opts->compact_run_num <= 0) + return 1; + break; + case 'n': + opts->run_num = strtol(optarg, NULL, 0); + SYS_ERR_COND(opts->run_num > MAX_RUNS, + "No more than %d runs supported\n", MAX_RUNS); + if (opts->run_num <= 0) + return 1; + break; + case 'q': + opts->q_num = strtol(optarg, NULL, 0); + if (opts->q_num <= 0) + return 1; + break; + case 'd': + opts->op_type = WD_DIR_DECOMPRESS; + break; + case 'F': + opts->is_file = true; + break; + case 'S': + opts->is_stream = MODE_STREAM; + break; + case 's': + opts->total_len = strtol(optarg, NULL, 0); + SYS_ERR_COND(opts->total_len <= 0, "invalid size '%s'\n", + optarg); + break; + case 't': + opts->thread_num = strtol(optarg, NULL, 0); + SYS_ERR_COND(opts->thread_num < 0, "invalid thread num '%s'\n", + optarg); + break; + case 'm': + opts->sync_mode = strtol(optarg, NULL, 0); + SYS_ERR_COND(opts->sync_mode < 0 || opts->sync_mode > 1, + "invalid sync mode '%s'\n", optarg); + break; + case 'V': + opts->verify = true; + break; + case 'v': + opts->verbose = true; + break; + case 'a': + opts->alg_type = WD_DEFLATE; + break; + case 'z': + opts->alg_type = WD_ZLIB; + break; + case 'L': + opts->data_fmt = WD_SGL_BUF; + break; + case 'Z': + opts->alg_type = WD_LZ77_ZSTD; + break; + default: + return 1; + } + + return 0; +} + +#ifdef HAVE_ZLIB + +#include + +/* + * Try to decompress a buffer using zLib's inflate(). Call compare_output with + * the decompressed stream as argument + * + * Return 0 on success, or an error. + */ +int hizip_check_output(void *buf, size_t size, size_t *checked, + check_output_fn compare_output, void *opaque) +{ + int ret, ret2; + unsigned char *out_buffer; + const size_t out_buf_size = 0x100000; + z_stream stream = { + .next_in = buf, + .avail_in = size, + }; + + out_buffer = calloc(1, out_buf_size); + if (!out_buffer) + return -ENOMEM; + + stream.next_out = out_buffer; + stream.avail_out = out_buf_size; + + /* Window size of 15, +32 for auto-decoding gzip/zlib */ + ret = inflateInit2(&stream, 15 + 32); + if (ret != Z_OK) { + WD_ERR("zlib inflateInit: %d\n", ret); + ret = -EINVAL; + goto out_free_buf; + } + + do { + ret = inflate(&stream, Z_NO_FLUSH); + if (ret < 0 || ret == Z_NEED_DICT) { + WD_ERR("zlib error %d - %s\n", ret, stream.msg); + ret = -ENOSR; + break; + } + + ret2 = compare_output(out_buffer, out_buf_size - + stream.avail_out, opaque); + /* compare_output should print diagnostic messages. */ + if (ret2) { + ret = Z_STREAM_ERROR; + break; + } + + if (!stream.avail_out) { + stream.next_out = out_buffer; + stream.avail_out = out_buf_size; + } + } while (ret != Z_STREAM_END); + + if (ret == Z_STREAM_END || ret == Z_OK) { + *checked = stream.total_out; + ret = 0; + } + + inflateEnd(&stream); +out_free_buf: + free(out_buffer); + return ret; +} + +int zlib_deflate(void *output, unsigned int out_size, + void *input, unsigned int in_size, + unsigned long *produced, int alg_type) +{ + int ret; + int windowBits; + z_stream stream = { + .next_in = input, + .avail_in = in_size, + .next_out = output, + .avail_out = out_size, + }; + + switch (alg_type) { + case WD_ZLIB: + windowBits = 15; + break; + case WD_DEFLATE: + windowBits = -15; + break; + case WD_GZIP: + windowBits = 15 + 16; + break; + default: + WD_ERR("algorithm %d unsupported by zlib\n", alg_type); + return -EINVAL; + } + + ret = deflateInit2(&stream, Z_BEST_SPEED, Z_DEFLATED, windowBits, 9, + Z_DEFAULT_STRATEGY); + if (ret != Z_OK) { + WD_ERR("zlib deflateInit: %d\n", ret); + return -EINVAL; + } + + do { + ret = deflate(&stream, Z_FINISH); + if (ret == Z_STREAM_ERROR || ret == Z_BUF_ERROR) { + WD_ERR("zlib error %d - %s\n", ret, stream.msg); + ret = -ENOSR; + break; + } else if (!stream.avail_in) { + if (ret != Z_STREAM_END) + WD_ERR("unexpected deflate return value %d\n", ret); + *produced = stream.total_out; + ret = 0; + break; + } else if (!stream.avail_out) { + WD_ERR("No more output available\n"); + ret = -ENOSPC; + break; + } + } while (ret == Z_OK); + + deflateEnd(&stream); + + return ret; +} +#endif diff --git a/uadk/test/hisi_zip_test/test_lib.h b/uadk/test/hisi_zip_test/test_lib.h new file mode 100644 index 0000000..4820817 --- /dev/null +++ b/uadk/test/hisi_zip_test/test_lib.h @@ -0,0 +1,351 @@ +// SPDX-License-Identifier: Apache-2.0 +/* + * Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. + * Copyright 2020-2021 Linaro ltd. + */ + +#ifndef TEST_LIB_H_ +#define TEST_LIB_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "wd_comp.h" +#include "wd_sched.h" + +#define SYS_ERR_COND(cond, msg, ...) \ +do { \ + if (cond) { \ + if (errno) \ + perror(msg); \ + else \ + fprintf(stderr, msg, ##__VA_ARGS__); \ + exit(EXIT_FAILURE); \ + } \ +} while (0) + +enum mode { + MODE_BLOCK, + MODE_STREAM, +}; + +#define __ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask)) +#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1) +#define MIN(a, b) ((a < b) ? a : b) + +/* + * I observed a worst case of 1.041x expansion with random data, but let's say 2 + * just in case. TODO: reduce this + */ +#define EXPANSION_RATIO 2 +/* The INFLATION_RATIO is high for text file. */ +#define INFLATION_RATIO 24 + +#define SGE_SIZE (8 * 1024) + +#define HIZIP_CHUNK_LIST_ENTRIES 32768 + +struct test_options { + int alg_type; + int op_type; + + /* bytes of data for a request */ + int block_size; + int q_num; + unsigned long total_len; + +#define MAX_RUNS 1024 + int run_num; + /* tasks running in parallel */ + int compact_run_num; + + /* send thread number */ + int thread_num; + /* poll thread number -- ASYNC */ + int poll_num; + /* 0: sync mode, 1: async mode */ + int sync_mode; + /* + * positive value: the number of messages are sent at a time. + * 0: batch mode is disabled. + * batch mode is only valid for ASYNC operations. + */ + int batch_num; + /* input file */ + int fd_in; + /* output file */ + int fd_out; + /* inlist file */ + int fd_ilist; + /* outlist file */ + int fd_olist; + + /* 0: pbuffer, 1: sgl */ + __u8 data_fmt; + + bool verify; + bool verbose; + bool is_decomp; + bool is_stream; + bool is_file; + bool use_env; + + int warmup_num; + +#define PERFORMANCE (1UL << 0) +#define TEST_ZLIB (1UL << 1) +#define TEST_THP (1UL << 2) + unsigned long option; + +#define STATS_NONE 0 +#define STATS_PRETTY 1 +#define STATS_CSV 2 + unsigned long display_stats; + + /* bind test case related below */ + int children; + +#define INJECT_SIG_BIND (1UL << 0) +#define INJECT_SIG_WORK (1UL << 1) +#define INJECT_TLB_FAULT (1UL << 2) + unsigned long faults; + +}; + +typedef struct _comp_md5_t { + MD5_CTX md5_ctx; + unsigned char md[MD5_DIGEST_LENGTH]; +} comp_md5_t; + +typedef struct hizip_chunk_list { + void *addr; + size_t size; + struct hizip_chunk_list *next; +} chunk_list_t; + +typedef struct _thread_data_t { + struct hizip_test_info *info; + struct wd_comp_req req; + comp_md5_t md5; + void *src; + void *dst; + size_t src_sz; + size_t dst_sz; + size_t sum; /* produced bytes for OUT */ + int tid; /* thread ID */ + int bcnt; /* batch mode: count */ + int pcnt; /* batch mode: poll count */ + int flush_bcnt; /* batch mode: flush count that is less batch_num */ + /* + * batch mode: set flag and wait batch end in sending thread. + * Clear batch flag if pcnt == bcnt in polling thread. + * batch_flag could replace flush_bcnt. + */ + int batch_flag; + sem_t sem; + chunk_list_t *in_list; + chunk_list_t *out_list; + struct wd_comp_req *reqs; +} thread_data_t; + +struct hizip_test_info { + struct test_options *opts; + char *in_buf, *out_buf; + size_t in_size, out_size; + /* in_chunk_sz & out_chunk_sz are used to format entries in list */ + size_t in_chunk_sz, out_chunk_sz; + size_t total_out; + struct uacce_dev_list *list; + handle_t h_sess; + struct wd_ctx_config ctx_conf; + pthread_t *send_tds; + int send_tnum; + pthread_t *poll_tds; + int poll_tnum; + /* tdatas: send thread data array, p_tdatas: poll thread data array */ + thread_data_t *tdatas; + thread_data_t *p_tdatas; + struct hizip_stats *stats; + struct { + struct timespec setup_time; + struct timespec start_time; + struct timespec end_time; + struct timespec setup_cputime; + struct timespec start_cputime; + struct timespec end_cputime; + struct rusage setup_rusage; + struct rusage start_rusage; + struct rusage end_rusage; + } tv; +}; + +extern int sum_pend, sum_thread_end; + +void *send_thread_func(void *arg); +void *poll_thread_func(void *arg); +void *sw_dfl_sw_ifl(void *arg); +int create_send_threads(struct test_options *opts, + struct hizip_test_info *info, + void *(*send_thread_func)(void *arg)); +int create_poll_threads(struct hizip_test_info *info, + void *(*poll_thread_func)(void *arg), + int num); +void free_threads(struct hizip_test_info *info); +int attach_threads(struct test_options *opts, + struct hizip_test_info *info); + +void gen_random_data(void *buf, size_t len); +int calculate_md5(comp_md5_t *md5, const void *buf, size_t len); +void dump_md5(comp_md5_t *md5); +int cmp_md5(comp_md5_t *orig, comp_md5_t *final); +void init_chunk_list(chunk_list_t *list, void *buf, size_t buf_sz, + size_t chunk_sz); +chunk_list_t *create_chunk_list(void *buf, size_t buf_sz, size_t chunk_sz); +void free_chunk_list(chunk_list_t *list); +int sw_deflate2(chunk_list_t *in_list, + chunk_list_t *out_list, + struct test_options *opts); +int sw_inflate2(chunk_list_t *in_list, + chunk_list_t *out_list, + struct test_options *opts); +int hw_deflate4(handle_t h_dfl, + chunk_list_t *in_list, + chunk_list_t *out_list, + struct test_options *opts, + sem_t *sem); +int hw_inflate4(handle_t h_ifl, + chunk_list_t *in_list, + chunk_list_t *out_list, + struct test_options *opts, + sem_t *sem); +int hw_deflate5(handle_t h_dfl, + chunk_list_t *in_list, + chunk_list_t *out_list, + thread_data_t *tdata); +int hw_inflate5(handle_t h_ifl, + chunk_list_t *in_list, + chunk_list_t *out_list, + thread_data_t *tdata); +int create_send_tdata(struct test_options *opts, + struct hizip_test_info *info); +int create_poll_tdata(struct test_options *opts, + struct hizip_test_info *info, + int poll_num); +void free2_threads(struct hizip_test_info *info); +int attach2_threads(struct test_options *opts, + struct hizip_test_info *info, + void *(*send_thread_func)(void *arg), + void *(*poll_thread_func)(void *arg)); +void *poll2_thread_func(void *arg); +int run_self_test(struct test_options *opts); +int run_cmd(struct test_options *opts); +int init_ctx_config(struct test_options *opts, + void *priv, + struct wd_sched **sched + ); +void uninit_config(void *priv, struct wd_sched *sched); +struct uacce_dev_list *get_dev_list(struct test_options *opts, int children); + +void hizip_prepare_random_input_data(char *buf, size_t len, size_t block_size); +int hizip_prepare_random_compressed_data(char *buf, size_t out_len, + size_t in_len, size_t *produced, + struct test_options *opts); + +int hizip_verify_random_output(struct test_options *opts, + struct hizip_test_info *info, + size_t out_sz); + +void *mmap_alloc(size_t len); +int mmap_free(void *addr, size_t len); + +int lib_poll_func(__u32 pos, __u32 expect, __u32 *count); +typedef int (*check_output_fn)(unsigned char *buf, unsigned int size, void *opaque); + +/* for block interface */ +int hw_blk_compress(int alg_type, int blksize, __u8 data_fmt, void *priv, + unsigned char *dst, __u32 *dstlen, + unsigned char *src, __u32 srclen); + +int hw_blk_decompress(int alg_type, int blksize, __u8 data_fmt, + unsigned char *dst, __u32 *dstlen, + unsigned char *src, __u32 srclen); + +/* for stream memory interface */ +int hw_stream_compress(int alg_type, int blksize, __u8 data_fmt, + unsigned char *dst, __u32 *dstlen, + unsigned char *src, __u32 srclen); + +int hw_stream_decompress(int alg_type, int blksize, __u8 data_fmt, + unsigned char *dst, __u32 *dstlen, + unsigned char *src, __u32 srclen); + +#ifdef USE_ZLIB +int hizip_check_output(void *buf, size_t size, size_t *checked, + check_output_fn check_output, void *opaque); +int zlib_deflate(void *output, unsigned int out_size, + void *input, unsigned int in_size, unsigned long *produced, + int alg_type); +#else +static inline int hizip_check_output(void *buf, size_t size, size_t *checked, + check_output_fn check_output, + void *opaque) +{ + static bool printed = false; + + if (!printed) { + WD_ERR("no zlib available, output buffer won't be checked\n"); + printed = true; + } + return -ENOSYS; +} +static inline int zlib_deflate(void *output, unsigned int out_size, void *input, + unsigned int in_size, unsigned long *produced, + int alg_type) +{ + WD_ERR("no zlib available\n"); + return -ENOSYS; +} +#endif + +static inline void hizip_test_adjust_len(struct test_options *opts) +{ + /* + * Align size to the next block. We allow non-power-of-two block sizes. + */ + opts->total_len = (opts->total_len + opts->block_size - 1) / + opts->block_size * opts->block_size; +} + +#define COMMON_OPTSTRING "hb:n:q:l:FSs:Vvzt:m:dacLZ" + +#define COMMON_HELP "%s [opts]\n" \ + " -b block size\n" \ + " -n number of runs\n" \ + " -q number of queues\n" \ + " -l number of compact runs\n" \ + " -F input file, default no input\n" \ + " -S stream mode, default block mode\n" \ + " -s total size\n" \ + " -V verify output\n" \ + " -v display detailed performance information\n" \ + " -a test deflate algorithm, default gzip\n" \ + " -z test zlib algorithm, default gzip\n" \ + " -t number of thread per process\n" \ + " -m mode of queues: 0 sync, 1 async\n" \ + " -d test decompression, default compression\n" \ + " -c use cpu to do zlib\n" \ + " -L test sgl type buffer, default pbuffer\n" \ + " -Z test lz77_zstd algorithm, default gzip\n" \ + "\n\n" + +int parse_common_option(const char opt, const char *optarg, + struct test_options *opts); +#endif /* TEST_LIB_H_ */ diff --git a/uadk/test/hisi_zip_test/test_sva_perf.c b/uadk/test/hisi_zip_test/test_sva_perf.c new file mode 100644 index 0000000..98670a5 --- /dev/null +++ b/uadk/test/hisi_zip_test/test_sva_perf.c @@ -0,0 +1,524 @@ +// SPDX-License-Identifier: Apache-2.0 +/* + * Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. + * Copyright 2020-2021 Linaro ltd. + */ + +/* + * Test performance of the SVA API + */ +#include /* For __NR_perf_event_open */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "test_lib.h" +#include "wd_sched.h" + +enum hizip_stats_variable { + ST_SETUP_TIME, + ST_RUN_TIME, + ST_CPU_TIME, + + /* CPU usage */ + ST_USER_TIME, + ST_SYSTEM_TIME, + + /* Faults */ + ST_MINFLT, + ST_MAJFLT, + + /* Context switches */ + ST_INVCTX, + ST_VCTX, + + /* Signals */ + ST_SIGNALS, + + /* Aggregated */ + ST_SPEED, + ST_TOTAL_SPEED, + ST_CPU_IDLE, + ST_FAULTS, + ST_IOPF, + + ST_COMPRESSION_RATIO, + + NUM_STATS +}; + +struct hizip_stats { + double v[NUM_STATS]; +}; + +int perf_event_open(struct perf_event_attr *attr, + pid_t pid, int cpu, int group_fd, + unsigned long flags) +{ + return syscall(__NR_perf_event_open, attr, pid, cpu, group_fd, flags); +} + +unsigned long long perf_event_put(int *perf_fds, int nr_fds); + +int perf_event_get(const char *event_name, int **perf_fds, int *nr_fds) +{ + int ret; + int cpu; + FILE *fd; + int nr_cpus; + unsigned int event_id; + char event_id_file[256]; + struct perf_event_attr event = { + .type = PERF_TYPE_TRACEPOINT, + .size = sizeof(event), + .disabled = true, + }; + + *perf_fds = NULL; + *nr_fds = 0; + + nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); + if (nr_cpus <= 0) { + WD_ERR("invalid number of CPUs\n"); + return nr_cpus; + } + + ret = snprintf(event_id_file, sizeof(event_id_file), + "/sys/kernel/debug/tracing/events/%s/id", event_name); + if (ret >= sizeof(event_id_file)) { + WD_ERR("event_id buffer overflow\n"); + return -EOVERFLOW; + } + fd = fopen(event_id_file, "r"); + if (fd == NULL) { + ret = -errno; + WD_ERR("Couldn't open file %s\n", event_id_file); + return ret; + } + + if (fscanf(fd, "%d", &event_id) != 1) { + WD_ERR("Couldn't parse file %s\n", event_id_file); + return -EINVAL; + } + fclose(fd); + event.config = event_id; + + *perf_fds = calloc(nr_cpus, sizeof(int)); + if (!*perf_fds) + return -ENOMEM; + *nr_fds = nr_cpus; + + /* + * An event is bound to either a CPU or a PID. If we want both, we need + * to open the event on all CPUs. Note that we can't use a perf group + * since they have to be on the same CPU. + */ + for (cpu = 0; cpu < nr_cpus; cpu++) { + int fd = perf_event_open(&event, -1, cpu, -1, 0); + + if (fd < 0) { + WD_ERR("Couldn't get perf event %s on CPU%d: %d\n", + event_name, cpu, errno); + perf_event_put(*perf_fds, cpu); + return fd; + } + + ioctl(fd, PERF_EVENT_IOC_RESET, 0); + ioctl(fd, PERF_EVENT_IOC_ENABLE, 0); + (*perf_fds)[cpu] = fd; + } + + return 0; +} + +/* + * Closes the perf fd and return the sample count. If it wasn't open, return 0. + */ +unsigned long long perf_event_put(int *perf_fds, int nr_fds) +{ + int ret; + int cpu; + uint64_t count, total = 0; + + if (!perf_fds) + return 0; + + for (cpu = 0; cpu < nr_fds; cpu++) { + int fd = perf_fds[cpu]; + + if (fd <= 0) { + WD_ERR("Invalid perf fd %d\n", cpu); + continue; + } + + ioctl(fd, PERF_EVENT_IOC_DISABLE, 0); + + ret = read(fd, &count, sizeof(count)); + if (ret < sizeof(count)) + WD_ERR("Couldn't read perf event for CPU%d\n", cpu); + + total += count; + close(fd); + + } + + free(perf_fds); + return total; +} + +static void set_thp(struct test_options *opts) +{ + char *p; + char s[14]; + FILE *file; + + file = fopen("/sys/kernel/mm/transparent_hugepage/enabled", "r"); + if (!file) + goto out_err; + p = fgets(s, 14, file); + fclose(file); + if (!p) + goto out_err; + + if (strcmp(s, "never") == 0) { + printf("Cannot test THP with enable=never\n"); + return; + } + + file = fopen("/sys/kernel/mm/transparent_hugepage/defrag", "r"); + if (!file) + goto out_err; + p = fgets(s, 14, file); + fclose(file); + if (!p) + goto out_err; + + if (strcmp(s, "defer") == 0 || strcmp(s, "never") == 0) { + printf("Cannot test THP with defrag=%s\n", s); + return; + } + + return; +out_err: + printf("THP unsupported?\n"); +} + +void stat_setup(struct hizip_test_info *info) +{ + clock_gettime(CLOCK_MONOTONIC_RAW, &info->tv.setup_time); + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &info->tv.setup_cputime); + getrusage(RUSAGE_SELF, &info->tv.setup_rusage); +} + +void stat_start(struct hizip_test_info *info) +{ + clock_gettime(CLOCK_MONOTONIC_RAW, &info->tv.start_time); + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &info->tv.start_cputime); + getrusage(RUSAGE_SELF, &info->tv.start_rusage); +} + +void stat_end(struct hizip_test_info *info) +{ + struct test_options *opts = info->opts; + struct hizip_stats *stats = info->stats; + double v; + size_t total_out; + unsigned long total_len; + + total_out = __atomic_load_n(&info->total_out, __ATOMIC_ACQUIRE); + clock_gettime(CLOCK_MONOTONIC_RAW, &info->tv.end_time); + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &info->tv.end_cputime); + getrusage(RUSAGE_SELF, &info->tv.end_rusage); + + stats->v[ST_SETUP_TIME] = (info->tv.start_time.tv_sec - + info->tv.setup_time.tv_sec) * 1000000000 + + info->tv.start_time.tv_nsec - + info->tv.setup_time.tv_nsec; + stats->v[ST_RUN_TIME] = (info->tv.end_time.tv_sec - + info->tv.start_time.tv_sec) * 1000000000 + + info->tv.end_time.tv_nsec - + info->tv.start_time.tv_nsec; + + stats->v[ST_CPU_TIME] = (info->tv.end_cputime.tv_sec - + info->tv.setup_cputime.tv_sec) * 1000000000 + + info->tv.end_cputime.tv_nsec - + info->tv.setup_cputime.tv_nsec; + stats->v[ST_USER_TIME] = (info->tv.end_rusage.ru_utime.tv_sec - + info->tv.setup_rusage.ru_utime.tv_sec) * + 1000000 + + info->tv.end_rusage.ru_utime.tv_usec - + info->tv.setup_rusage.ru_utime.tv_usec; + stats->v[ST_SYSTEM_TIME] = (info->tv.end_rusage.ru_stime.tv_sec - + info->tv.setup_rusage.ru_stime.tv_sec) * + 1000000 + + info->tv.end_rusage.ru_stime.tv_usec - + info->tv.setup_rusage.ru_stime.tv_usec; + + stats->v[ST_MINFLT] = info->tv.end_rusage.ru_minflt - + info->tv.setup_rusage.ru_minflt; + stats->v[ST_MAJFLT] = info->tv.end_rusage.ru_majflt - + info->tv.setup_rusage.ru_majflt; + + stats->v[ST_VCTX] = info->tv.end_rusage.ru_nvcsw - + info->tv.setup_rusage.ru_nvcsw; + stats->v[ST_INVCTX] = info->tv.end_rusage.ru_nivcsw - + info->tv.setup_rusage.ru_nivcsw; + + stats->v[ST_SIGNALS] = info->tv.end_rusage.ru_nsignals - + info->tv.setup_rusage.ru_nsignals; + + /* check last loop is enough, same as below hizip_verify_output */ + stats->v[ST_COMPRESSION_RATIO] = (double)opts->total_len / + total_out * 100; + + total_len = opts->total_len * opts->compact_run_num; + /* ST_RUN_TIME records nanoseconds */ + stats->v[ST_SPEED] = (total_len * opts->thread_num * 1000) / + (1.024 * 1.024 * stats->v[ST_RUN_TIME]); + + stats->v[ST_TOTAL_SPEED] = (total_len * opts->thread_num * 1000) / + ((stats->v[ST_RUN_TIME] + + stats->v[ST_SETUP_TIME]) * 1.024 * 1.024); + + v = stats->v[ST_RUN_TIME] + stats->v[ST_SETUP_TIME]; + stats->v[ST_CPU_IDLE] = (v - stats->v[ST_CPU_TIME]) / v * 100; + stats->v[ST_FAULTS] = stats->v[ST_MAJFLT] + stats->v[ST_MINFLT]; +} + +static void handle_sigbus(int sig) +{ + printf("SIGBUS!\n"); + _exit(0); +} + +int main(int argc, char **argv) +{ + struct test_options opts = { + .alg_type = WD_GZIP, + .op_type = WD_DIR_COMPRESS, + .q_num = 1, + .run_num = 1, + .compact_run_num = 1, + .thread_num = 1, + .sync_mode = 0, + .block_size = 512000, + .total_len = opts.block_size * 10, + .verify = false, + .verbose = false, + .is_decomp = false, + .is_stream = false, + .is_file = false, + .display_stats = STATS_PRETTY, + .children = 0, + .faults = 0, + .data_fmt = 0, + }; + struct option long_options[] = { + {"self", no_argument, 0, 0 }, + {"in", required_argument, 0, 0 }, + {"out", required_argument, 0, 0 }, + {"ilist", required_argument, 0, 0 }, + {"olist", required_argument, 0, 0 }, + {"env", no_argument, 0, 0 }, + {0, 0, 0, 0 }, + }; + int show_help = 0; + int opt, option_idx; + int self = 0; + + opts.fd_in = -1; + opts.fd_out = -1; + opts.fd_ilist = -1; + opts.fd_olist = -1; + opts.alg_type = WD_COMP_ALG_MAX; + while ((opt = getopt_long(argc, argv, COMMON_OPTSTRING "f:o:w:k:r:", + long_options, &option_idx)) != -1) { + switch (opt) { + case 0: + switch (option_idx) { + case 0: /* self */ + self = 1; + break; + case 1: /* in */ + if (optarg) { + opts.fd_in = open(optarg, O_RDONLY); + if (opts.fd_in < 0) { + printf("Fail to open %s\n", + optarg); + show_help = 1; + } else + opts.is_file = true; + } else { + printf("Input file is missing!\n"); + show_help = 1; + } + if (lseek(opts.fd_in, 0, SEEK_SET) < 0) { + printf("Fail on lseek()!\n"); + show_help = 1; + } + break; + case 2: /* out */ + if (optarg) { + opts.fd_out = open(optarg, + O_CREAT | O_WRONLY, + S_IWUSR | S_IRGRP | + S_IROTH); + if (opts.fd_out < 0) { + printf("Fail to open %s\n", + optarg); + show_help = 1; + } else + opts.is_file = true; + } else { + printf("Output file is missing!\n"); + show_help = 1; + } + if (lseek(opts.fd_out, 0, SEEK_SET) < 0) { + printf("Fail on lseek()!\n"); + show_help = 1; + } + break; + case 3: /* ilist */ + if (!optarg) { + printf("IN list file is missing!\n"); + show_help = 1; + break; + } + opts.fd_ilist = open(optarg, O_RDONLY); + if (opts.fd_ilist < 0) { + printf("Fail to open %s\n", optarg); + show_help = 1; + break; + } + opts.is_file = true; + if (lseek(opts.fd_ilist, 0, SEEK_SET) < 0) { + printf("Fail on lseek()!\n"); + show_help = 1; + break; + } + break; + case 4: /* olist */ + if (!optarg) { + printf("OUT list file is missing!\n"); + show_help = 1; + break; + } + opts.fd_olist = open(optarg, + O_CREAT | O_WRONLY, + S_IWUSR | S_IRGRP | + S_IROTH); + if (opts.fd_olist < 0) { + printf("Fail to open %s\n", optarg); + show_help = 1; + break; + } + opts.is_file = true; + if (lseek(opts.fd_olist, 0, SEEK_SET) < 0) { + printf("Fail on lseek()!\n"); + show_help = 1; + break; + } + break; + case 5: /* env */ + opts.use_env = true; + break; + default: + show_help = 1; + break; + } + break; + case 'f': + if (strcmp(optarg, "none") == 0) { + opts.display_stats = STATS_NONE; + } else if (strcmp(optarg, "csv") == 0) { + opts.display_stats = STATS_CSV; + } else if (strcmp(optarg, "pretty") == 0) { + opts.display_stats = STATS_PRETTY; + } else { + SYS_ERR_COND(1, "invalid argument to -f: '%s'\n", optarg); + break; + } + break; + case 'o': + switch (optarg[0]) { + case 'p': + opts.option |= PERFORMANCE; + break; + case 't': + opts.option |= TEST_THP; + set_thp(&opts); + break; + default: + SYS_ERR_COND(1, "invalid argument to -o: '%s'\n", optarg); + break; + } + break; + case 'c': + opts.option |= TEST_ZLIB; + break; + case 'r': + opts.children = strtol(optarg, NULL, 0); + if (opts.children < 0) + show_help = 1; + break; + case 'k': + switch (optarg[0]) { + case 'b': + opts.faults |= INJECT_SIG_BIND; + break; + case 't': + opts.faults |= INJECT_TLB_FAULT; + break; + case 'w': + opts.faults |= INJECT_SIG_WORK; + break; + default: + SYS_ERR_COND(1, "invalid argument to -k: '%s'\n", optarg); + break; + } + break; + default: + show_help = parse_common_option(opt, optarg, &opts); + break; + } + } + + signal(SIGBUS, handle_sigbus); + + if (!show_help) { + if (self) + return run_self_test(&opts); + return run_cmd(&opts); + } + + hizip_test_adjust_len(&opts); + + SYS_ERR_COND(show_help || optind > argc, + COMMON_HELP + " -f output format for the statistics\n" + " 'none' do not output statistics\n" + " 'pretty' human readable format\n" + " 'csv' raw, machine readable\n" + " -o options\n" + " 'perf' prefaults the output pages\n" + " 'thp' try to enable transparent huge pages\n" + " 'zlib' use zlib instead of the device\n" + " -r number of children to create\n" + " -k kill thread\n" + " 'bind' kills the process after bind\n" + " 'tlb' tries to access an unmapped buffer\n" + " 'work' kills the process while the queue is working\n", + argv[0] + ); + return 0; +} diff --git a/uadk/test/hisi_zip_test/testsuit.c b/uadk/test/hisi_zip_test/testsuit.c new file mode 100644 index 0000000..ac1a5f6 --- /dev/null +++ b/uadk/test/hisi_zip_test/testsuit.c @@ -0,0 +1,1372 @@ +// SPDX-License-Identifier: Apache-2.0 +/* + * Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. + * Copyright 2020-2021 Linaro ltd. + */ + +#include +#include +#include +#include +#include "test_lib.h" + +#define POLL_STRING_LEN 128 + +enum hizip_stats_variable { + ST_SETUP_TIME, + ST_RUN_TIME, + ST_CPU_TIME, + + /* CPU usage */ + ST_USER_TIME, + ST_SYSTEM_TIME, + + /* Faults */ + ST_MINFLT, + ST_MAJFLT, + + /* Context switches */ + ST_INVCTX, + ST_VCTX, + + /* Signals */ + ST_SIGNALS, + + /* Aggregated */ + ST_SPEED, + ST_TOTAL_SPEED, + ST_CPU_IDLE, + ST_FAULTS, + ST_IOPF, + + ST_COMPRESSION_RATIO, + + NUM_STATS +}; + +struct hizip_stats { + double v[NUM_STATS]; +}; + +extern int perf_event_open(struct perf_event_attr *attr, + pid_t pid, int cpu, int group_fd, + unsigned long flags); +extern int perf_event_get(const char *event_name, int **perf_fds, int *nr_fds); +extern unsigned long long perf_event_put(int *perf_fds, int nr_fds); +extern void stat_setup(struct hizip_test_info *info); +extern void stat_start(struct hizip_test_info *info); +extern void stat_end(struct hizip_test_info *info); + +static size_t count_chunk_list_sz(chunk_list_t *list) +{ + size_t sum = 0; + chunk_list_t *p; + + for (p = list; p; p = p->next) + sum += p->size; + return sum; +} + +static void *sw_dfl_hw_ifl(void *arg) +{ + thread_data_t *tdata = (thread_data_t *)arg; + struct hizip_test_info *info = tdata->info; + struct test_options *opts = info->opts; + struct wd_comp_sess_setup setup = {0}; + struct sched_params param = {0}; + handle_t h_ifl; + void *tbuf; + size_t tbuf_sz; + chunk_list_t *tlist; + comp_md5_t final_md5 = {{0}}; + int i, ret; + __u32 tout_sz; + + tbuf_sz = tdata->src_sz * EXPANSION_RATIO; + tbuf = mmap_alloc(tbuf_sz); + if (!tbuf) + return (void *)(uintptr_t)(-ENOMEM); + tlist = create_chunk_list(tbuf, tbuf_sz, + info->in_chunk_sz * EXPANSION_RATIO); + if (!tlist) { + ret = -ENOMEM; + goto out; + } + if (opts->option & PERFORMANCE) { + /* hack: + * memset buffer and trigger page fault early in the cpu + * instead of later in the SMMU + * Enhance performance in sva case + * no impact to non-sva case + */ + memset(tbuf, 5, tbuf_sz); + } + if (opts->is_stream) { + /* STREAM mode: only one entry in the list */ + init_chunk_list(tdata->in_list, tdata->src, + tdata->src_sz, tdata->src_sz); + for (i = 0; i < opts->compact_run_num; i++) { + init_chunk_list(tlist, tbuf, tbuf_sz, tbuf_sz); + init_chunk_list(tdata->out_list, tdata->dst, + tdata->dst_sz, tdata->dst_sz); + ret = sw_deflate2(tdata->in_list, tlist, opts); + if (ret) { + printf("Fail to deflate by zlib: %d\n", ret); + goto out_strm; + } + tout_sz = tdata->dst_sz; + ret = hw_stream_decompress(opts->alg_type, + opts->block_size, + opts->data_fmt, + tdata->dst, + &tout_sz, + tlist->addr, + tlist->size); + if (ret) { + printf("Fail to inflate by HW: %d\n", ret); + goto out_strm; + } + ret = calculate_md5(&tdata->md5, tdata->in_list->addr, + tdata->in_list->size); + if (ret) { + printf("Fail to generate MD5 (%d)\n", ret); + goto out_strm; + } + ret = calculate_md5(&final_md5, tdata->out_list->addr, + tout_sz); + if (ret) { + printf("Fail to generate MD5 (%d)\n", ret); + goto out_strm; + } + ret = cmp_md5(&tdata->md5, &final_md5); + if (ret) { + printf("MD5 is unmatched (%d) at %dth times on " + "thread %d\n", ret, i, tdata->tid); + goto out_strm; + } + } + free_chunk_list(tlist); + mmap_free(tbuf, tbuf_sz); + return NULL; + } + + /* BLOCK mode */ + setup.alg_type = opts->alg_type; + setup.op_type = WD_DIR_DECOMPRESS; + + param.type = setup.op_type; + param.numa_id = 0; + setup.sched_param = ¶m; + h_ifl = wd_comp_alloc_sess(&setup); + if (!h_ifl) { + ret = -EINVAL; + goto out_strm; + } + + init_chunk_list(tdata->in_list, tdata->src, tdata->src_sz, + info->in_chunk_sz); + for (i = 0; i < opts->compact_run_num; i++) { + init_chunk_list(tlist, tbuf, tbuf_sz, + info->in_chunk_sz * EXPANSION_RATIO); + init_chunk_list(tdata->out_list, tdata->dst, tdata->dst_sz, + info->out_chunk_sz); + ret = sw_deflate2(tdata->in_list, tlist, opts); + if (ret) { + printf("Fail to deflate by zlib: %d\n", ret); + goto out_run; + } + ret = hw_inflate4(h_ifl, tlist, tdata->out_list, opts, + &tdata->sem); + if (ret) { + printf("Fail to inflate by HW: %d\n", ret); + goto out_run; + } + ret = calculate_md5(&tdata->md5, tdata->src, tdata->src_sz); + if (ret) { + printf("Fail to generate MD5 (%d)\n", ret); + goto out_run; + } + ret = calculate_md5(&final_md5, tdata->dst, tdata->dst_sz); + if (ret) { + printf("Fail to generate MD5 (%d)\n", ret); + goto out_run; + } + ret = cmp_md5(&tdata->md5, &final_md5); + if (ret) { + printf("MD5 is unmatched (%d) at %dth times on " + "thread %d\n", ret, i, tdata->tid); + goto out_run; + } + } + wd_comp_free_sess(h_ifl); + free_chunk_list(tlist); + mmap_free(tbuf, tbuf_sz); + /* mark sending thread to end */ + __atomic_add_fetch(&sum_thread_end, 1, __ATOMIC_ACQ_REL); + return NULL; +out_run: + wd_comp_free_sess(h_ifl); +out_strm: + free_chunk_list(tlist); +out: + mmap_free(tbuf, tbuf_sz); + return (void *)(uintptr_t)(ret); +} + +static void *hw_dfl_sw_ifl(void *arg) +{ + thread_data_t *tdata = (thread_data_t *)arg; + struct hizip_test_info *info = tdata->info; + struct test_options *opts = info->opts; + struct wd_comp_sess_setup setup = {0}; + struct sched_params param = {0}; + handle_t h_dfl; + void *tbuf; + size_t tbuf_sz; + chunk_list_t *tlist; + comp_md5_t final_md5 = {{0}}; + int i, ret; + __u32 tmp_sz; + + tbuf_sz = tdata->src_sz * EXPANSION_RATIO; + tbuf = mmap_alloc(tbuf_sz); + if (!tbuf) + return (void *)(uintptr_t)(-ENOMEM); + tlist = create_chunk_list(tbuf, tbuf_sz, + opts->block_size * EXPANSION_RATIO); + if (!tlist) { + ret = -ENOMEM; + goto out; + } + if (opts->option & PERFORMANCE) { + /* hack: + * memset buffer and trigger page fault early in the cpu + * instead of later in the SMMU + * Enhance performance in sva case + * no impact to non-sva case + */ + memset(tbuf, 5, tbuf_sz); + } + if (opts->is_stream) { + /* STREAM mode: only one entry in the list */ + init_chunk_list(tdata->in_list, tdata->src, + tdata->src_sz, tdata->src_sz); + for (i = 0; i < opts->compact_run_num; i++) { + init_chunk_list(tlist, tbuf, tbuf_sz, tbuf_sz); + init_chunk_list(tdata->out_list, tdata->dst, + tdata->dst_sz, tdata->dst_sz); + tmp_sz = tbuf_sz; + ret = hw_stream_compress(opts->alg_type, + opts->block_size, + opts->data_fmt, + tlist->addr, + &tmp_sz, + tdata->src, + tdata->src_sz); + if (ret) { + printf("Fail to deflate by HW: %d\n", ret); + goto out_strm; + } + tlist->size = tmp_sz; // write back + ret = sw_inflate2(tlist, tdata->out_list, opts); + if (ret) { + printf("Fail to inflate by zlib: %d\n", ret); + goto out_strm; + } + ret = calculate_md5(&tdata->md5, tdata->in_list->addr, + tdata->in_list->size); + if (ret) { + printf("Fail to generate MD5 (%d)\n", ret); + goto out_strm; + } + ret = calculate_md5(&final_md5, tdata->out_list->addr, + tdata->out_list->size); + if (ret) { + printf("Fail to generate MD5 (%d)\n", ret); + goto out_strm; + } + ret = cmp_md5(&tdata->md5, &final_md5); + if (ret) { + printf("MD5 is unmatched (%d) at %dth times on " + "thread %d\n", ret, i, tdata->tid); + goto out_strm; + } + } + free_chunk_list(tlist); + mmap_free(tbuf, tbuf_sz); + return NULL; + } + + /* BLOCK mode */ + setup.alg_type = opts->alg_type; + setup.op_type = WD_DIR_COMPRESS; + param.type = setup.op_type; + param.numa_id = 0; + setup.sched_param = ¶m; + h_dfl = wd_comp_alloc_sess(&setup); + if (!h_dfl) { + ret = -EINVAL; + goto out_strm; + } + + init_chunk_list(tdata->in_list, tdata->src, tdata->src_sz, + info->in_chunk_sz); + for (i = 0; i < opts->compact_run_num; i++) { + init_chunk_list(tlist, tbuf, tbuf_sz, + opts->block_size * EXPANSION_RATIO); + init_chunk_list(tdata->out_list, tdata->dst, tdata->dst_sz, + info->out_chunk_sz); + ret = hw_deflate4(h_dfl, tdata->in_list, tlist, opts, + &tdata->sem); + if (ret) { + printf("Fail to deflate by HW: %d\n", ret); + goto out_run; + } + ret = sw_inflate2(tlist, tdata->out_list, opts); + if (ret) { + printf("Fail to inflate by zlib: %d\n", ret); + goto out_run; + } + ret = calculate_md5(&tdata->md5, tdata->src, tdata->src_sz); + if (ret) { + printf("Fail to generate MD5 (%d)\n", ret); + goto out_run; + } + ret = calculate_md5(&final_md5, tdata->dst, tdata->dst_sz); + if (ret) { + printf("Fail to generate MD5 (%d)\n", ret); + goto out_run; + } + ret = cmp_md5(&tdata->md5, &final_md5); + if (ret) { + printf("MD5 is unmatched (%d) at %dth times on " + "thread %d\n", ret, i, tdata->tid); + goto out_run; + } + } + wd_comp_free_sess(h_dfl); + free_chunk_list(tlist); + mmap_free(tbuf, tbuf_sz); + /* mark sending thread to end */ + __atomic_add_fetch(&sum_thread_end, 1, __ATOMIC_ACQ_REL); + return NULL; +out_run: + wd_comp_free_sess(h_dfl); +out_strm: + free_chunk_list(tlist); +out: + mmap_free(tbuf, tbuf_sz); + return (void *)(uintptr_t)(ret); +} + +static void *hw_dfl_hw_ifl(void *arg) +{ + thread_data_t *tdata = (thread_data_t *)arg; + struct hizip_test_info *info = tdata->info; + struct test_options *opts = info->opts; + struct wd_comp_sess_setup setup = {0}; + struct sched_params param = {0}; + handle_t h_dfl, h_ifl; + void *tbuf; + size_t tbuf_sz; + chunk_list_t *tlist; + comp_md5_t final_md5 = {{0}}; + int i, ret; + __u32 tmp_sz, tout_sz; + + tbuf_sz = tdata->src_sz * EXPANSION_RATIO; + tbuf = mmap_alloc(tbuf_sz); + if (!tbuf) + return (void *)(uintptr_t)(-ENOMEM); + if (opts->option & PERFORMANCE) { + /* hack: + * memset buffer and trigger page fault early in the cpu + * instead of later in the SMMU + * Enhance performance in sva case + * no impact to non-sva case + */ + memset(tbuf, 5, tbuf_sz); + } + if (opts->is_stream) { + for (i = 0; i < opts->compact_run_num; i++) { + tmp_sz = tbuf_sz; + ret = hw_stream_compress(opts->alg_type, + opts->block_size, + opts->data_fmt, + tbuf, + &tmp_sz, + tdata->src, + tdata->src_sz); + if (ret) { + printf("Fail to deflate by HW: %d\n", ret); + goto out; + } + tout_sz = tdata->dst_sz; + ret = hw_stream_decompress(opts->alg_type, + opts->block_size, + opts->data_fmt, + tdata->dst, + &tout_sz, + tbuf, + tmp_sz); + if (ret) { + printf("Fail to inflate by HW: %d\n", ret); + goto out; + } + ret = calculate_md5(&tdata->md5, tdata->in_list->addr, + tdata->in_list->size); + if (ret) { + printf("Fail to generate MD5 (%d)\n", ret); + goto out; + } + ret = calculate_md5(&final_md5, tdata->dst, tout_sz); + if (ret) { + printf("Fail to generate MD5 (%d)\n", ret); + goto out; + } + ret = cmp_md5(&tdata->md5, &final_md5); + if (ret) { + printf("MD5 is unmatched (%d) at %dth times on " + "thread %d\n", ret, i, tdata->tid); + goto out; + } + } + mmap_free(tbuf, tbuf_sz); + return NULL; + } + + /* BLOCK mode */ + tlist = create_chunk_list(tbuf, tbuf_sz, + opts->block_size * EXPANSION_RATIO); + if (!tlist) { + ret = -ENOMEM; + goto out; + } + + setup.alg_type = opts->alg_type; + setup.op_type = WD_DIR_COMPRESS; + param.type = setup.op_type; + param.numa_id = 0; + setup.sched_param = ¶m; + h_dfl = wd_comp_alloc_sess(&setup); + if (!h_dfl) { + ret = -EINVAL; + goto out_dfl; + } + + setup.op_type = WD_DIR_DECOMPRESS; + param.type = setup.op_type; + setup.sched_param = ¶m; + h_ifl = wd_comp_alloc_sess(&setup); + if (!h_ifl) { + ret = -EINVAL; + goto out_ifl; + } + + for (i = 0; i < opts->compact_run_num; i++) { + init_chunk_list(tlist, tbuf, tbuf_sz, + opts->block_size * EXPANSION_RATIO); + init_chunk_list(tdata->out_list, tdata->dst, + tdata->dst_sz, + info->out_chunk_sz); + ret = hw_deflate4(h_dfl, tdata->in_list, tlist, opts, + &tdata->sem); + if (ret) { + printf("Fail to deflate by HW: %d\n", ret); + goto out_run; + } + ret = hw_inflate4(h_ifl, tlist, tdata->out_list, opts, + &tdata->sem); + if (ret) { + printf("Fail to inflate by HW: %d\n", ret); + goto out_run; + } + ret = calculate_md5(&tdata->md5, tdata->src, tdata->src_sz); + if (ret) { + printf("Fail to generate MD5 (%d)\n", ret); + goto out_run; + } + ret = calculate_md5(&final_md5, tdata->dst, tdata->dst_sz); + if (ret) { + printf("Fail to generate MD5 (%d)\n", ret); + goto out_run; + } + ret = cmp_md5(&tdata->md5, &final_md5); + if (ret) { + printf("MD5 is unmatched (%d) at %dth times on " + "thread %d\n", ret, i, tdata->tid); + goto out_run; + } + } + wd_comp_free_sess(h_ifl); + wd_comp_free_sess(h_dfl); + free_chunk_list(tlist); + mmap_free(tbuf, tbuf_sz); + /* mark sending thread to end */ + __atomic_add_fetch(&sum_thread_end, 1, __ATOMIC_ACQ_REL); + return NULL; +out_run: + wd_comp_free_sess(h_ifl); +out_ifl: + wd_comp_free_sess(h_dfl); +out_dfl: + free_chunk_list(tlist); +out: + mmap_free(tbuf, tbuf_sz); + return (void *)(uintptr_t)(ret); +} + +static void *hw_dfl_perf(void *arg) +{ + thread_data_t *tdata = (thread_data_t *)arg; + struct hizip_test_info *info = tdata->info; + struct test_options *opts = info->opts; + struct wd_comp_sess_setup setup = {0}; + struct sched_params param = {0}; + handle_t h_dfl; + int i, ret; + uint32_t tout_sz; + + if (opts->is_stream) { + for (i = 0; i < opts->compact_run_num; i++) { + tout_sz = tdata->dst_sz; + ret = hw_stream_compress(opts->alg_type, + opts->block_size, + opts->data_fmt, + tdata->dst, + &tout_sz, + tdata->src, + tdata->src_sz); + if (ret) { + printf("Fail to deflate by HW: %d\n", ret); + return (void *)(uintptr_t)ret; + } + } + tdata->out_list->addr = tdata->dst; + tdata->out_list->size = tout_sz; + tdata->out_list->next = NULL; + return NULL; + } + + setup.alg_type = opts->alg_type; + setup.op_type = WD_DIR_COMPRESS; + param.type = setup.op_type; + param.numa_id = 0; + setup.sched_param = ¶m; + h_dfl = wd_comp_alloc_sess(&setup); + if (!h_dfl) + return (void *)(uintptr_t)(-EINVAL); + + for (i = 0; i < opts->compact_run_num; i++) { + init_chunk_list(tdata->out_list, tdata->dst, + tdata->dst_sz, + info->out_chunk_sz); + ret = hw_deflate4(h_dfl, tdata->in_list, tdata->out_list, opts, + &tdata->sem); + if (ret) { + printf("Fail to deflate by HW: %d\n", ret); + goto out; + } + } + wd_comp_free_sess(h_dfl); + /* mark sending thread to end */ + __atomic_add_fetch(&sum_thread_end, 1, __ATOMIC_ACQ_REL); + return NULL; +out: + wd_comp_free_sess(h_dfl); + return (void *)(uintptr_t)(ret); +} + +static void *hw_ifl_perf(void *arg) +{ + thread_data_t *tdata = (thread_data_t *)arg; + struct hizip_test_info *info = tdata->info; + struct test_options *opts = info->opts; + struct wd_comp_sess_setup setup = {0}; + struct sched_params param = {0}; + handle_t h_ifl; + int i, ret; + uint32_t tout_sz; + + if (opts->is_stream) { + for (i = 0; i < opts->compact_run_num; i++) { + tout_sz = tdata->dst_sz; + ret = hw_stream_decompress(opts->alg_type, + opts->block_size, + opts->data_fmt, + tdata->dst, + &tout_sz, + tdata->in_list->addr, + tdata->in_list->size); + if (ret) { + printf("Fail to inflate by HW: %d\n", ret); + return (void *)(uintptr_t)ret; + } + tdata->out_list->addr = tdata->dst; + tdata->out_list->size = tout_sz; + tdata->out_list->next = NULL; + } + return NULL; + } + + setup.alg_type = opts->alg_type; + setup.op_type = WD_DIR_DECOMPRESS; + param.type = setup.op_type; + param.numa_id = 0; + setup.sched_param = ¶m; + h_ifl = wd_comp_alloc_sess(&setup); + if (!h_ifl) + return (void *)(uintptr_t)(-EINVAL); + + for (i = 0; i < opts->compact_run_num; i++) { + init_chunk_list(tdata->out_list, tdata->dst, + tdata->dst_sz, + info->out_chunk_sz); + ret = hw_inflate4(h_ifl, tdata->in_list, tdata->out_list, opts, + &tdata->sem); + if (ret) { + printf("Fail to inflate by HW: %d\n", ret); + goto out; + } + } + wd_comp_free_sess(h_ifl); + /* mark sending thread to end */ + __atomic_add_fetch(&sum_thread_end, 1, __ATOMIC_ACQ_REL); + return NULL; +out: + wd_comp_free_sess(h_ifl); + return (void *)(uintptr_t)(ret); +} + +/* BATCH mode is used */ +void *hw_dfl_perf3(void *arg) +{ + thread_data_t *tdata = (thread_data_t *)arg; + struct hizip_test_info *info = tdata->info; + struct test_options *opts = info->opts; + struct wd_comp_sess_setup setup = {0}; + struct sched_params param = {0}; + handle_t h_dfl; + int i, ret; + uint32_t tout_sz; + + if (opts->is_stream) { + for (i = 0; i < opts->compact_run_num; i++) { + tout_sz = tdata->dst_sz; + ret = hw_stream_compress(opts->alg_type, + opts->block_size, + opts->data_fmt, + tdata->dst, + &tout_sz, + tdata->src, + tdata->src_sz); + if (ret) { + printf("Fail to deflate by HW: %d\n", ret); + return (void *)(uintptr_t)ret; + } + } + tdata->out_list->addr = tdata->dst; + tdata->out_list->size = tout_sz; + tdata->out_list->next = NULL; + return NULL; + } + + setup.alg_type = opts->alg_type; + setup.op_type = WD_DIR_COMPRESS; + param.type = setup.op_type; + param.numa_id = 0; + setup.sched_param = ¶m; + h_dfl = wd_comp_alloc_sess(&setup); + if (!h_dfl) + return (void *)(uintptr_t)(-EINVAL); + + for (i = 0; i < opts->compact_run_num; i++) { + init_chunk_list(tdata->out_list, tdata->dst, + tdata->dst_sz, + info->out_chunk_sz); + ret = hw_deflate5(h_dfl, tdata->in_list, tdata->out_list, + tdata); + if (ret) { + printf("Fail to deflate by HW: %d\n", ret); + goto out; + } + } + wd_comp_free_sess(h_dfl); + /* mark sending thread to end */ + __atomic_add_fetch(&sum_thread_end, 1, __ATOMIC_ACQ_REL); + return NULL; +out: + wd_comp_free_sess(h_dfl); + return (void *)(uintptr_t)(ret); +} + +/* BATCH mode is used */ +void *hw_ifl_perf3(void *arg) +{ + thread_data_t *tdata = (thread_data_t *)arg; + struct hizip_test_info *info = tdata->info; + struct test_options *opts = info->opts; + struct wd_comp_sess_setup setup = {0}; + struct sched_params param = {0}; + handle_t h_ifl; + int i, ret; + uint32_t tout_sz; + + if (opts->is_stream) { + for (i = 0; i < opts->compact_run_num; i++) { + tout_sz = tdata->dst_sz; + ret = hw_stream_decompress(opts->alg_type, + opts->block_size, + opts->data_fmt, + tdata->dst, + &tout_sz, + tdata->src, + tdata->src_sz); + if (ret) { + printf("Fail to inflate by HW: %d\n", ret); + return (void *)(uintptr_t)ret; + } + tdata->out_list->addr = tdata->dst; + tdata->out_list->size = tout_sz; + tdata->out_list->next = NULL; + } + return NULL; + } + + setup.alg_type = opts->alg_type; + setup.op_type = WD_DIR_DECOMPRESS; + param.type = setup.op_type; + param.numa_id = 0; + setup.sched_param = ¶m; + h_ifl = wd_comp_alloc_sess(&setup); + if (!h_ifl) + return (void *)(uintptr_t)(-EINVAL); + + for (i = 0; i < opts->compact_run_num; i++) { + init_chunk_list(tdata->out_list, tdata->dst, + tdata->dst_sz, + info->out_chunk_sz); + ret = hw_inflate5(h_ifl, tdata->in_list, tdata->out_list, + tdata); + if (ret) { + printf("Fail to inflate by HW: %d\n", ret); + goto out; + } + } + wd_comp_free_sess(h_ifl); + /* mark sending thread to end */ + __atomic_add_fetch(&sum_thread_end, 1, __ATOMIC_ACQ_REL); + return NULL; +out: + wd_comp_free_sess(h_ifl); + return (void *)(uintptr_t)(ret); +} + +/* + * Load both ilist file. + */ +int load_ilist(struct hizip_test_info *info, char *model) +{ + struct test_options *opts = info->opts; + thread_data_t *tdata = &info->tdatas[0]; + chunk_list_t *p; + size_t sum = 0; + ssize_t file_sz = 0; + void *addr; + + if (!strcmp(model, "hw_ifl_perf")) { + if (!opts->is_stream) { + if (opts->fd_ilist < 0) { + printf("Missing IN list file!\n"); + return -EINVAL; + } + p = tdata->in_list; + addr = info->in_buf; + while (p) { + file_sz = read(opts->fd_ilist, p, + sizeof(chunk_list_t)); + if (file_sz < 0) + return -EFAULT; + p->addr = addr; + sum += file_sz; + if (p->next) + p->next = p + 1; + addr += p->size; + p = p->next; + } + } + } + return (int)sum; +} + +/* + * Load compression/decompression content. + */ +int load_file_data(struct hizip_test_info *info) +{ + struct test_options *opts = info->opts; + size_t file_sz; + + file_sz = read(opts->fd_in, info->in_buf, info->in_size); + if (file_sz < info->in_size) { + printf("Expect to read %ld bytes. " + "But only read %ld bytes!\n", + info->in_size, file_sz); + return -EFAULT; + } + return (int)file_sz; +} + +/* + * Store both olist file. opts->is_file must be enabled first. + */ +int store_olist(struct hizip_test_info *info, char *model) +{ + struct test_options *opts = info->opts; + thread_data_t *tdata = &info->tdatas[0]; + chunk_list_t *p; + size_t sum = 0; + ssize_t file_sz = 0; + + if (!opts->is_stream) { + if (opts->fd_olist >= 0) { + /* compress with BLOCK */ + p = tdata->out_list; + while (p) { + file_sz = write(opts->fd_olist, p, + sizeof(chunk_list_t)); + if (file_sz < sizeof(chunk_list_t)) + return -EFAULT; + file_sz = write(opts->fd_out, p->addr, + p->size); + if (file_sz < p->size) + return -EFAULT; + p = p->next; + sum += file_sz; + } + } else { + /* decompress with BLOCK */ + p = tdata->out_list; + while (p) { + file_sz = write(opts->fd_out, p->addr, + p->size); + if (file_sz < p->size) + return -EFAULT; + p = p->next; + sum += file_sz; + } + } + } else if (opts->is_stream) { + p = tdata->out_list; + file_sz = write(opts->fd_out, p->addr, p->size); + if (file_sz < p->size) + return -EFAULT; + sum = file_sz; + } + return (int)sum; +} + +static int nonenv_resource_init(struct test_options *opts, + struct hizip_test_info *info, + struct wd_sched **sched) +{ + int ret; + + info->list = get_dev_list(opts, 1); + if (!info->list) + return -EINVAL; + ret = init_ctx_config(opts, info, sched); + if (ret < 0) { + wd_free_list_accels(info->list); + return ret; + } + return 0; +} + +static void nonenv_resource_uninit(struct test_options *opts, + struct hizip_test_info *info, + struct wd_sched *sched) +{ + uninit_config(info, sched); + wd_free_list_accels(info->list); +} + +static bool event_unavailable = false; + +int test_hw(struct test_options *opts, char *model) +{ + struct hizip_test_info info = {0}; + struct wd_sched *sched = NULL; + double ilen, usec, speed; + char zbuf[120]; + int ret, zbuf_idx, ifl_flag = 0; + void *(*func)(void *); + size_t tbuf_sz = 0; + void *tbuf = NULL; + struct stat statbuf; + chunk_list_t *tlist = NULL; + int div; + __u32 num; + __u8 enable; + int nr_fds = 0; + int *perf_fds = NULL; + struct hizip_stats stats; + + if (!opts || !model) { + ret = -EINVAL; + goto out; + } + info.opts = opts; + info.stats = &stats; + + if (!event_unavailable && + perf_event_get("iommu/dev_fault", &perf_fds, &nr_fds)) { + printf("IOPF statistic unavailable\n"); + /* No need to retry and print an error on every run */ + event_unavailable = true; + } + stat_setup(&info); + + memset(zbuf, 0, 120); + if (!strcmp(model, "sw_dfl_hw_ifl")) { + func = sw_dfl_hw_ifl; + info.in_size = opts->total_len; + if (opts->is_stream) + info.out_size = opts->total_len; + else + info.out_size = opts->total_len; + info.in_chunk_sz = opts->block_size; + info.out_chunk_sz = opts->block_size; + zbuf_idx = sprintf(zbuf, "Mix SW deflate and HW %s %s inflate", + opts->sync_mode ? "ASYNC" : "SYNC", + opts->is_stream ? "STREAM" : "BLOCK"); + } else if (!strcmp(model, "hw_dfl_sw_ifl")) { + func = hw_dfl_sw_ifl; + info.in_size = opts->total_len; + info.out_size = opts->total_len; + info.in_chunk_sz = opts->block_size; + info.out_chunk_sz = opts->block_size; + zbuf_idx = sprintf(zbuf, "Mix HW %s %s deflate and SW inflate", + opts->sync_mode ? "ASYNC" : "SYNC", + opts->is_stream ? "STREAM" : "BLOCK"); + } else if (!strcmp(model, "hw_dfl_hw_ifl")) { + func = hw_dfl_hw_ifl; + info.in_size = opts->total_len; + if (opts->is_stream) + info.out_size = opts->total_len; + else + info.out_size = opts->total_len; + info.in_chunk_sz = opts->block_size; + info.out_chunk_sz = opts->block_size; + zbuf_idx = sprintf(zbuf, + "Mix HW %s %s deflate and HW %s %s inflate", + opts->sync_mode ? "ASYNC" : "SYNC", + opts->is_stream ? "STREAM" : "BLOCK", + opts->sync_mode ? "ASYNC" : "SYNC", + opts->is_stream ? "STREAM" : "BLOCK"); + } else if (!strcmp(model, "hw_dfl_perf")) { + func = hw_dfl_perf; + info.in_size = opts->total_len; + info.out_size = opts->total_len * EXPANSION_RATIO; + info.in_chunk_sz = opts->block_size; + info.out_chunk_sz = opts->block_size * EXPANSION_RATIO; + zbuf_idx = sprintf(zbuf, "HW %s %s deflate", + opts->sync_mode ? "ASYNC" : "SYNC", + opts->is_stream ? "STREAM" : "BLOCK"); + } else if (!strcmp(model, "hw_dfl_perf3")) { + func = hw_dfl_perf3; + info.in_size = opts->total_len; + info.out_size = opts->total_len * EXPANSION_RATIO; + info.in_chunk_sz = opts->block_size; + info.out_chunk_sz = opts->block_size * EXPANSION_RATIO; + zbuf_idx = sprintf(zbuf, "HW %s %s deflate", + opts->sync_mode ? "ASYNC" : "SYNC", + opts->is_stream ? "STREAM" : "BLOCK"); + } else if (!strcmp(model, "hw_ifl_perf")) { + func = hw_ifl_perf; + info.in_size = opts->total_len; + info.out_size = opts->total_len * INFLATION_RATIO; + info.in_chunk_sz = opts->block_size; + info.out_chunk_sz = opts->block_size * INFLATION_RATIO; + zbuf_idx = sprintf(zbuf, "HW %s %s inflate", + opts->sync_mode ? "ASYNC" : "SYNC", + opts->is_stream ? "STREAM" : "BLOCK"); + ifl_flag = 1; + } else if (!strcmp(model, "hw_ifl_perf3")) { + func = hw_ifl_perf3; + info.in_size = opts->total_len * EXPANSION_RATIO; + info.out_size = opts->total_len; + info.in_chunk_sz = opts->block_size; + info.out_chunk_sz = opts->block_size * INFLATION_RATIO; + zbuf_idx = sprintf(zbuf, "HW %s %s inflate", + opts->sync_mode ? "ASYNC" : "SYNC", + opts->is_stream ? "STREAM" : "BLOCK"); + ifl_flag = 1; + } else { + printf("Wrong model is specified:%s\n", model); + ret = -EINVAL; + goto out; + } + + if (opts->use_env) + ret = wd_comp_env_init(NULL); + else + ret = nonenv_resource_init(opts, &info, &sched); + if (ret < 0) + goto out; + + if (opts->faults & INJECT_SIG_BIND) + kill(getpid(), SIGTERM); + + if (opts->use_env) { + ret = wd_comp_get_env_param(0, opts->op_type, opts->sync_mode, &num, &enable); + if (ret < 0) + goto out; + } + + if (opts->is_file) { + ret = fstat(opts->fd_in, &statbuf); + if (ret < 0) + goto out_src; + opts->total_len = statbuf.st_size; + info.in_size = opts->total_len; + if (ifl_flag) + info.out_size = opts->total_len * INFLATION_RATIO; + else + info.out_size = opts->total_len * EXPANSION_RATIO; + /* + * If fd_ilist exists, it's inflation. + * Make sure block inflation has enough room. + */ + if (opts->fd_ilist >= 0) { + ret = fstat(opts->fd_ilist, &statbuf); + if (!ret) { + div = statbuf.st_size / sizeof(chunk_list_t); + info.in_chunk_sz = (info.in_size + div - 1) / + div; + info.out_chunk_sz = (info.out_size + div - 1) / + div; + } + } + } + info.in_buf = mmap_alloc(info.in_size); + if (!info.in_buf) { + ret = -ENOMEM; + goto out_src; + } + ret = create_send_tdata(opts, &info); + if (ret) + goto out_send; + ret = create_poll_tdata(opts, &info, opts->poll_num); + if (ret) + goto out_poll; + if (opts->is_file) { + /* in_list is created by create_send3_threads(). */ + ret = load_file_data(&info); + if (ret < 0) + goto out_buf; + ret = load_ilist(&info, model); + if (ret < 0) + goto out_buf; + } else { + if (ifl_flag) { + thread_data_t *tdata = info.tdatas; + tbuf_sz = info.in_size / EXPANSION_RATIO; + tbuf = mmap_alloc(tbuf_sz); + if (!tbuf) { + ret = -ENOMEM; + goto out_buf; + } + tlist = create_chunk_list(tbuf, tbuf_sz, + opts->block_size / + EXPANSION_RATIO); + init_chunk_list(tlist, tbuf, tbuf_sz, + opts->block_size / EXPANSION_RATIO); + gen_random_data(tbuf, tbuf_sz); + ret = sw_deflate2(tlist, tdata[0].in_list, opts); + if (ret) { + free_chunk_list(tlist); + mmap_free(tbuf, tbuf_sz); + goto out_buf; + } + free_chunk_list(tlist); + mmap_free(tbuf, tbuf_sz); + } else + gen_random_data(info.in_buf, info.in_size); + } + if (opts->faults & INJECT_TLB_FAULT) { + /* + * Now unmap the buffers and retry the access. Normally we + * should get an access fault, but if the TLB wasn't properly + * invalidated, the access succeeds and corrupts memory! + * This test requires small jobs, to make sure that we reuse + * the same TLB entry between the tests. Run for example with + * "-s 0x1000 -b 0x1000". + */ + ret = munmap(info.in_buf, info.in_size); + if (ret) { + printf("Failed to unmap."); + goto out_buf; + } + /* A warning if the parameters might produce false positives */ + if (opts->total_len > 0x54000) + fprintf(stderr, "NOTE: test might trash the TLB\n"); + } + stat_start(&info); + ret = attach2_threads(opts, &info, func, poll2_thread_func); + if (ret) + goto out_buf; + stat_end(&info); + info.stats->v[ST_IOPF] = perf_event_put(perf_fds, nr_fds); + if (opts->is_file) + store_olist(&info, model); + + usec = info.stats->v[ST_RUN_TIME] / 1000; + if (opts->op_type == WD_DIR_DECOMPRESS) + ilen = (float)count_chunk_list_sz(info.tdatas[0].out_list); + else + ilen = opts->total_len; + ilen *= opts->thread_num * opts->compact_run_num; + speed = ilen * 1000 * 1000 / 1024 / 1024 / usec; + if (opts->sync_mode) { + zbuf_idx += sprintf(zbuf + zbuf_idx, + " with %d send + %d poll threads", + opts->thread_num, + opts->poll_num); + } else { + zbuf_idx += sprintf(zbuf + zbuf_idx, + " with %d send threads", + opts->thread_num); + } + if (!strcmp(model, "hw_dfl_perf") || !strcmp(model, "hw_ifl_perf") || + !strcmp(model, "hw_dfl_perf3") || !strcmp(model, "hw_ifl_perf3")) { + printf("%s at %.2fMB/s in %f usec (BLK:%d, Bnum:%d).\n", + zbuf, speed, usec, opts->block_size, opts->batch_num); + } else { + printf("%s in %f usec (BLK:%d, Bnum:%d).\n", + zbuf, usec, opts->block_size, opts->batch_num); + } + free2_threads(&info); + if (opts->use_env) + wd_comp_env_uninit(); + else + nonenv_resource_uninit(opts, &info, sched); + usleep(1000); + return 0; +out_buf: +out_poll: + free2_threads(&info); + if (opts->use_env) + wd_comp_env_uninit(); + else + nonenv_resource_uninit(opts, &info, sched); + printf("Fail to run %s() (%d)!\n", model, ret); + return ret; +out_send: + mmap_free(info.in_buf, info.in_size); +out_src: + if (opts->use_env) + wd_comp_env_uninit(); + else + nonenv_resource_uninit(opts, &info, sched); +out: + printf("Fail to run %s() (%d)!\n", model, ret); + return ret; +} + +int run_self_test(struct test_options *opts) +{ + int i, f_ret = 0; + char poll_str[POLL_STRING_LEN]; + + printf("Start to run self test!\n"); + opts->alg_type = WD_ZLIB; + opts->data_fmt = WD_FLAT_BUF; + opts->sync_mode = 0; + opts->q_num = 16; + for (i = 0; i < 10; i++) { + opts->sync_mode = 0; + switch (i) { + case 0: + opts->thread_num = 1; + break; + case 1: + opts->thread_num = 2; + break; + case 2: + opts->thread_num = 4; + break; + case 3: + opts->thread_num = 8; + break; + case 4: + opts->thread_num = 16; + break; + case 5: + opts->thread_num = 1; + opts->is_stream = 1; + break; + case 6: + opts->thread_num = 2; + opts->is_stream = 1; + break; + case 7: + opts->thread_num = 4; + opts->is_stream = 1; + break; + case 8: + opts->thread_num = 8; + opts->is_stream = 1; + break; + case 9: + opts->thread_num = 16; + opts->is_stream = 1; + break; + } + f_ret |= test_hw(opts, "hw_dfl_perf"); + f_ret |= test_hw(opts, "hw_ifl_perf"); + } + opts->is_stream = 0; /* restore to BLOCK mode */ + for (i = 0; i < 5; i++) { + opts->thread_num = 8; + switch (i) { + case 0: + opts->sync_mode = 0; + break; + case 1: + opts->sync_mode = 1; opts->poll_num = 1; + break; + case 2: + opts->sync_mode = 1; opts->poll_num = 2; + break; + case 3: + opts->sync_mode = 1; opts->poll_num = 4; + break; + case 4: + opts->sync_mode = 1; opts->poll_num = 8; + break; + default: + return -EINVAL; + } + if (opts->use_env && opts->poll_num) { + memset(poll_str, 0, POLL_STRING_LEN); + sprintf(poll_str, + "sync-comp:8@0,sync-decomp:8@0," + "async-comp:8@0,async-decomp:8@0"); + setenv("WD_COMP_CTX_NUM", poll_str, 1); + memset(poll_str, 0, POLL_STRING_LEN); + sprintf(poll_str, "%d@0", opts->poll_num), + setenv("WD_COMP_ASYNC_POLL_NUM", poll_str, 1); + } + f_ret |= test_hw(opts, "sw_dfl_hw_ifl"); + f_ret |= test_hw(opts, "hw_dfl_sw_ifl"); + f_ret |= test_hw(opts, "hw_dfl_hw_ifl"); + f_ret |= test_hw(opts, "hw_dfl_perf"); + f_ret |= test_hw(opts, "hw_ifl_perf"); + } + if (!f_ret) + printf("Run self test successfully!\n"); + return f_ret; +} + +static int set_default_opts(struct test_options *opts) +{ + if (!opts->block_size) + opts->block_size = 8192; + if (!opts->total_len) { + if (opts->block_size) + opts->total_len = opts->block_size * 10; + else + opts->total_len = 8192 * 10; + } + if (!opts->thread_num) + opts->thread_num = 1; + if (!opts->q_num) + opts->q_num = opts->thread_num; + if (!opts->compact_run_num) + opts->compact_run_num = 1; + if (!opts->poll_num) + opts->poll_num = 1; + if (opts->alg_type == WD_COMP_ALG_MAX) + opts->alg_type = WD_GZIP; + return 0; +} + +static int run_one_cmd(struct test_options *opts) +{ + int ret; + + if (opts->op_type == WD_DIR_COMPRESS) { + if (opts->verify) + ret = test_hw(opts, "hw_dfl_sw_ifl"); + else + ret = test_hw(opts, "hw_dfl_perf"); + } else { + if (opts->verify) + ret = test_hw(opts, "sw_dfl_hw_ifl"); + else + ret = test_hw(opts, "hw_ifl_perf"); + } + return ret; +} + +int run_cmd(struct test_options *opts) +{ + int ret = 0, i; + int nr_children = 0, status; + pid_t pid, *pids = NULL; + bool success = true; + + set_default_opts(opts); + if (opts->children) { + pids = calloc(opts->children, sizeof(pid_t)); + if (!pids) + return -ENOMEM; + for (i = 0; i < opts->children; i++) { + pid = fork(); + if (pid < 0) { + printf("cannot fork: %d\n", errno); + success = false; + break; + } else if (pid > 0) { + /* Parent */ + pids[nr_children++] = pid; + continue; + } + /* Child */ + ret = run_one_cmd(opts); + return ret; + } + for (i = 0; i < nr_children; i++) { + pid = pids[i]; + ret = waitpid(pid, &status, 0); + if (ret < 0) { + printf("wait(pid=%d) error %d\n", pid, errno); + success = false; + continue; + } + if (WIFEXITED(status)) { + ret = WEXITSTATUS(status); + if (ret) { + printf("child %d returned with %d\n", + pid, ret); + success = false; + } + } else if (WIFSIGNALED(status)) { + ret = WTERMSIG(status); + printf("child %d killed by sig %d\n", pid, ret); + success = false; + } else { + printf("unexpected status for child %d\n", pid); + success = false; + } + } + if (success == false) { + printf("Failed to run spawn test!\n"); + if (!ret) + ret = -EINVAL; + } + } else + ret = run_one_cmd(opts); + return ret; +} diff --git a/uadk/test/list_loader.py b/uadk/test/list_loader.py new file mode 100644 index 0000000..d5e1578 --- /dev/null +++ b/uadk/test/list_loader.py @@ -0,0 +1,139 @@ +#!/usr/bin/python +#-*- coding: utf-8 -*- + +import os +import os.path +import sys, getopt +import numpy as np +import tempfile + +class listcontent(object): + def __init__(self, ifile, ofile): + self.ifile_nm = ifile + self.ofile_nm = ofile + self.ifile = open(ifile, "rb") + self.ofile = open(ofile, "wb") + # addr: 8 bytes, size: 8 bytes, next: 8 bytes + #self.entry_sz = 0x18; + self.entry_addr = 0; + self.entry_size = 0; + self.entry_next = 0; + + def __del__(self): + self.ifile.close() + self.ofile.close() + + def deflate(self, olist, blk_sz): + ifile_sz = os.path.getsize(self.ifile_nm) + count = (ifile_sz + int(blk_sz) - 1) / int(blk_sz) + # Create array + data = np.ndarray(count * 3, dtype=np.uint64) + entries = data.reshape(-1, 3) + i = 0 + while i < count: + # Each block of data is stored in temporary file that is used + # by gzip. + f = tempfile.NamedTemporaryFile(delete=False) + blk = self.ifile.read(int(blk_sz)) + f.write(blk) + f.close() + of = tempfile.NamedTemporaryFile(delete=False) + of.close() + os.system("gzip -c --fast < %s > %s" % (f.name, of.name)) + if not i: + os.system("cat %s > %s" % (of.name, self.ofile_nm)) + else: + os.system("cat %s >> %s" % (of.name, self.ofile_nm)) + # entries[i][0] should be the address of output buffer. + # But the output is file now, not buffer. So fill it with + # any non-zero value. + entries[i][0] = 1 + entries[i][1] = os.path.getsize(of.name) + if i == count - 1: + entries[i][2] = 0 + else: + entries[i][2] = 1 + i += 1 + os.remove(f.name) + os.remove(of.name) + entries.tofile(olist) + + # Read block data from ifile by ilist. And inflate each block data. + def inflate(self, ilist): + self.ilist_nm = ilist + data = np.fromfile(self.ilist_nm, dtype=np.uint64) + # Each entry contains addr, size and next fields + # Convert data array into the two dimensional array + entries = data.reshape(-1, 3) + i = 0 + while i < entries.shape[0]: + # Each block of data is stored in temporary file that is used + # by gunzip. + f = tempfile.NamedTemporaryFile(delete=False) + blk = self.ifile.read(entries[i][1]) + f.write(blk) + f.close() + if not i: + os.system("gunzip < %s > %s" % (f.name, self.ofile_nm)) + else: + os.system("gunzip < %s >> %s" % (f.name, self.ofile_nm)) + os.remove(f.name) + if not entries[i][2]: + break + i += 1 + +def sw_deflate(ifile, ofile, olist, blk_sz): + dfl = listcontent(ifile, ofile) + dfl.deflate(olist, blk_sz) + +def sw_inflate(ifile, ofile, ilist): + ifl = listcontent(ifile, ofile) + ifl.inflate(ilist) + +def main(argv): + ilist = '' + olist = '' + ifile = '' + ofile = '' + blk_sz = 0 + try: + opts, args = getopt.getopt(argv, "hb:", ["ilist=","olist=","in=","out="]) + for opt, arg in opts: + if opt in ("-h"): + print('Software deflate command:') + print(' list_loader -b --in --out --olist ') + print('Software inflate command:') + print(' list_loader --in --out --ilist ') + sys.exit() + elif opt in ("-b"): + blk_sz = arg + elif opt in ("--ilist"): + if not os.path.isfile(arg): + print("File does not exist:", arg) + sys.exit(1) + ilist = arg + elif opt in ("--olist"): + olist = arg + elif opt in ("--in"): + if not os.path.isfile(arg): + print("File does not exist:", arg) + sys.exit(1) + ifile = arg + elif opt in ("--out"): + ofile = arg + except getopt.GetoptError: + # Compress source to destination file and output list file + print('Software deflate command:') + print(' list_loader -b --in --out --olist ') + # Decompress source to destination file with input list file + print('Software inflate command:') + print(' list_loader --in --out --ilist ') + sys.exit(2) + + if blk_sz: + sw_deflate(ifile, ofile, olist, blk_sz) + else: + sw_inflate(ifile, ofile, ilist) + +if __name__ == "__main__": + main(sys.argv[1:]) diff --git a/uadk/test/sanity_test.sh b/uadk/test/sanity_test.sh new file mode 100644 index 0000000..207eee5 --- /dev/null +++ b/uadk/test/sanity_test.sh @@ -0,0 +1,481 @@ +#!/bin/bash -e +# +# This is a sanity test about uadk algorithms. +# +# Before test, please build uadk and install it into system according to the +# steps in INSTALL doc. +# +# Please feel free to add more basic tests. +# +# If user doesn't install the binaries, libraries and head files into the +# configed path, user must specify path in this way. +# +# $sudo LD_LIBRARY_PATH={library path} PATH={bin path} \ +# C_INCLUDE_PATH={head path} sanity_test.sh + +#VALGRIND=valgrind + +have_hisi_zip=0 +have_hisi_sec=0 +have_hisi_hpre=0 +zip_result=-1 +sec_result=-1 +hpre_result=-1 + +RM="rm" +CP="cp" +CHMOD="chmod" + +# arg1: zip/sec/hpre +# Return UACCE mode. Return -1 if UACCE module is invalid. +check_uacce_mode() +{ + case $1 in + "zip") + if [ ! -f "/sys/module/hisi_zip/parameters/uacce_mode" ]; then + mode=-1 + else + mode=`cat /sys/module/hisi_zip/parameters/uacce_mode` + fi + ;; + "sec") + if [ ! -f "/sys/module/hisi_sec2/parameters/uacce_mode" ]; then + mode=-1 + else + mode=`cat /sys/module/hisi_sec2/parameters/uacce_mode` + fi + ;; + "hpre") + if [ ! -f "/sys/module/hisi_hpre/parameters/uacce_mode" ]; then + mode=-1 + else + mode=`cat /sys/module/hisi_hpre/parameters/uacce_mode` + fi + ;; + *) + mode=-1 + ;; + esac + return $mode +} + +run_cmd() +{ + exit_code=0 + if [ -z ${VALGRIND} ]; then + # "|| exit_code=$?" is used to capature the return value. + # It could prevent bash to stop scripts when error occurs. + $@ &> /dev/null || exit_code=$? + else + ${VALGRIND} $@ + fi + return $exit_code +} + +run_zip_test_v1() +{ + dd if=/dev/urandom of=origin bs=512K count=1 >& /dev/null + run_cmd test_hisi_zip -z < origin > hw.zlib + + dd if=/dev/urandom of=origin bs=512K count=1 >& /dev/null + run_cmd test_hisi_zip -g < origin > hw.gz +} + +# arg1: source file, arg2: destination file, arg3: algorithm type +hw_blk_deflate() +{ + case $3 in + "gzip") + ${RM} -f /tmp/gzip_list.bin + zip_sva_perf --in $1 --out $2 --olist /tmp/gzip_list.bin $@ + ;; + "zlib") + zip_sva_perf -z --in $1 --out $2 --olist /tmp/zlib_list.bin $@ + ;; + *) + echo "Unsupported algorithm type: $3" + return -1 + ;; + esac +} + +# arg1: source file, arg2: destination file, arg3: algorithm type +hw_blk_inflate() +{ + case $3 in + "gzip") + zip_sva_perf -d --in $1 --out $2 --ilist /tmp/gzip_list.bin $@ + ;; + "zlib") + zip_sva_perf -z -d --in $1 --out $2 --ilist /tmp/zlib_list.bin $@ + ;; + *) + echo "Unsupported algorithm type: $3" + return -1 + ;; + esac +} + +# arg1: source file, arg2: destination file, arg3: algorithm type +hw_strm_deflate() +{ + case $3 in + "gzip") + zip_sva_perf -S --in $1 --out $2 $@ + ;; + "zlib") + zip_sva_perf -z -S --in $1 --out $2 $@ + ;; + *) + echo "Unsupported algorithm type: $3" + return -1 + ;; + esac +} + +# arg1: source file, arg2: destination file, arg3: algorithm type +hw_strm_inflate() +{ + case $3 in + "gzip") + zip_sva_perf -S -d --in $1 --out $2 $@ + ;; + "zlib") + zip_sva_perf -z -S -d --in $1 --out $2 $@ + ;; + *) + echo "Unsupported algorithm type: $3" + return -1 + ;; + esac +} + +# arg1: source file, arg2: destination file, arg3: algorithm type, +# arg4: block size +sw_blk_deflate() +{ + case $3 in + "gzip") + ${RM} -f /tmp/gzip_list.bin + python test/list_loader.py --in $1 --out $2 --olist /tmp/gzip_list.bin -b $4 + ;; + *) + echo "Unsupported algorithm type: $3" + return -1 + ;; + esac +} + +# arg1: source file, arg2: destination file, arg3: algorithm type +sw_blk_inflate() +{ + case $3 in + "gzip") + python test/list_loader.py --in $1 --out $2 --ilist /tmp/gzip_list.bin + ;; + *) + echo "Unsupported algorithm type: $3" + return -1 + ;; + esac +} + +# arg1: source file, arg2: destination file, arg3: algorithm type +sw_strm_deflate() +{ + case $3 in + "gzip") + gzip -c --fast < $1 > $2 || exit_code=$? + ;; + *) + echo "Unsupported algorithm type: $3" + return -1 + ;; + esac +} + +# arg1: source file, arg2: destination file, arg3: algorithm type +sw_strm_inflate() +{ + case $3 in + "gzip") + gunzip < $1 > $2 || exit_code=$? + ;; + *) + echo "Unsupported algorithm type: $3" + return -1 + ;; + esac +} + +# arg1: random, arg2: indicates X MB of random file +# arg1: existed file name +prepare_src_file() +{ + case $1 in + "random") + dd if=/dev/urandom of=origin bs=1M count=$2 &> /dev/null + ;; + *) + ${CP} $1 origin + ${CHMOD} 777 origin + ;; + esac +} + +# arg1: existed text file +hw_dfl_sw_ifl() +{ + ${RM} -f origin /tmp/ori.gz ori.md5 + echo "hardware compress with gzip format and software decompress:" + # Generate random data with 1MB size + echo "with 1MB random data" + prepare_src_file random 1 + md5sum origin > ori.md5 + + hw_blk_deflate origin /tmp/ori.gz gzip -b 8192 --env + sw_blk_inflate /tmp/ori.gz origin gzip + md5sum -c ori.md5 + + ${RM} -f /tmp/ori.gz + hw_strm_deflate origin /tmp/ori.gz gzip -b 8192 --env + sw_strm_inflate /tmp/ori.gz origin gzip + md5sum -c ori.md5 + + # Generate random data with 500MB size + echo "with 500MB random data" + prepare_src_file random 500 + md5sum origin > ori.md5 + + ${RM} -f /tmp/ori.gz + hw_strm_deflate origin /tmp/ori.gz gzip -b 8192 --env + sw_strm_inflate /tmp/ori.gz origin gzip + md5sum -c ori.md5 + + # Use existed text file. It's not in alignment. + echo "with text file $1" + ${RM} -f origin /tmp/ori.gz ori.md5 + prepare_src_file $1 + md5sum origin > ori.md5 + + hw_blk_deflate origin /tmp/ori.gz gzip -b 8192 --env + sw_blk_inflate /tmp/ori.gz origin gzip + md5sum -c ori.md5 + + # This case fails. + ${RM} -f /tmp/ori.gz + hw_strm_deflate origin /tmp/ori.gz gzip -b 8192 --env + sw_strm_inflate /tmp/ori.gz origin gzip + md5sum -c ori.md5 +} + +# arg1: existed text file +sw_dfl_hw_ifl() +{ + ${RM} -f origin /tmp/ori.gz ori.md5 + echo "gzip compress and hardware decompress:" + # Generate random data with 1MB size + echo "with 1MB random data" + prepare_src_file random 1 + md5sum origin > ori.md5 + + # Only gzip compress and hardware decompress + sw_blk_deflate origin /tmp/ori.gz gzip 8192 + hw_blk_inflate /tmp/ori.gz origin gzip -b 8192 + md5sum -c ori.md5 + hw_blk_inflate /tmp/ori.gz origin gzip -b 8192 --env + md5sum -c ori.md5 + + sw_strm_deflate origin /tmp/ori.gz gzip 8192 + hw_strm_inflate /tmp/ori.gz origin gzip -b 8192 --env + md5sum -c ori.md5 + + # Generate random data with 500MB size + echo "with 500MB random data" + prepare_src_file random 500 + md5sum origin > ori.md5 + + ${RM} -f /tmp/ori.gz + sw_strm_deflate origin /tmp/ori.gz gzip 8192 + hw_strm_inflate /tmp/ori.gz origin gzip -b 8192 --env + md5sum -c ori.md5 + + # Use existed text file. It's not in alignment. + echo "with text file $1" + ${RM} -f origin /tmp/ori.gz ori.md5 + prepare_src_file $1 + md5sum origin > ori.md5 + + sw_blk_deflate origin /tmp/ori.gz gzip 8192 + hw_blk_inflate /tmp/ori.gz origin gzip -b 8192 --env + md5sum -c ori.md5 + + sw_strm_deflate origin /tmp/ori.gz gzip 8192 + hw_strm_inflate /tmp/ori.gz origin gzip -b 8192 --env + md5sum -c ori.md5 +} + +# arg1: existed text file +hw_dfl_hw_ifl() +{ + ${RM} -f origin /tmp/ori.gz ori.md5 + echo "hardware compress and hardware decompress:" + # Generate random data with 1MB size + echo "with 1MB random data" + prepare_src_file random 1 + md5sum origin > ori.md5 + + hw_blk_deflate origin /tmp/ori.gz gzip -b 8192 + hw_blk_inflate /tmp/ori.gz origin gzip -b 8192 + md5sum -c ori.md5 + + ${RM} -f /tmp/ori.gz + hw_strm_deflate origin /tmp/ori.gz gzip -b 8192 + hw_strm_inflate /tmp/ori.gz origin gzip -b 8192 + md5sum -c ori.md5 + + # Use existed text file. It's not in alignment. + echo "with text file $1" + ${RM} -f origin /tmp/ori.gz ori.md5 + prepare_src_file $1 + md5sum origin > ori.md5 + + hw_blk_deflate origin /tmp/ori.gz gzip -b 8192 + hw_blk_inflate /tmp/ori.gz origin gzip -b 8192 + md5sum -c ori.md5 + + ${RM} -f /tmp/ori.gz + hw_strm_deflate origin /tmp/ori.gz gzip -b 8192 + hw_strm_inflate /tmp/ori.gz origin gzip -b 8192 + md5sum -c ori.md5 +} + +# failed: return 1; success: return 0 +run_zip_test_v2() +{ + export WD_COMP_CTX_NUM="sync-comp:4@0,sync-decomp:4@0,async-comp:4@0,async-decomp:4@0" + export WD_COMP_ASYNC_POLL_EN=1 + export WD_COMP_ASYNC_POLL_NUM="4@0" + # test without environment variables + # limit test file in 64MB + rm -fr /tmp/syslog + dd if=/var/log/syslog of=/tmp/syslog bs=1M count=16 >& /dev/null + sw_dfl_hw_ifl /tmp/syslog + hw_dfl_sw_ifl /tmp/syslog + WD_COMP_EPOLL_EN=1 hw_dfl_hw_ifl /tmp/syslog + WD_COMP_EPOLL_EN=0 hw_dfl_hw_ifl /tmp/syslog + # test without environment variables + #zip_sva_perf -b 8192 -s 81920 -l 1000 --self + # test with environment variables + #zip_sva_perf -b 8192 -s 81920 -l 1000 --self --env +} + +# Accept more paraterms +# failed: return 1; success: return 0 +run_sec_test_v2() +{ + run_cmd test_hisi_sec --cipher 0 --optype 0 --pktlen 16 --keylen 16 \ + --times 1 --sync --multi 1 $@ + + run_cmd test_hisi_sec --cipher 0 --optype 0 --pktlen 16 --keylen 16 \ + --times 1 --async --multi 1 $@ + + run_cmd test_hisi_sec --digest 0 --optype 0 --pktlen 16 --keylen 16 \ + --times 1 --sync --multi 1 $@ + + run_cmd test_hisi_sec --digest 0 --optype 0 --pktlen 16 --keylen 16 \ + --times 1 --async --multi 1 $@ +} + +# failed: return 1; success: return 0 +run_hpre_test_v2() +{ + run_cmd test_hisi_hpre --trd_mode=sync + + run_cmd test_hisi_hpre --trd_mode=async +} + +# failed: return 1; success: return 0 +output_result() +{ + echo "test result:" + if [ $have_hisi_zip -eq 0 ]; then + echo "---> hisi_zip device is not existed!" + fi + + if [ $have_hisi_sec -eq 0 ]; then + echo "---> hisi_sec device is not existed!" + fi + + if [ $have_hisi_hpre -eq 0 ]; then + echo "---> hisi_hpre device is not existed!" + fi + + if [ $zip_result == 1 ]; then + echo "---> hisi_zip test is failed!" + fi + + if [ $sec_result == 1 ]; then + echo "---> hisi_sec test is failed!" + fi + + if [ $hpre_result == 1 ]; then + echo "---> hisi_hpre test is failed!" + fi + + if [ $zip_result -ne 1 -a $sec_result -ne 1 -a $hpre_result -ne 1 ]; then + echo "===> tests for exited device are all passed!" + return 0 + fi + + return 1 +} + +# start to test +find /dev -name hisi_zip-* &> /dev/null +if [ $? -eq 0 ]; then + chmod 666 /dev/hisi_zip-* + have_hisi_zip=1 + check_uacce_mode zip || exit_code=$? + if [ $exit_code -eq 1 ]; then + run_zip_test_v2 + zip_result=$? + else + run_zip_test_v1 + zip_result=$? + fi +fi + +find /dev -name hisi_sec2-* &> /dev/null +if [ $? -eq 0 ]; then + chmod 666 /dev/hisi_sec2-* + have_hisi_sec=1 + check_uacce_mode sec || exit_code=$? + if [ $exit_code -eq 1 ]; then + # Run without sglnum parameter + run_sec_test_v2 + sec_result=$? + # Re-run with sglnum parameter + run_sec_test_v2 --sglnum=2 + sec_result=$? + else + # Skip to test sec temporarily + sec_result=0 + fi +fi + +find /dev -name hisi_hpre-* &> /dev/null +if [ $? -eq 0 ]; then + chmod 666 /dev/hisi_hpre-* + have_hisi_hpre=1 + check_uacce_mode hpre || exit_code=$? + if [ $exit_code -eq 1 ]; then + run_hpre_test_v2 + hpre_result=$? + else + # Skip to test sec temporarily + hpre_result=0 + fi +fi + +output_result diff --git a/uadk/test/wd_mempool_test.c b/uadk/test/wd_mempool_test.c new file mode 100644 index 0000000..cf6be70 --- /dev/null +++ b/uadk/test/wd_mempool_test.c @@ -0,0 +1,989 @@ +/* + * We consider three problems: 1. Rate of memory usage; + * 2. performance of alloc/free; 3. memory fragmentation. + * + * 1. mempool create from huge page + * 2. mempool create from mmap + pin + * + * 3. mempool create from huge page, blk pool small block size + * 4. mempool create from huge page, blk pool big block size + * + * 5. mempool create from mmap + pin, blk pool small block size + * 6. mempool create from mmap + pin, blk pool big block size + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hisi_sec_test/test_hisi_sec.h" +#include "wd.h" +#include "wd_cipher.h" +#include "wd_sched.h" + +#define WD_MEM_MAX_THREAD 20 +#define WD_MEM_MAX_BUF_SIZE 256 + +#define SEC_TST_PRT printf +#define HW_CTX_SIZE (24 * 1024) +#define BUFF_SIZE 1024 +#define IV_SIZE 256 +#define THREADS_NUM 64 +#define SVA_THREADS 64 +#define USE_CTX_NUM 64 +#define BYTES_TO_MB 20 + +#define SCHED_SINGLE "sched_single" +#define SCHED_NULL_CTX_SIZE 4 +#define TEST_WORD_LEN 4096 +#define MAX_ALGO_PER_TYPE 12 +#define MIN_SVA_BD_NUM 1 + +static struct wd_ctx_config g_ctx_cfg; + +static long long int g_times; +static unsigned int g_thread_num; +static unsigned int g_blknum; +static unsigned int g_syncmode; +static unsigned int g_ctxnum; +static pthread_spinlock_t lock = 0; +static __u32 last_ctx = 0; + +struct test_option { + unsigned long mp_size; + int node; + unsigned long blk_size[WD_MEM_MAX_THREAD]; + unsigned long blk_num[WD_MEM_MAX_THREAD]; + unsigned long sleep_value[WD_MEM_MAX_THREAD]; + unsigned long perf; + unsigned thread_num; + __u32 algclass; + __u32 algtype; + __u32 optype; + __u32 pktlen; + __u32 keylen; + __u32 times; + __u32 syncmode; + __u32 xmulti; + __u32 ctxnum; + __u32 block; + __u32 blknum; +}; + +struct sva_bd { + char *src; + char *dst; +}; + +struct sva_bd_pool { + struct sva_bd *bds; +}; + +struct test_opt_per_thread { + unsigned long mp_size; + int tid; + int flag; + int mode; + int cpu_id; + int node; + unsigned long blk_size; + unsigned long blk_num; + unsigned long sleep_value; + unsigned thread_num; + struct wd_cipher_req *req; + struct wd_cipher_sess_setup *setup; + struct timeval start_tval; + unsigned long long send_task_num; + unsigned long long recv_task_num; + struct sva_bd_pool *bd_pool; + + handle_t mp, bp; +}; + +static pthread_t system_test_thrds[THREADS_NUM]; +static struct test_opt_per_thread thr_data[THREADS_NUM]; + +static void show_help(void) +{ + printf(" --mp_size mempool size\n" + " --node numa node of mempool\n" + " --blk_size_array <\"size1 size2 ...\">\n" + " size of each block pool\n" + " --blk_num_array <\"num1 num2 ...\">\n" + " block num of each block pool\n" + " --sleep_value <\"value1 value2 ...\">\n" + " test thread will sleep some time between\n" + " allocating and freeing memory, these values\n" + " are for this purpose\n" + " --perf 0 for mempool, 1 for block pool, 2 for sec's alg perf\n" + " --multi pthread num\n" + " --times if perf is 2, this is times for sec's alg in every pthread\n" + " --ctxnum ctx num\n" + " in blkpool\n" + " --path file's path\n" + " --help show this help\n"); +} + +static int parse_value_in_string(unsigned long *array, unsigned long num, + char *string) +{ + char str[WD_MEM_MAX_BUF_SIZE]; + char *tmp, *str_t; + int i = 0; + + strncpy(str, string, WD_MEM_MAX_BUF_SIZE - 1); + str[WD_MEM_MAX_BUF_SIZE - 1] = '\0'; + str_t = str; + + while ((tmp = strtok(str_t, " ")) && i < num) { + array[i++] = strtol(tmp, NULL, 0); + str_t = NULL; + } + + if (i == num) { + WD_ERR("Input parameter more than %lu\n", num); + return -1; + } + + return 0; +} + +void dump_parse(struct test_option *opt) +{ + int i; + char perf_str[3][16] = {"mempool test", "blkpool test", "perf test"}; + + printf("---------------------------------------\n"); + printf(" This is %s\n", perf_str[opt->perf]); + printf(" mp_size: %lu\n", opt->mp_size); + printf(" node: %d\n", opt->node); + printf(" thread_num: %u\n\n", g_thread_num); + for (i = 0; i < g_thread_num; i++) { + printf(" pthread %d:", i + 1); + printf("blk_size-%lu ", opt->blk_size[i]); + printf("blk_num-%lu ", opt->blk_num[i]); + printf("sleep_value-%lu\n", opt->sleep_value[i]); + } + + printf("---------------------------------------\n"); +} + +static int test_sec_option_convert(struct test_option *option); + +static int parse_cmd_line(int argc, char *argv[], struct test_option *opt) +{ + int option_index = 0; + int c, ret; + + static struct option long_options[] = { + {"mp_size", required_argument, 0, 1}, + {"node", required_argument, 0, 2}, + {"blk_size_array", required_argument, 0, 3}, + {"blk_num_array", required_argument, 0, 4}, + {"sleep_value", required_argument, 0, 5}, + {"perf", required_argument, 0, 6}, + {"multi", required_argument, 0, 7}, + {"times", required_argument, 0, 8}, + {"sync", no_argument, 0, 9}, + {"async", no_argument, 0, 10}, + {"ctxnum", required_argument, 0, 11}, + {"help", no_argument, 0, 12}, + {0, 0, 0, 0} + }; + + + opt->syncmode = 0; + while (1) { + c = getopt_long(argc, argv, "", long_options, &option_index); + if (c == -1) + break; + + switch (c) { + case 1: + opt->mp_size = strtol(optarg, NULL, 0); + break; + case 2: + opt->node = strtol(optarg, NULL, 0); + break; + case 3: + parse_value_in_string(opt->blk_size, WD_MEM_MAX_THREAD, + optarg); + break; + case 4: + parse_value_in_string(opt->blk_num, WD_MEM_MAX_THREAD, + optarg); + break; + case 5: + parse_value_in_string(opt->sleep_value, + WD_MEM_MAX_THREAD, optarg); + break; + case 6: + opt->perf = strtol(optarg, NULL, 0); + break; + case 7: + opt->xmulti = strtol(optarg, NULL, 0); + break; + case 8: + opt->times = strtol(optarg, NULL, 0); + break; + case 9: + opt->syncmode = 0; + break; + case 10: + opt->syncmode = 1; + break; + case 11: + opt->ctxnum = strtol(optarg, NULL, 0); + break; + case 12: + show_help(); + return -1; + default: + printf("bad input parameter, exit\n"); + show_help(); + return -1; + } + } + + ret = test_sec_option_convert(opt); + if (ret) + return ret; + + dump_parse(opt); + return 0; +} + +static void dump_mp_bp(struct wd_mempool_stats *mp_s, struct wd_blockpool_stats *bp_s) +{ + printf("---------------------------------------\n"); + printf("dump mp bp info:\n"); + printf("mp page_type : %s\n", mp_s->page_type ? "pin" : "hugepage"); + printf("mp page_size : %lu\n", mp_s->page_size); + printf("mp page_num : %lu\n", mp_s->page_num); + printf("mp blk_size : %lu\n", mp_s->blk_size); + printf("mp blk_num : %lu\n", mp_s->blk_num); + printf("mp free_blk_num : %lu\n", mp_s->free_blk_num); + printf("mp blk_usage_rate : %lu%%\n\n", mp_s->blk_usage_rate); + + printf("bp block_size : %lu\n", bp_s->block_size); + printf("bp block_num : %lu\n", bp_s->block_num); + printf("bp free_block_num : %lu\n", bp_s->free_block_num); + printf("bp block_usage_rate : %lu%%\n", bp_s->block_usage_rate); + printf("bp mem_waste_rate : %lu%%\n\n", bp_s->mem_waste_rate); + printf("---------------------------------------\n"); +} + +void *alloc_free_thread(void *data) +{ + struct test_opt_per_thread *opt = data; + int i, j; + char *p; + + /* fix me: temporarily make iterate num to 100 */ + for (i = 0; i < 100; i++) { + p = wd_block_alloc(opt->bp); + if (!p) { + printf("Fail to alloc mem\n"); + } + + for (j = 0; j < 10; j++) { + *(p + j) = 8; + } + + sleep(opt->sleep_value); + + wd_block_free(opt->bp, p); + } + + printf("alloc_free_thread successful\n"); + return NULL; +} + +static int test_blkpool(struct test_option *opt) +{ + struct test_opt_per_thread per_thread_opt[WD_MEM_MAX_THREAD] = {{0}}; + pthread_t threads[WD_MEM_MAX_THREAD]; + int i, bp_thread_num = g_thread_num; + handle_t mp, bp; + + mp = wd_mempool_create(opt->mp_size, opt->node); + if (WD_IS_ERR(mp)) { + printf("Fail to create mempool, err(%lld)!\n", WD_HANDLE_ERR(mp)); + return -1; + } + + bp = wd_blockpool_create(mp, opt->blk_size[0], opt->blk_num[0]); + if (WD_IS_ERR(bp)) { + printf("Fail to create blkpool, err(%lld)!\n", WD_HANDLE_ERR(bp)); + return -1; + } + + for (i = 0; i < bp_thread_num; i++) { + per_thread_opt[i].mp = mp; + per_thread_opt[i].bp = bp; + per_thread_opt[i].sleep_value = opt->sleep_value[i]; + + pthread_create(&threads[i], NULL, alloc_free_thread, + &per_thread_opt[i]); + } + + for (i = 0; i < bp_thread_num; i++) { + pthread_join(threads[i], NULL); + } + + wd_blockpool_destroy(bp); + wd_mempool_destroy(mp); + + return 0; +} + +void *blk_test_thread(void *data) +{ + struct test_opt_per_thread *opt = data; + struct wd_blockpool_stats bp_stats = {0}; + struct wd_mempool_stats mp_stats = {0}; + handle_t mp, bp; + + mp = wd_mempool_create(opt->mp_size, opt->node); + if (WD_IS_ERR(mp)) { + printf("Fail to create mempool, err %lld\n", WD_HANDLE_ERR(mp)); + return (void *)-1; + } + + bp = wd_blockpool_create(mp, opt->blk_size, opt->blk_num); + if (WD_IS_ERR(bp)) { + printf("Fail to create blkpool, err %lld\n", WD_HANDLE_ERR(bp)); + return (void *)-1; + } + + + char *block = wd_block_alloc(bp); + if (!block) { + printf("Fail to alloc block\n"); + return (void *)-1; + } + + int i, j; + j = opt->blk_size / 10; + for (i = 0;i < j;i++) + strcpy(block + i * 10, "xaaxaaxaax"); + + printf("please check memory about numa, input any key and Entry key then go on:"); + j = scanf("%d", &i); + + sleep(opt->sleep_value); + /* fix me: need a opt? */ + if (1) { + wd_mempool_stats(mp, &mp_stats); + wd_blockpool_stats(bp, &bp_stats); + dump_mp_bp(&mp_stats, &bp_stats); + } + + wd_block_free(bp, block); + wd_blockpool_destroy(bp); + wd_mempool_destroy(mp); + + printf("test mempool successful!\n"); + return NULL; +} + +static int test_mempool(struct test_option *opt) +{ + struct test_opt_per_thread per_thread_opt[WD_MEM_MAX_THREAD] = {{0}}; + pthread_t threads[WD_MEM_MAX_THREAD]; + int i, bp_thread_num = g_thread_num; + + printf("mempool(thread_num=%d) is testing...\n", bp_thread_num); + + for (i = 0; i < bp_thread_num; i++) { + per_thread_opt[i].mp_size = opt->mp_size; + per_thread_opt[i].node = opt->node; + per_thread_opt[i].blk_size = opt->blk_size[i]; + per_thread_opt[i].blk_num = opt->blk_num[i]; + per_thread_opt[i].sleep_value = opt->sleep_value[i]; + + pthread_create(&threads[i], NULL, blk_test_thread, + &per_thread_opt[i]); + } + + for (i = 0; i < bp_thread_num; i++) { + pthread_join(threads[i], NULL); + } + + return 0; +} + +static handle_t sva_sched_init(handle_t h_sched_ctx, void *sched_param) +{ + return (handle_t)0; +} + +static __u32 sva_sched_pick_next_ctx(handle_t h_sched_ctx, + void *sched_key, const int sched_mode) +{ + __u32 index; + + pthread_spin_lock(&lock); + if (++last_ctx == g_ctx_cfg.ctx_num) + last_ctx = 0; + index = last_ctx; + pthread_spin_unlock(&lock); + + return index; +} + +static int sva_sched_poll_policy(handle_t h_sched_ctx, __u32 expect, + __u32 *count) +{ + int recv = 0; + int ret = 0; + __u32 cnt; + int i; + + if (unlikely(g_ctx_cfg.ctxs[0].ctx_mode != CTX_MODE_ASYNC)) { + SEC_TST_PRT("ctx mode is not AYNC!\n"); + *count = 0; + return -1; + } + + for (i = 0; i < g_ctx_cfg.ctx_num; i++) { + ret = wd_cipher_poll_ctx(i, 1, &cnt); + /* ret is 0 means no error and recv 1 finished task */ + if (!ret) + recv++; + /* here is an error, return ret and recv num currently */ + else if (ret != -EAGAIN) + break; + } + + *count = recv; + + return ret; +} + +static int sva_init_ctx_config(int type, int mode) +{ + struct uacce_dev_list *list; + struct wd_sched sched; + struct wd_ctx *ctx_attr; + int ret; + int i; + + list = wd_get_accel_list("cipher"); + if (!list) + return -ENODEV; + + memset(&g_ctx_cfg, 0, sizeof(struct wd_ctx_config)); + if (g_ctxnum > USE_CTX_NUM) + SEC_TST_PRT("ctx nums request too much!\n"); + + ctx_attr = malloc(g_ctxnum * sizeof(struct wd_ctx)); + if (!ctx_attr) { + SEC_TST_PRT("malloc ctx_attr memory fail!\n"); + return -ENOMEM; + } + memset(ctx_attr, 0, g_ctxnum * sizeof(struct wd_ctx)); + + /* Just use first found dev to test here */ + for (i = 0; i < g_ctxnum; i++) { + ctx_attr[i].ctx = wd_request_ctx(list->dev); + if (!ctx_attr[i].ctx) { + ret = -EINVAL; + SEC_TST_PRT("Fail to request ctx!\n"); + goto out; + } + ctx_attr[i].op_type = type; + ctx_attr[i].ctx_mode = mode; + } + + g_ctx_cfg.ctx_num = g_ctxnum; + g_ctx_cfg.ctxs = ctx_attr; + sched.name = "sched_multi"; + sched.pick_next_ctx = sva_sched_pick_next_ctx; + sched.poll_policy = sva_sched_poll_policy; + sched.sched_init = sva_sched_init; + /*cipher init*/ + ret = wd_cipher_init(&g_ctx_cfg, &sched); + if (ret) { + SEC_TST_PRT("Fail to cipher ctx!\n"); + goto out; + } + wd_free_list_accels(list); + + return 0; +out: + free(ctx_attr); + return ret; +} + +static void sva_uninit_config(void) +{ + int i; + + wd_cipher_uninit(); + for (i = 0; i < g_ctx_cfg.ctx_num; i++) + wd_release_ctx(g_ctx_cfg.ctxs[i].ctx); + free(g_ctx_cfg.ctxs); +} + +static void *async_cb(struct wd_cipher_req *req, void *data) +{ + return NULL; +} + +static void *sva_sec_cipher_sync(void *arg) +{ + struct test_opt_per_thread *pdata = (struct test_opt_per_thread *)arg; + struct wd_cipher_sess_setup *setup = pdata->setup; + struct wd_cipher_req *req = pdata->req; + struct cipher_testvec *tv = &aes_cbc_perf_128[0];; + struct timeval cur_tval; + unsigned long Perf = 0, pktlen; + handle_t h_sess; + float speed, time_used; + unsigned int count = 0; + int cnt = g_times; + int ret; + int j; + + gettimeofday(&pdata->start_tval, NULL); + h_sess = wd_cipher_alloc_sess(setup); + if (!h_sess) + return NULL; + + pktlen = BUFF_SIZE; + ret = wd_cipher_set_key(h_sess, (const __u8*)tv->key, tv->klen); + if (ret) { + SEC_TST_PRT("test sec cipher set key is failed!\n"); + goto out;; + } + /* run task */ + while (cnt) { + j = count % g_blknum; + req->src = pdata->bd_pool->bds[j].src; + req->dst = pdata->bd_pool->bds[j].dst; + ret = wd_do_cipher_sync(h_sess, req); + cnt--; + pdata->send_task_num++; + count++; + } + + gettimeofday(&cur_tval, NULL); + time_used = (float)((cur_tval.tv_sec - pdata->start_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - pdata->start_tval.tv_usec); + speed = pdata->send_task_num / time_used * 1000000; + Perf = speed * pktlen / 1024; //B->KB + SEC_TST_PRT("Sync Mode thread time_used:%0.0f us, Perf: %ld KB/s\n", + time_used, Perf); + +out: + wd_cipher_free_sess(h_sess); + return NULL; +} + +static int sva_sync_create_threads(int thread_num, struct wd_cipher_req *reqs, + struct wd_cipher_sess_setup *setups, struct test_opt_per_thread *tds) +{ + int thread_id = (int)syscall(__NR_gettid); + struct timeval start_tval, cur_tval; + unsigned long Perf = 0; + float speed, time_used; + pthread_attr_t attr; + int i, ret; + + if (thread_num > SVA_THREADS) { + SEC_TST_PRT("can't creat %d threads", thread_num); + return -EINVAL; + } + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + gettimeofday(&start_tval, NULL); + for (i = 0; i < thread_num; i++) { + thr_data[i].tid = i; + thr_data[i].req = &reqs[i]; + thr_data[i].setup = &setups[i]; + thr_data[i].bd_pool = tds[i].bd_pool; + ret = pthread_create(&system_test_thrds[i], &attr, + sva_sec_cipher_sync, &thr_data[i]); + if (ret) { + SEC_TST_PRT("Failed to create thread, ret:%d\n", ret); + return ret; + } + } + + thr_data[i].tid = i; + pthread_attr_destroy(&attr); + for (i = 0; i < thread_num; i++) { + ret = pthread_join(system_test_thrds[i], NULL); + } + + gettimeofday(&cur_tval, NULL); + time_used = (double)((cur_tval.tv_sec - start_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - start_tval.tv_usec); + SEC_TST_PRT("time_used:%0.0f us, send task num:%llu\n", time_used, g_times * g_thread_num); + speed = g_times * g_thread_num / time_used * 1000000; + Perf = speed * BUFF_SIZE / 1024; //B->KB + SEC_TST_PRT("Sync mode avg Pro-%d, thread_id-%d, speed:%f ops, Perf: %ld KB/s\n", + getpid(), thread_id, speed, Perf); + + return 0; +} + +static void *sva_sec_cipher_async(void *arg) +{ + struct test_opt_per_thread *pdata = (struct test_opt_per_thread *)arg; + struct wd_cipher_sess_setup *setup = pdata->setup; + struct wd_cipher_req *req = pdata->req; + struct cipher_testvec *tv = &aes_cbc_perf_128[0];; + unsigned int count = 0; + int cnt = g_times; + handle_t h_sess; + int ret; + int j, i; + + setup->alg = WD_CIPHER_AES; + setup->mode = WD_CIPHER_CBC; + + h_sess = wd_cipher_alloc_sess(setup); + if (!h_sess) + return NULL; + + ret = wd_cipher_set_key(h_sess, (const __u8*)tv->key, tv->klen); + if (ret) { + SEC_TST_PRT("test sec cipher set key is failed!\n"); + goto out;; + } + i = cnt; + /* run task */ + do { +try_do_again: + j = count % g_blknum; + req->src = pdata->bd_pool->bds[j].src; + req->dst = pdata->bd_pool->bds[j].dst; + ret = wd_do_cipher_async(h_sess, req); + i--; + if (ret == -EBUSY) { // busy + usleep(100); + goto try_do_again; + } else if (ret) { + SEC_TST_PRT("test sec cipher send req is error!\n"); + goto out; + } + cnt--; + count++; + } while (cnt); + + ret = 0; +out: + wd_cipher_free_sess(h_sess); + return NULL; +} + +static void *sva_poll_func(void *arg) +{ + __u32 count = 0; + __u32 recv = 0; + int ret; + + int expt = g_times * g_thread_num; + + while (1) { + ret = wd_cipher_poll(1, &count); + if (ret < 0 && ret != -EAGAIN) { + SEC_TST_PRT("poll ctx recv: %u\n", recv); + break; + } + + recv += count; + if (expt == recv) { + break; + } + } + + pthread_exit(NULL); + return NULL; +} + +static int sva_async_create_threads(int thread_num, struct wd_cipher_req *reqs, + struct wd_cipher_sess_setup *setups, struct test_opt_per_thread *tds) +{ + int thread_id = (int)syscall(__NR_gettid); + struct timeval start_tval, cur_tval; + unsigned long Perf = 0; + float speed, time_used; + pthread_attr_t attr; + int i, ret; + + if (thread_num > SVA_THREADS) { + SEC_TST_PRT("can't creat %d threads", thread_num); + return -EINVAL; + } + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + gettimeofday(&start_tval, NULL); + for (i = 0; i < thread_num; i++) { + thr_data[i].tid = i; + thr_data[i].req = &reqs[i]; + thr_data[i].setup = &setups[i]; + thr_data[i].bd_pool = tds[i].bd_pool; + ret = pthread_create(&system_test_thrds[i], &attr, sva_sec_cipher_async, &thr_data[i]); + if (ret) { + SEC_TST_PRT("Failed to create thread, ret:%d\n", ret); + return ret; + } + } + + ret = pthread_create(&system_test_thrds[i], &attr, sva_poll_func, NULL); + if (ret) { + SEC_TST_PRT("Failed to create poll thread, ret:%d\n", ret); + return ret; + } + pthread_attr_destroy(&attr); + for (i = 0; i < thread_num; i++) { + ret = pthread_join(system_test_thrds[i], NULL); + if (ret) { + SEC_TST_PRT("Join %dth thread fail!\n", i); + return ret; + } + } + // asyn_thread_exit = 1; + ret = pthread_join(system_test_thrds[i], NULL); + if (ret) { + SEC_TST_PRT("Join %dth thread fail!\n", i); + return ret; + } + + gettimeofday(&cur_tval, NULL); + time_used = (double)((cur_tval.tv_sec - start_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - start_tval.tv_usec); + SEC_TST_PRT("time_used:%0.0f us, send task num:%llu\n", time_used, g_times * g_thread_num); + speed = g_times * g_thread_num / time_used * 1000000; + Perf = speed * BUFF_SIZE / 1024; //B->KB + SEC_TST_PRT("Async mode Pro-%d, thread_id-%d, speed:%f ops, Perf: %ld KB/s\n", + getpid(), thread_id, speed, Perf); + + return 0; +} + + +int init_bd_pool(struct test_opt_per_thread *td) +{ + struct cipher_testvec *tv = &aes_cbc_perf_128[0]; + int i, j = 0; + + td->bd_pool = malloc(sizeof(struct sva_bd_pool)); + if (!td->bd_pool) { + SEC_TST_PRT("init bd pool alloc thread failed!\n"); + return -ENOMEM; + } + td->bd_pool->bds = malloc(g_times * sizeof(struct sva_bd)); + if (!td->bd_pool->bds) { + SEC_TST_PRT("init bd pool bds alloc thread failed!\n"); + free(td->bd_pool); + return -ENOMEM; + } + + for (i = 0; i < g_times; i++) { + td->bd_pool->bds[i].src = wd_block_alloc(td->bp); + if (!td->bd_pool->bds[i].src) { + SEC_TST_PRT("block(%u) fail to alloc src mem!!\n", i); + goto src_fail; + } + + td->bd_pool->bds[i].dst = wd_block_alloc(td->bp); + if (!td->bd_pool->bds[i].dst) { + SEC_TST_PRT("block(%u) fail to alloc dst mem!!\n", i); + goto dst_fail; + } + memcpy(td->bd_pool->bds[i].src, tv->ptext, tv->len); + } + + return 0; + +src_fail: + for (j = 0;j < i; j++) { + wd_block_free(td->bp, td->bd_pool->bds[i].dst); +dst_fail: + wd_block_free(td->bp, td->bd_pool->bds[i].src); + } + free(td->bd_pool->bds); + free(td->bd_pool); + + return -ENOMEM; +} + +void free_bd_pool(struct test_opt_per_thread *td) +{ + int i; + + for (i = 0; i < g_times; i++) { + wd_block_free(td->bp, td->bd_pool->bds[i].dst); + wd_block_free(td->bp, td->bd_pool->bds[i].src); + } + + free(td->bd_pool->bds); + free(td->bd_pool); +} + +static int test_sec_perf(struct test_option *opt) +{ + struct test_opt_per_thread datas[WD_MEM_MAX_THREAD] = {{0}}; + struct wd_cipher_sess_setup setup[WD_MEM_MAX_THREAD]; + struct wd_cipher_req req[WD_MEM_MAX_THREAD]; + struct cipher_testvec *tv = &aes_cbc_perf_128[0]; + handle_t mp; + int i; + int ret = 0; + + int bp_thread_num = g_thread_num; + + memset(datas, 0, sizeof(struct test_opt_per_thread) * WD_MEM_MAX_THREAD); + memset(req, 0, sizeof(struct wd_cipher_req) * WD_MEM_MAX_THREAD); + memset(setup, 0, sizeof(struct wd_cipher_sess_setup) * WD_MEM_MAX_THREAD); + + if (g_syncmode == 0) + ret = sva_init_ctx_config(CTX_TYPE_ENCRYPT, CTX_MODE_SYNC); + else + ret = sva_init_ctx_config(CTX_TYPE_ENCRYPT, CTX_MODE_ASYNC); + if (ret) { + SEC_TST_PRT("fail to init ctx config!\n"); + goto init_ctx_fail; + } + + SEC_TST_PRT("test alg: %s(128)\n", "cbc(aes)"); + mp = wd_mempool_create(opt->mp_size, opt->node); + if (WD_IS_ERR(mp)) { + SEC_TST_PRT("node(%u) mem_size(%lu), fail to create memory pool, err(%lld)!\n", + opt->node, opt->mp_size, WD_HANDLE_ERR(mp)); + goto mp_fail; + } + + for (i = 0; i < bp_thread_num; i++) { + datas[i].bp = wd_blockpool_create(mp, opt->blk_size[i], opt->blk_num[i]); + if (WD_IS_ERR(datas[i].bp)) { + SEC_TST_PRT("blk_size(%lu) blk_num(%lu), thread(%u) is fail to create blk_pool, err(%lld)\n", + opt->blk_size[i], opt->blk_num[i], i, WD_HANDLE_ERR(datas[i].bp)); + goto bp_fail; + } + + SEC_TST_PRT("blk_size(%lu) blk_num(%lu), thread(%u) is success to create blk_pool!!\n", opt->blk_size[i], opt->blk_num[i], i); + + ret = init_bd_pool(&datas[i]); + if (ret < 0){ + SEC_TST_PRT("thread(%u) fail to alloc bd!!\n", i); + goto init_bd_pool_fail; + } + SEC_TST_PRT("thread(%u) success to alloc bd pool!!\n", i); + + req[i].src = wd_block_alloc(datas[i].bp); + if (!req[i].src) { + SEC_TST_PRT("thread(%u) fail to alloc src mem!!\n", i); + goto src_fail; + } + + memcpy(req[i].src, tv->ptext, opt->pktlen); + req[i].in_bytes = BUFF_SIZE; + + req[i].dst = wd_block_alloc(datas[i].bp); + if (!req[i].dst) { + SEC_TST_PRT("thread(%u) fail to alloc dst mem!!\n", i); + goto dst_fail; + } + req[i].out_bytes = tv->len; + req[i].out_buf_bytes = opt->blk_size[i]; + + req[i].iv = wd_block_alloc(datas[i].bp); + if (!req[i].iv) { + SEC_TST_PRT("thread(%u) fail to alloc iv mem!!\n", i); + goto iv_fail; + } + memcpy(req[i].iv, tv->iv, strlen(tv->iv)); + req[i].iv_bytes = strlen(tv->iv); + + /* config arg */ + setup[i].alg = WD_CIPHER_AES; + setup[i].mode = WD_CIPHER_CBC; + + req[i].op_type = WD_CIPHER_ENCRYPTION; + req[i].cb = async_cb; + req[i].cb_param = &datas[i]; + } + + if (g_syncmode == 0) + ret = sva_sync_create_threads(bp_thread_num, req, setup, datas); + else + ret = sva_async_create_threads(bp_thread_num, req, setup, datas); + + i--; + do { +bp_fail: + wd_block_free(datas[i].bp, req[i].iv); +iv_fail: + wd_block_free(datas[i].bp, req[i].dst); +dst_fail: + wd_block_free(datas[i].bp, req[i].src); +src_fail: + free_bd_pool(&datas[i]); +init_bd_pool_fail: + wd_blockpool_destroy(datas[i].bp); + i--; + } while(i >= 0); + + wd_mempool_destroy(mp); + +mp_fail: + sva_uninit_config(); +init_ctx_fail: + return -1; + +} + +static int test_sec_option_convert(struct test_option *option) +{ + unsigned long long sum_size = 0; + int i; + + if (option->syncmode > 1) { + show_help(); + return -EINVAL; + } + + g_times = option->times ? option->times : + (BUFF_SIZE * BUFF_SIZE); + + g_thread_num = option->xmulti ? option->xmulti : 1; + g_syncmode = option->syncmode; + g_ctxnum = option->ctxnum; + + for (i = 0;i < g_thread_num;i++) + sum_size = option->blk_size[i] * option->blk_num[i]; + + if (sum_size > option->mp_size) { + printf("Mempool size is too small!\n"); + option->mp_size = sum_size; + } + + return 0; +} +int main(int argc, char *argv[]) +{ + struct test_option opt = {0}; + int ret; + + ret = parse_cmd_line(argc, argv, &opt); + if (ret < 0) + return -1; + + if (!opt.perf) + return test_mempool(&opt); + else if (opt.perf == 1) + return test_blkpool(&opt); + else + return test_sec_perf(&opt); +} diff --git a/uadk/uadk_tool/Makefile.am b/uadk/uadk_tool/Makefile.am new file mode 100644 index 0000000..d5b125f --- /dev/null +++ b/uadk/uadk_tool/Makefile.am @@ -0,0 +1,43 @@ +ACLOCAL_AMFLAGS = -I m4 -I./include +AUTOMAKE_OPTIONS = foreign subdir-objects +AM_CFLAGS=-Wall -fno-strict-aliasing -I$(top_srcdir) -I$(top_srcdir)/benchmark/include \ + -pthread + +#AUTOMAKE_OPTIONS = subdir-objects + +bin_PROGRAMS=uadk_tool + +uadk_tool_SOURCES=uadk_tool.c dfx/uadk_dfx.c dfx/uadk_dfx.h \ + benchmark/uadk_benchmark.c benchmark/uadk_benchmark.h \ + benchmark/sec_uadk_benchmark.c benchmark/sec_uadk_benchmark.h \ + benchmark/sec_wd_benchmark.c benchmark/sec_wd_benchmark.h \ + benchmark/hpre_uadk_benchmark.c benchmark/hpre_uadk_benchmark.h \ + benchmark/hpre_wd_benchmark.c hpre_wd_benchmark.h \ + benchmark/zip_uadk_benchmark.c benchmark/zip_uadk_benchmark.h \ + benchmark/zip_wd_benchmark.c benchmark/zip_wd_benchmark.h + +if WD_STATIC_DRV +AM_CFLAGS+=-Bstatic +uadk_tool_LDADD=$(libwd_la_OBJECTS) \ + $(libwd_crypto_la_OBJECTS) \ + ../.libs/libwd_comp.a \ + ../.libs/libhisi_sec.a \ + ../.libs/libhisi_hpre.a \ + ../.libs/libhisi_zip.a \ + -ldl -lnuma +else +uadk_tool_LDADD=-L../.libs -l:libwd.so.2 -l:libwd_crypto.so.2 \ + -l:libwd_comp.so.2 -lnuma +endif + +uadk_tool_LDFLAGS=-Wl,-rpath,'/usr/local/lib' + +if WITH_ZLIB_FSE_DIR +AM_CFLAGS += -DZLIB_FSE +uadk_tool_LDADD+= $(with_zlib_fse_dir)/libfse.a +endif + +if HAVE_CRYPTO +uadk_tool_SOURCES+=benchmark/sec_soft_benchmark.c benchmark/sec_soft_benchmark.h +uadk_tool_LDADD+=$(libcrypto_LIBS) +endif diff --git a/uadk/uadk_tool/benchmark/hpre_protocol_data.h b/uadk/uadk_tool/benchmark/hpre_protocol_data.h new file mode 100644 index 0000000..9c92138 --- /dev/null +++ b/uadk/uadk_tool/benchmark/hpre_protocol_data.h @@ -0,0 +1,1667 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +#ifndef HPRE_PROTOCOL_DATA_H +#define HPRE_PROTOCOL_DATA_H + +static unsigned char rsa_e_1024[] = { + 0x01, 0x00, 0x01, +}; + +static unsigned char rsa_p_1024[] = { + 0xf6, 0x49, 0xf2, 0xec, 0x89, 0xc8, 0xc2, 0x9b, 0x38, 0xd8, 0x74, 0x9b, 0x77, 0xed, 0x96, 0xc7, + 0x6d, 0xed, 0x15, 0x51, 0x2d, 0xfe, 0x67, 0x10, 0xa5, 0xdf, 0xd0, 0x59, 0x79, 0x75, 0x00, 0x60, + 0x3d, 0xd0, 0xf6, 0xe4, 0xda, 0x16, 0x5a, 0x24, 0x14, 0x01, 0xfa, 0x19, 0x07, 0x75, 0x21, 0x70, + 0x88, 0x40, 0xd9, 0x2f, 0xec, 0x83, 0x9e, 0x5f, 0xaa, 0xc0, 0xa3, 0x70, 0x18, 0xf5, 0x78, 0xdf, +}; + +static unsigned char rsa_q_1024[] = { + 0xcf, 0x53, 0x52, 0x09, 0x0d, 0xd7, 0x84, 0xdb, 0xa4, 0x4c, 0x79, 0x74, 0x0d, 0x94, 0xa0, 0x19, + 0x94, 0x33, 0xbf, 0x39, 0xe5, 0xef, 0xf5, 0xe9, 0x6c, 0xef, 0xd0, 0x9a, 0x4c, 0x00, 0x14, 0x68, + 0x66, 0xa7, 0x80, 0x32, 0x14, 0x84, 0xc9, 0x6f, 0x9a, 0x7d, 0x43, 0x0e, 0x9f, 0x85, 0x27, 0x6c, + 0x65, 0x50, 0x9b, 0x88, 0x54, 0x22, 0x72, 0x95, 0x90, 0x26, 0xc4, 0xa8, 0x19, 0x1c, 0x47, 0x03, +}; + +static unsigned char rsa_dp_1024[] = { + 0xd0, 0xb6, 0x66, 0x28, 0xd1, 0xb2, 0xd2, 0x48, 0x1c, 0x6a, 0x42, 0x97, 0x25, 0x90, 0xb0, 0x40, + 0x1d, 0x05, 0xd7, 0x14, 0xce, 0x77, 0x52, 0xfc, 0x26, 0xb5, 0x7e, 0xa8, 0xf4, 0x66, 0x94, 0x84, + 0xfa, 0x9d, 0xc5, 0x3c, 0xb7, 0x1c, 0x4e, 0x13, 0x58, 0xe9, 0x3b, 0xfa, 0x4d, 0xf9, 0x92, 0xf6, + 0xfc, 0x60, 0x88, 0x2d, 0x36, 0xaf, 0x6b, 0x5d, 0x03, 0x24, 0xf0, 0xdc, 0x24, 0x2a, 0x91, 0xdd, +}; + +static unsigned char rsa_dq_1024[] = { + 0x09, 0x4a, 0x89, 0x9d, 0xa0, 0x42, 0x2d, 0x51, 0x0e, 0x8e, 0xe2, 0xce, 0x81, 0xa1, 0x4c, 0x7f, + 0x78, 0xf5, 0xcc, 0xb7, 0x12, 0x87, 0xeb, 0x74, 0x57, 0x8e, 0x73, 0xc1, 0xc6, 0x70, 0x26, 0x79, + 0xfb, 0x47, 0xbc, 0x66, 0x02, 0x27, 0x65, 0x43, 0x9c, 0x1f, 0xca, 0xf6, 0x87, 0xcd, 0x96, 0xd3, + 0xb3, 0xc2, 0xa6, 0x05, 0xb9, 0x07, 0x86, 0x2d, 0x0f, 0xb5, 0xbd, 0x10, 0x6f, 0x77, 0xa5, 0xf3, +}; + +static unsigned char rsa_qinv_1024[] = { + 0x59, 0xf3, 0xaf, 0x75, 0xde, 0xdd, 0xcc, 0xc7, 0x62, 0xd7, 0xed, 0x4e, 0x81, 0x18, 0xca, 0x42, + 0xab, 0x36, 0x3b, 0x83, 0x5c, 0xd0, 0x55, 0x3f, 0x37, 0x3a, 0xa9, 0x64, 0x25, 0x65, 0x05, 0xde, + 0x87, 0xca, 0x54, 0xdb, 0x24, 0xdc, 0xe8, 0xf7, 0x4a, 0xfe, 0x2c, 0x59, 0xbf, 0x3d, 0x45, 0x43, + 0x91, 0x9e, 0x6b, 0x9c, 0xf6, 0xce, 0xb2, 0xf8, 0xc5, 0x2e, 0xef, 0x85, 0x58, 0xed, 0x4a, 0x0e, +}; + +static unsigned char rsa_d_1024[] = { + 0x13, 0xbe, 0x3a, 0x33, 0xf3, 0xad, 0x6f, 0xc7, 0x3a, 0x8c, 0x77, 0xe3, 0x73, 0xb8, 0x13, 0xf0, + 0x66, 0x50, 0xd7, 0x04, 0xe5, 0xeb, 0x11, 0x31, 0x97, 0x9b, 0xac, 0xd5, 0x72, 0x9f, 0xe4, 0xeb, + 0xd7, 0x27, 0x9b, 0x2d, 0xef, 0xca, 0xa3, 0x7c, 0xe7, 0x2f, 0x5e, 0xd7, 0xe9, 0x85, 0xbd, 0x88, + 0xce, 0xb6, 0x32, 0xe2, 0xf3, 0xe4, 0x28, 0x0f, 0xc7, 0x8e, 0xa5, 0xbb, 0xc4, 0xd4, 0xe8, 0xd9, + 0x23, 0x81, 0x4c, 0x71, 0x37, 0xc9, 0x78, 0xe2, 0xd8, 0x54, 0x01, 0x05, 0xb9, 0x5e, 0x48, 0xab, + 0x65, 0x76, 0x63, 0xe3, 0x90, 0xaf, 0x25, 0x00, 0xde, 0xe3, 0xb7, 0x6f, 0x91, 0xa1, 0x5e, 0x7a, + 0x84, 0xbf, 0x62, 0x08, 0x63, 0xe7, 0x0a, 0x23, 0x42, 0x50, 0xc8, 0x33, 0x29, 0xb9, 0x27, 0x27, + 0xe6, 0x34, 0x73, 0x69, 0x08, 0x76, 0xaf, 0x65, 0x1e, 0x3b, 0x51, 0xa5, 0x16, 0xad, 0x20, 0xe5, +}; + +static unsigned char rsa_n_1024[] = { + 0xc7, 0x75, 0xf4, 0x53, 0x6b, 0xd4, 0x69, 0x28, 0x39, 0xeb, 0xa7, 0x70, 0xcf, 0x8f, 0x47, 0x54, + 0x57, 0xf9, 0x43, 0xd3, 0xd6, 0x7b, 0xa4, 0xc9, 0x4b, 0xb3, 0x9d, 0xb3, 0x7f, 0x8f, 0x46, 0x31, + 0xf6, 0xbe, 0x62, 0xa4, 0x0c, 0x7e, 0x41, 0x41, 0x2e, 0x4d, 0x31, 0x1a, 0x92, 0xca, 0x69, 0x27, + 0x0a, 0x06, 0x23, 0xf5, 0x0f, 0x50, 0xf0, 0x17, 0xfa, 0x92, 0x25, 0x1c, 0xb6, 0x59, 0x2c, 0xcc, + 0xc9, 0x4d, 0x3c, 0x38, 0x04, 0xbb, 0x05, 0xc5, 0x20, 0xe5, 0xaf, 0x06, 0xd0, 0xc4, 0x14, 0x9c, + 0xa9, 0xa4, 0x7e, 0x97, 0x04, 0xb9, 0xe7, 0x60, 0x47, 0xa2, 0xed, 0xea, 0xda, 0xec, 0x4e, 0x0a, + 0x7a, 0x01, 0x00, 0x19, 0x19, 0x99, 0x49, 0x28, 0x70, 0x07, 0x21, 0xd8, 0x0d, 0x1f, 0x2d, 0xa2, + 0x9d, 0x78, 0x94, 0x26, 0xdd, 0x26, 0x65, 0x66, 0xf3, 0x04, 0xc3, 0x3b, 0x5e, 0xca, 0x43, 0x9d, +}; + +static unsigned char rsa_e_2048[] = { + 0x01, 0x00, 0x01, +}; + +static unsigned char rsa_p_2048[] = { + 0x01, 0xf8, 0x33, 0x75, 0x8c, 0x8d, 0x6b, 0xed, 0x4b, 0xf7, 0x0a, 0x3a, 0x67, 0xd5, 0x91, + 0x27, 0xe6, 0x62, 0x90, 0x67, 0xd2, 0xe3, 0x33, 0xdc, 0xba, 0x96, 0x81, 0xb7, 0xc9, 0xc8, + 0xa6, 0x64, 0x8b, 0xe9, 0x2f, 0x1d, 0x87, 0x3c, 0x9a, 0x95, 0x19, 0x8b, 0x04, 0x8c, 0x1a, + 0xc1, 0x6b, 0x76, 0x8d, 0xe3, 0x2a, 0x50, 0xec, 0xb8, 0xf7, 0x02, 0x38, 0x5d, 0xd0, 0xe6, + 0xc0, 0x9f, 0xb5, 0xc6, 0xf7, 0xd0, 0x34, 0xec, 0xd5, 0x4d, 0xf5, 0x26, 0x32, 0x8a, 0xe8, + 0x5f, 0xd5, 0x1d, 0x0e, 0xd8, 0xcd, 0x84, 0xe0, 0xd6, 0x09, 0x3a, 0xcd, 0x8b, 0x5c, 0x96, + 0x89, 0xf0, 0x2e, 0xb7, 0x87, 0x9c, 0x12, 0xeb, 0xd6, 0x84, 0x00, 0x3d, 0x1c, 0xff, 0xa0, + 0xaa, 0x82, 0x0a, 0x4d, 0x53, 0x06, 0xde, 0x5a, 0x0c, 0x4a, 0xd4, 0x94, 0x5b, 0x01, 0xac, + 0x9f, 0x9e, 0x7e, 0x90, 0xb0, 0xd7, 0x19 +}; + +static unsigned char rsa_q_2048[] = { + 0x01, 0xe1, 0xf1, 0x9b, 0xd6, 0xcf, 0x15, 0x49, 0x4c, 0xfa, 0x90, 0xf1, 0x27, 0xb1, 0xe2, + 0xc9, 0xf8, 0xec, 0x97, 0xc5, 0x10, 0x6c, 0xad, 0x62, 0xba, 0x1b, 0x23, 0x1e, 0x95, 0xb3, + 0x30, 0x89, 0x15, 0xc2, 0x19, 0x9e, 0xa8, 0x06, 0x30, 0xe1, 0xf0, 0x14, 0xfa, 0x99, 0x10, + 0x22, 0x13, 0x43, 0xb1, 0x97, 0xa4, 0x7d, 0x5d, 0x92, 0xa4, 0xf1, 0x28, 0x33, 0xbc, 0x9b, + 0x20, 0xba, 0x73, 0x66, 0x32, 0x96, 0x63, 0xb2, 0x1d, 0x49, 0xe8, 0xbc, 0x2e, 0x88, 0x2b, + 0x9f, 0x89, 0x14, 0xb6, 0x5e, 0xe1, 0xe9, 0x0f, 0x1c, 0xa8, 0xd5, 0xa4, 0xda, 0x61, 0xde, + 0x0c, 0x36, 0xce, 0xf2, 0x89, 0xeb, 0x59, 0xd5, 0xd0, 0xdf, 0x77, 0xb5, 0x14, 0xa6, 0xcf, + 0x35, 0x86, 0xf1, 0x78, 0x1a, 0x8a, 0x52, 0x6f, 0x06, 0x20, 0x17, 0xca, 0xa8, 0xae, 0x4a, + 0x60, 0xf9, 0x89, 0x05, 0xc6, 0x0d, 0x87 +}; + +static unsigned char rsa_dp_2048[] = { + 0x54, 0xd7, 0xb3, 0xec, 0x16, 0xd0, 0x16, 0x7a, 0x35, 0xf3, 0xce, 0xa8, 0x32, 0x53, 0xde, + 0xb6, 0xf1, 0xd7, 0x02, 0xe1, 0x85, 0xc1, 0xf0, 0x5e, 0xa5, 0x7c, 0xe6, 0x84, 0x59, 0xf3, + 0x45, 0xf0, 0x15, 0x29, 0x0c, 0x7a, 0xf9, 0x43, 0xb9, 0xdb, 0x36, 0x7d, 0x69, 0x66, 0x07, + 0x2e, 0x22, 0x20, 0xf6, 0x1c, 0xe4, 0xc9, 0x30, 0xc6, 0xbf, 0xe4, 0xe4, 0x44, 0x86, 0xcf, + 0xdb, 0x10, 0x27, 0x8f, 0x03, 0xc6, 0x24, 0x24, 0x30, 0x9e, 0x13, 0xf3, 0x65, 0x54, 0x7c, + 0xeb, 0xcb, 0x9b, 0xf7, 0xf7, 0x7d, 0x68, 0xa8, 0x1b, 0x9d, 0x7d, 0x80, 0xf9, 0xef, 0x8a, + 0xfe, 0x93, 0x9d, 0xe6, 0x7f, 0xe8, 0xdf, 0x2e, 0x95, 0xbf, 0xc4, 0x88, 0xe0, 0xab, 0x14, + 0x86, 0x15, 0x5d, 0xb5, 0x9e, 0xee, 0x43, 0x90, 0xd5, 0xf6, 0xb7, 0x90, 0x28, 0xd3, 0xf7, + 0x78, 0x20, 0x2c, 0x10, 0xd5, 0xe1 +}; + +static unsigned char rsa_dq_2048[] = { + 0x38, 0x83, 0x81, 0x77, 0xb5, 0xfe, 0xd4, 0x02, 0x9f, 0xdb, 0x41, 0x3c, 0x1b, 0x62, 0xf1, + 0xb6, 0x2b, 0xe0, 0x3c, 0x2e, 0x89, 0xdf, 0xe7, 0x14, 0xd5, 0xbb, 0xcf, 0x89, 0x54, 0x62, + 0xdb, 0xa0, 0x5e, 0x8b, 0x6c, 0x8c, 0x5d, 0x75, 0x7b, 0xf9, 0x10, 0x2c, 0xb6, 0xa8, 0x2a, + 0xa6, 0xc1, 0xa8, 0x60, 0x94, 0xdc, 0x52, 0x8d, 0xb0, 0xa3, 0xca, 0xc8, 0x0e, 0x54, 0xce, + 0x88, 0xae, 0xa1, 0x8c, 0x4b, 0x10, 0x53, 0xc1, 0x95, 0x7a, 0x22, 0x1e, 0xfe, 0xbe, 0xc6, + 0xcd, 0x67, 0x4d, 0x5f, 0x60, 0xf4, 0x58, 0x5e, 0x4e, 0xfa, 0x06, 0x83, 0xc9, 0x38, 0x25, + 0x8c, 0x83, 0xc5, 0xf3, 0x20, 0x52, 0xff, 0x7c, 0xa7, 0xc7, 0xbc, 0xc7, 0x38, 0x2c, 0x52, + 0x25, 0x89, 0xc9, 0x40, 0xab, 0x79, 0xb1, 0x25, 0x31, 0xbc, 0x38, 0x7a, 0x81, 0x3d, 0x9d, + 0x93, 0x85, 0x5a, 0xd4, 0xf7, 0x9f +}; + +static unsigned char rsa_qinv_2048[] = { + 0x01, 0x3d, 0x2b, 0xcc, 0x55, 0x34, 0x6f, 0x0b, 0x2d, 0x84, 0x57, 0x16, 0x50, 0x06, 0x38, + 0x3f, 0xcf, 0x61, 0x25, 0x6d, 0x16, 0xc4, 0x91, 0x0e, 0x28, 0xa4, 0xbe, 0x2e, 0x0a, 0x12, + 0x6a, 0x0b, 0xe7, 0xda, 0x94, 0x12, 0x36, 0x99, 0xbe, 0x3c, 0x51, 0x01, 0x98, 0x84, 0x77, + 0xc8, 0xed, 0xd9, 0xaa, 0xbc, 0x3d, 0x7a, 0x48, 0x69, 0xf4, 0xac, 0x68, 0x78, 0xfa, 0x81, + 0xba, 0x57, 0xbd, 0xaa, 0x9d, 0xcc, 0x39, 0x57, 0x87, 0x77, 0xe9, 0x2a, 0xcd, 0xde, 0xfc, + 0x4d, 0xf5, 0xb6, 0x4f, 0xc3, 0x53, 0x00, 0x5a, 0xf6, 0x14, 0x96, 0x7b, 0x37, 0x7e, 0x9f, + 0x89, 0xa0, 0x7e, 0xa4, 0xc8, 0xe5, 0xb1, 0x7b, 0x29, 0x82, 0x95, 0x7b, 0x08, 0x68, 0xb6, + 0x76, 0x4b, 0xf9, 0x5f, 0x31, 0xe7, 0x3f, 0xf2, 0x2a, 0xbe, 0xe4, 0x28, 0xf3, 0x83, 0x0f, + 0x17, 0xe9, 0x8f, 0xbb, 0x4f, 0x1e, 0x26 +}; + +static unsigned char rsa_d_2048[] = { + 0x03, 0xb5, 0x34, 0x8b, 0x3c, 0xfa, 0x14, 0xd1, 0x38, 0x44, 0xc0, 0xb5, 0xee, 0x6f, 0xa6, + 0x8b, 0x46, 0x4a, 0x46, 0x77, 0x7f, 0x49, 0x4f, 0x0a, 0x00, 0x5d, 0xed, 0x36, 0xe2, 0x22, + 0x0b, 0xc6, 0x6c, 0xd6, 0x25, 0x15, 0xa2, 0x51, 0xa1, 0xc8, 0xb7, 0x22, 0xd8, 0xad, 0xb7, + 0xf8, 0x59, 0xa9, 0x69, 0x32, 0xf0, 0xa4, 0xc6, 0x17, 0x40, 0xaa, 0x74, 0x4d, 0x98, 0x2f, + 0x71, 0xc0, 0x18, 0xdd, 0x3d, 0xe9, 0x0f, 0x7a, 0x1a, 0x7f, 0xff, 0xf8, 0x5b, 0x63, 0x13, + 0xf8, 0xfe, 0x4b, 0xf8, 0x9f, 0xa5, 0xfc, 0x6d, 0x60, 0x49, 0x5a, 0xc2, 0xbd, 0x07, 0x6c, + 0x32, 0xe7, 0x24, 0xf9, 0x46, 0x03, 0xab, 0x54, 0x30, 0x3b, 0x29, 0x91, 0x0f, 0x1c, 0x77, + 0x3a, 0x00, 0xf4, 0xe3, 0xcf, 0xd8, 0x35, 0x3e, 0x0f, 0xd0, 0xd8, 0xf4, 0x50, 0x6e, 0x88, + 0x6a, 0x4f, 0xd0, 0xa8, 0x40, 0x5a, 0x2f, 0x3c, 0x11, 0x4f, 0x43, 0xb0, 0x43, 0x23, 0x20, + 0x36, 0xb7, 0xb2, 0x16, 0xed, 0xbc, 0xb5, 0xc8, 0xde, 0x7e, 0x4a, 0x03, 0x7a, 0xf6, 0xa2, + 0xa8, 0xb6, 0xc0, 0xd0, 0x98, 0x94, 0x7a, 0x81, 0x02, 0xc1, 0xce, 0x0b, 0xed, 0x6e, 0xf1, + 0x5d, 0xb7, 0xb3, 0x9c, 0xa9, 0x88, 0x52, 0xf9, 0xf9, 0xcf, 0xfd, 0x74, 0x6a, 0xa3, 0x3b, + 0x0c, 0xa0, 0x32, 0xd2, 0xb6, 0x31, 0x8b, 0x93, 0x3b, 0x8a, 0x04, 0x2e, 0xdd, 0x14, 0x60, + 0x35, 0xa0, 0xd4, 0xca, 0xdc, 0x9e, 0x96, 0x23, 0xac, 0x64, 0xd5, 0x29, 0xb2, 0x0d, 0x46, + 0x01, 0xe6, 0xf7, 0xa0, 0xe0, 0x9c, 0xfb, 0xde, 0x21, 0xff, 0xff, 0x4f, 0xc0, 0x04, 0x3e, + 0xc4, 0x4b, 0xaf, 0x20, 0x1c, 0x41, 0xce, 0x07, 0x3c, 0x79, 0xfc, 0x6d, 0x7c, 0xef, 0x1e, + 0x37, 0x14, 0x78, 0x9d, 0x26, 0x85, 0x2a, 0xcc, 0x72, 0x22, 0x83, 0xb3, 0x2f +}; + +static unsigned char rsa_n_2048[] = { + 0x03, 0xB5, 0x34, 0x8B, 0x3C, 0xFA, 0x14, 0xD1, 0x38, 0x44, 0xC0, 0xB5, 0xEE, 0x6F, 0xA6, 0x8B, + 0x46, 0x4A, 0x46, 0x77, 0x7F, 0x49, 0x4F, 0x0A, 0x00, 0x5D, 0xED, 0x36, 0xE2, 0x22, 0x0B, 0xC6, + 0x6C, 0xD6, 0x25, 0x15, 0xA2, 0x51, 0xA1, 0xC8, 0xB7, 0x22, 0xD8, 0xAD, 0xB7, 0xF8, 0x59, 0xA9, + 0x69, 0x32, 0xF0, 0xA4, 0xC6, 0x17, 0x40, 0xAA, 0x74, 0x4D, 0x98, 0x2F, 0x71, 0xC0, 0x18, 0xDD, + 0x3D, 0xE9, 0x0F, 0x7A, 0x1A, 0x7F, 0xFF, 0xF8, 0x5B, 0x63, 0x13, 0xF8, 0xFE, 0x4B, 0xF8, 0x9F, + 0xA5, 0xFC, 0x6D, 0x60, 0x49, 0x5A, 0xC2, 0xBD, 0x07, 0x6C, 0x32, 0xE7, 0x24, 0xF9, 0x46, 0x03, + 0xAB, 0x54, 0x30, 0x3B, 0x29, 0x91, 0x0F, 0x1C, 0x77, 0x3A, 0x00, 0xF4, 0xE3, 0xCF, 0xD8, 0x35, + 0x3E, 0x0F, 0xD0, 0xD8, 0xF4, 0x50, 0x6E, 0x88, 0x6A, 0x4F, 0xD0, 0xA8, 0x40, 0x5A, 0x2F, 0x3C, + 0x11, 0x4F, 0x43, 0xB0, 0x43, 0x23, 0x20, 0x36, 0xB7, 0xB2, 0x16, 0xED, 0xBC, 0xB5, 0xC8, 0xDE, + 0x7E, 0x4A, 0x03, 0x7A, 0xF6, 0xA2, 0xA8, 0xB6, 0xC0, 0xD0, 0x98, 0x94, 0x7A, 0x81, 0x02, 0xC1, + 0xCE, 0x0B, 0xED, 0x6E, 0xF1, 0x5D, 0xB7, 0xB3, 0x9C, 0xA9, 0x88, 0x52, 0xF9, 0xF9, 0xCF, 0xFD, + 0x74, 0x6A, 0xA3, 0x3B, 0x0C, 0xA0, 0x32, 0xD2, 0xB6, 0x31, 0x8B, 0x93, 0x3B, 0x8A, 0x04, 0x2E, + 0xDD, 0x14, 0x60, 0x35, 0xA0, 0xD4, 0xCA, 0xDC, 0x9E, 0x96, 0x23, 0xAC, 0x64, 0xD5, 0x29, 0xB2, + 0x0D, 0x46, 0x01, 0xE6, 0xF7, 0xA0, 0xE0, 0x9C, 0xFB, 0xDE, 0x21, 0xFF, 0xFF, 0x4F, 0xC0, 0x04, + 0x3E, 0xC4, 0x4B, 0xAF, 0x20, 0x1C, 0x41, 0xCE, 0x07, 0x3C, 0x79, 0xFC, 0x6D, 0x7C, 0xEF, 0x1E, + 0x37, 0x14, 0x78, 0x9D, 0x26, 0x85, 0x2A, 0xCC, 0x72, 0x22, 0x83, 0xB3, 0x2F +}; + +static unsigned char rsa_e_3072[] = { + 0x01, 0x00, 0x01 +}; + +static unsigned char rsa_p_3072[] = { + 0xfe, 0x2d, 0x13, 0xf6, 0x82, 0xbd, 0xc9, 0x3f, 0xf2, 0x44, 0x87, 0xb0, 0x9c, 0xda, 0xca, 0xb5, + 0xfa, 0x01, 0x6f, 0xf0, 0x3d, 0xd0, 0xd2, 0x1c, 0x40, 0xef, 0xc6, 0x69, 0xe0, 0xe9, 0x66, 0x06, + 0x29, 0x00, 0x7e, 0xe6, 0x0b, 0x1a, 0x02, 0x50, 0x5e, 0x0e, 0x19, 0x5f, 0x6a, 0xf3, 0x0c, 0xa5, + 0x3f, 0xe9, 0xc4, 0x5d, 0x36, 0xc5, 0xbe, 0xc7, 0x77, 0xfc, 0x15, 0x05, 0xb3, 0xa4, 0xc7, 0xd1, + 0xab, 0x3f, 0xfc, 0x42, 0xc3, 0x9a, 0x0e, 0x5a, 0xd8, 0x51, 0xeb, 0x36, 0x2c, 0xf2, 0x07, 0xe3, + 0x5c, 0xcb, 0xe1, 0xf3, 0xd7, 0x67, 0x42, 0x2f, 0x3a, 0x31, 0x21, 0x0f, 0x4e, 0x4d, 0x03, 0x30, + 0xaf, 0xd9, 0x05, 0x03, 0x64, 0x79, 0x7d, 0x7b, 0x96, 0x48, 0xe5, 0x6f, 0x84, 0x44, 0x03, 0x36, + 0x08, 0xf6, 0xe8, 0xb4, 0xa8, 0x7d, 0xb4, 0x63, 0x73, 0x6f, 0x2b, 0x14, 0xb0, 0x6e, 0x0c, 0x96, + 0x3d, 0xe2, 0xda, 0x7f, 0x4f, 0x07, 0xc3, 0xb0, 0x89, 0x53, 0x9d, 0x14, 0x61, 0x17, 0xe6, 0xa4, + 0x52, 0x1a, 0xfb, 0xd4, 0xdd, 0xe0, 0x54, 0x2a, 0xf2, 0x86, 0x30, 0x8c, 0x1c, 0x68, 0x30, 0x72, + 0xcc, 0xa0, 0x3f, 0xe0, 0x14, 0x3d, 0xfc, 0xf2, 0xd9, 0x91, 0xea, 0xe8, 0xe8, 0x9a, 0x78, 0xfb, + 0xa8, 0x16, 0x50, 0x24, 0xfe, 0x54, 0xd4, 0x57, 0xf1, 0xd9, 0x8f, 0xcb, 0x6d, 0x38, 0x63, 0x21 +}; + +static unsigned char rsa_q_3072[] = { + 0xd4, 0x12, 0x12, 0xd1, 0x4e, 0x9e, 0xa8, 0xb4, 0xf3, 0x94, 0x4d, 0x03, 0x70, 0x83, 0x4f, 0x1c, + 0x16, 0x85, 0xd8, 0xa8, 0x8d, 0xcc, 0xfe, 0xde, 0x5d, 0x08, 0xc3, 0xdf, 0xc4, 0xd8, 0xf9, 0x60, + 0x50, 0x9a, 0x58, 0xd5, 0xf5, 0x96, 0xec, 0x95, 0x09, 0x7b, 0x5f, 0x96, 0xaf, 0xf5, 0xee, 0x79, + 0x46, 0x8b, 0x38, 0x2c, 0x9b, 0x17, 0x69, 0x07, 0x91, 0x74, 0x57, 0x73, 0x99, 0xd9, 0x89, 0xa4, + 0x20, 0x0b, 0xb5, 0x7f, 0x30, 0xd7, 0x13, 0xda, 0x0d, 0xc0, 0x3a, 0x96, 0x76, 0xf7, 0xac, 0x86, + 0x5e, 0x1f, 0x5d, 0xd4, 0x54, 0xa0, 0x30, 0xca, 0x36, 0x00, 0x7c, 0xc1, 0xd8, 0x05, 0x73, 0xde, + 0x75, 0x6c, 0xd0, 0x69, 0xe5, 0xfa, 0xd8, 0x24, 0xca, 0xb0, 0xee, 0x8a, 0x63, 0x83, 0x1b, 0x90, + 0xb8, 0x0d, 0x6d, 0xd5, 0x75, 0xe4, 0x5c, 0x73, 0xc7, 0xff, 0xe4, 0x57, 0x6a, 0x59, 0xc3, 0x17, + 0x05, 0xc4, 0xc4, 0x87, 0xc2, 0x11, 0x7a, 0x34, 0xbd, 0xb4, 0x7c, 0x7f, 0x3a, 0x60, 0xd7, 0x57, + 0xcb, 0x48, 0xb1, 0x14, 0xa6, 0x4f, 0x57, 0x35, 0xc7, 0x64, 0xf9, 0xb8, 0x11, 0xe8, 0x22, 0xfd, + 0x6c, 0x53, 0xdd, 0xef, 0x6a, 0x88, 0x56, 0xf7, 0x6d, 0x51, 0xa1, 0x5b, 0x26, 0x81, 0xa0, 0xd4, + 0x78, 0x10, 0x9f, 0x2d, 0x88, 0xdc, 0xa1, 0x09, 0xd0, 0x84, 0x7a, 0x3b, 0x38, 0x7c, 0x5f, 0x75 +}; + +static unsigned char rsa_dp_3072[] = { + 0xfd, 0x8d, 0x3a, 0x3c, 0xce, 0x6f, 0x44, 0x32, 0xe6, 0x1a, 0x36, 0xc1, 0x97, 0xb7, 0x2a, 0x40, + 0x1e, 0x05, 0x11, 0x05, 0x36, 0xa4, 0xf8, 0xf3, 0xf6, 0x53, 0x3a, 0x3a, 0xa4, 0x82, 0x2f, 0xa4, + 0x35, 0x82, 0xa9, 0x14, 0x12, 0x3e, 0xff, 0xcf, 0xec, 0x03, 0x64, 0x8c, 0x2a, 0xc4, 0x09, 0xf9, + 0x4e, 0xa8, 0x83, 0x99, 0xf8, 0xe9, 0x8a, 0x46, 0xb1, 0x0a, 0x66, 0x6e, 0x29, 0xa6, 0x57, 0x2e, + 0x71, 0x06, 0x83, 0x3e, 0x96, 0xa1, 0x37, 0x70, 0xa8, 0x1a, 0x0f, 0xe9, 0x1b, 0x2c, 0xd5, 0x71, + 0x99, 0x40, 0x49, 0x46, 0x55, 0xba, 0x4b, 0xeb, 0x90, 0xc1, 0x31, 0x99, 0x73, 0x22, 0x9f, 0xec, + 0x11, 0x7f, 0x0b, 0xe1, 0x36, 0x79, 0x7b, 0x13, 0xad, 0xf7, 0x49, 0xe8, 0xd4, 0xa8, 0x84, 0x0b, + 0x83, 0x25, 0xcb, 0x3d, 0x6c, 0x56, 0xf9, 0x7b, 0xbb, 0xcb, 0x49, 0xce, 0x79, 0xb1, 0x4e, 0x1d, + 0x11, 0xdf, 0x1a, 0xd7, 0xa4, 0x9e, 0xba, 0x37, 0x80, 0xc6, 0x48, 0x0b, 0xec, 0x4f, 0x4b, 0x64, + 0xe0, 0x02, 0xca, 0xf4, 0xad, 0xe0, 0xfa, 0x15, 0x5d, 0x99, 0x3f, 0x14, 0x85, 0xc1, 0xe9, 0x92, + 0x9b, 0x4d, 0xc0, 0x6a, 0x67, 0xc6, 0xee, 0x6d, 0xd3, 0x5c, 0x1c, 0x59, 0xfa, 0xaf, 0x1d, 0xc0, + 0xed, 0x0c, 0x55, 0x26, 0x92, 0x0f, 0x4d, 0x43, 0xed, 0x9e, 0x7a, 0x33, 0x13, 0xe1, 0x0c, 0x01 +}; + +static unsigned char rsa_dq_3072[] = { + 0x51, 0xfc, 0xde, 0xcb, 0x8e, 0xe2, 0xa6, 0x04, 0xb7, 0x3a, 0xf9, 0x7f, 0x3f, 0xeb, 0x74, 0x15, + 0x3e, 0xdb, 0xe6, 0x44, 0x5b, 0xf6, 0x09, 0xfe, 0xfb, 0xe6, 0xdc, 0x9b, 0x51, 0x66, 0x35, 0x1b, + 0x38, 0x6e, 0x43, 0xb4, 0x0c, 0x6b, 0x99, 0xf1, 0x90, 0xa5, 0xe2, 0xf1, 0xc5, 0xfb, 0x85, 0x83, + 0xdb, 0x73, 0x0d, 0x77, 0xa9, 0x4a, 0x26, 0xaf, 0xe7, 0x5b, 0x1c, 0x48, 0x34, 0x0d, 0xb7, 0x39, + 0xfd, 0xad, 0xa9, 0x30, 0x90, 0x38, 0x46, 0x93, 0x81, 0xc7, 0x74, 0x9f, 0x21, 0x45, 0x65, 0xac, + 0xd9, 0x0c, 0xb5, 0x60, 0xd6, 0x8a, 0xcb, 0xf2, 0x11, 0x68, 0xa4, 0xd2, 0xe8, 0x6a, 0x4b, 0x3e, + 0x91, 0x15, 0x4d, 0x89, 0xf3, 0x80, 0xc4, 0x39, 0x8d, 0x27, 0x54, 0x41, 0xaa, 0x71, 0x50, 0xa1, + 0xe5, 0x96, 0x43, 0x85, 0x48, 0x3b, 0xce, 0x46, 0x70, 0xe7, 0x0c, 0x67, 0x83, 0x55, 0x4a, 0xa8, + 0x46, 0xf1, 0xa8, 0xad, 0x77, 0xa8, 0xfc, 0x1f, 0x11, 0xcc, 0x8a, 0x69, 0x41, 0xaf, 0x98, 0xf1, + 0x77, 0x45, 0x16, 0x39, 0x0e, 0x87, 0x14, 0x07, 0x55, 0x9c, 0x43, 0x33, 0x17, 0xb1, 0x30, 0x7d, + 0xdb, 0x78, 0x9d, 0x0f, 0xe7, 0x96, 0xe8, 0x50, 0x66, 0x32, 0x2d, 0xf8, 0xa8, 0x6d, 0x6b, 0x39, + 0x59, 0x65, 0xcb, 0xb4, 0x75, 0xfa, 0x1e, 0x44, 0x46, 0x1a, 0x41, 0x8b, 0x4d, 0xae, 0x3f, 0xd5 +}; + +static unsigned char rsa_qinv_3072[] = { + 0xb2, 0xa1, 0x52, 0x54, 0xee, 0xcd, 0xb9, 0x07, 0xde, 0x26, 0x8a, 0x1b, 0x93, 0x91, 0xf7, 0x08, + 0xbe, 0x81, 0x23, 0x0c, 0xba, 0x24, 0x7a, 0x66, 0x57, 0x41, 0x09, 0xc6, 0x3a, 0x25, 0xa8, 0x56, + 0x03, 0x34, 0xcd, 0xcb, 0x97, 0xe8, 0x48, 0xdf, 0x64, 0xc8, 0xd3, 0xe2, 0xfd, 0xaa, 0xcb, 0xdc, + 0x9c, 0xfc, 0xab, 0x0d, 0x00, 0x57, 0x06, 0xb3, 0x71, 0x53, 0xe9, 0x2d, 0x7c, 0xcc, 0x68, 0xca, + 0x24, 0x94, 0x11, 0x48, 0x21, 0xb0, 0x55, 0xcb, 0xa9, 0x2b, 0x09, 0x99, 0x90, 0x9a, 0xaa, 0xea, + 0xa3, 0xbd, 0x4d, 0xf3, 0xba, 0x67, 0x55, 0x3c, 0x5c, 0xbf, 0xfa, 0x23, 0xbf, 0xfc, 0xcd, 0x7e, + 0x99, 0x60, 0xf1, 0x71, 0x78, 0x03, 0x15, 0xbb, 0xda, 0x54, 0xd9, 0x3d, 0x0d, 0x19, 0xad, 0xbf, + 0x3e, 0x35, 0xa9, 0x5d, 0xf7, 0xb1, 0x88, 0x78, 0x96, 0x59, 0xda, 0x0b, 0x54, 0xd9, 0x8a, 0x64, + 0x89, 0xf8, 0xea, 0x27, 0x78, 0x73, 0x58, 0x40, 0x1f, 0xec, 0xa3, 0xdd, 0xe3, 0xdb, 0x88, 0xdb, + 0x3f, 0x00, 0xc1, 0xdb, 0x95, 0x24, 0x7d, 0x55, 0x2f, 0xe1, 0xa1, 0xa5, 0x70, 0x13, 0xd5, 0xc7, + 0x26, 0x41, 0x9f, 0x79, 0xc7, 0x5b, 0x30, 0x58, 0x65, 0x16, 0xa0, 0x0d, 0xac, 0x1d, 0xc8, 0x8d, + 0xe1, 0xce, 0xc2, 0x61, 0x0f, 0xb0, 0x02, 0xc9, 0x80, 0x1e, 0xbd, 0x25, 0x83, 0xbc, 0x9d, 0xdc +}; + +static unsigned char rsa_d_3072[] = { + 0x33, 0x49, 0x58, 0xb0, 0x89, 0x3d, 0x96, 0x78, 0xb7, 0x2a, 0x99, 0x5e, 0x0c, 0x56, 0xae, 0x08, + 0x32, 0xe1, 0xb9, 0x1c, 0x17, 0xd7, 0x71, 0xaa, 0x57, 0x37, 0x58, 0xbf, 0x94, 0xf8, 0xa0, 0xdf, + 0xdb, 0x0a, 0xfd, 0x2f, 0xce, 0x8a, 0x82, 0x43, 0x11, 0x48, 0x6b, 0xec, 0x61, 0x72, 0x77, 0x98, + 0x53, 0x00, 0x32, 0x5e, 0xbe, 0x3d, 0x37, 0xaf, 0x53, 0x55, 0x13, 0xc7, 0x61, 0x03, 0x6a, 0x28, + 0xc8, 0xe6, 0xa8, 0xac, 0x5f, 0xcf, 0x15, 0x54, 0x36, 0xc4, 0x74, 0x60, 0x3b, 0xcc, 0xbc, 0x4f, + 0x05, 0x27, 0x0d, 0x9e, 0x3c, 0x0c, 0x74, 0x1d, 0x59, 0xb7, 0x28, 0x05, 0x94, 0x2d, 0x0d, 0x02, + 0x60, 0xaa, 0x82, 0x14, 0x29, 0xf9, 0x38, 0x6a, 0xcb, 0x3a, 0xc4, 0x14, 0x70, 0xa4, 0x6b, 0x34, + 0xb6, 0xad, 0x11, 0xca, 0x4b, 0x76, 0x59, 0xd7, 0x29, 0xf1, 0x2e, 0xef, 0xf9, 0xa9, 0xf4, 0xd5, + 0x50, 0x13, 0x60, 0xc9, 0xac, 0x96, 0x14, 0x23, 0xdd, 0x3a, 0x2d, 0x9a, 0x9f, 0x58, 0xa8, 0xcb, + 0x70, 0xe4, 0x19, 0x45, 0x5c, 0xec, 0x7c, 0x64, 0xab, 0x76, 0x63, 0x07, 0xe0, 0x98, 0x5a, 0xbc, + 0x91, 0xc0, 0xbc, 0x84, 0xd5, 0x06, 0xef, 0xc4, 0xa2, 0xe0, 0x8f, 0x5a, 0xc9, 0x0e, 0x74, 0x3a, + 0x64, 0x80, 0x72, 0x8f, 0x62, 0xe4, 0x23, 0xe2, 0x7c, 0x79, 0x60, 0x49, 0xd6, 0x24, 0xca, 0x3d, + 0x8f, 0xb5, 0xbf, 0xee, 0x31, 0x25, 0x7b, 0xf8, 0x36, 0xe3, 0x47, 0x4a, 0xc6, 0xd8, 0x6e, 0xfe, + 0x05, 0xf0, 0x42, 0x4b, 0x90, 0x59, 0xf4, 0x45, 0xb7, 0x89, 0xed, 0x20, 0x9e, 0x60, 0x36, 0xaf, + 0xd3, 0x07, 0x2f, 0x5a, 0x47, 0xdc, 0x00, 0xb7, 0x01, 0xc7, 0x5d, 0xa0, 0x1f, 0x03, 0x08, 0x57, + 0x2e, 0x1e, 0x95, 0x61, 0xf7, 0x6c, 0x62, 0x7a, 0x07, 0x6b, 0x27, 0x81, 0xb9, 0xe6, 0x49, 0x9d, + 0x15, 0x6d, 0x19, 0xba, 0xd3, 0x11, 0xd5, 0x2b, 0xd1, 0x24, 0x1e, 0x16, 0xd0, 0x78, 0xdc, 0xda, + 0x55, 0x4a, 0x8a, 0x46, 0x04, 0xda, 0x7a, 0xb2, 0xda, 0xe4, 0xc0, 0xc7, 0xb7, 0x2b, 0xd6, 0x22, + 0x5a, 0xe3, 0xf7, 0xe1, 0xa4, 0xed, 0x6a, 0xb5, 0xb4, 0x3c, 0x25, 0x1e, 0x41, 0x0f, 0xb1, 0x26, + 0x88, 0xfc, 0x10, 0x25, 0x52, 0x2d, 0x95, 0xac, 0xf8, 0x81, 0x29, 0xe0, 0x90, 0xc0, 0x10, 0xdf, + 0x83, 0xbd, 0xee, 0x9c, 0xb6, 0x79, 0x9c, 0xd2, 0x6f, 0x4a, 0xd9, 0x15, 0xd1, 0xdb, 0x23, 0x38, + 0x1e, 0xf5, 0x69, 0x81, 0xc3, 0xe4, 0x02, 0xa2, 0x1f, 0xe8, 0xa2, 0x95, 0xbe, 0x3e, 0x40, 0x3b, + 0xda, 0xa1, 0x96, 0x7d, 0x51, 0xae, 0x06, 0x84, 0x02, 0xe1, 0x99, 0xcb, 0x9e, 0xf0, 0xe8, 0x7d, + 0x9c, 0xa3, 0x00, 0xd0, 0x1d, 0xe1, 0x52, 0xc4, 0x71, 0x12, 0x5c, 0x53, 0xd6, 0x88, 0xfb, 0x81 +}; + +static unsigned char rsa_n_3072[] = { + 0xd2, 0x8f, 0x46, 0x62, 0x87, 0xde, 0x40, 0xdb, 0xdc, 0xd5, 0xf1, 0x7b, 0x14, 0x75, 0x7e, 0x5e, + 0xcb, 0x38, 0x7f, 0x9e, 0xc4, 0x30, 0xb6, 0x77, 0x6d, 0x20, 0x9a, 0x52, 0xe0, 0x0a, 0x9d, 0x34, + 0x09, 0xfd, 0x15, 0xbe, 0x36, 0x25, 0x71, 0x85, 0x0d, 0x6a, 0x33, 0x6d, 0x81, 0xd5, 0x74, 0x4c, + 0x2f, 0x8a, 0xd2, 0xad, 0xa0, 0x94, 0x26, 0x3d, 0xba, 0x1d, 0xe9, 0x33, 0xdc, 0x50, 0x6d, 0xc2, + 0xd1, 0xc9, 0xc9, 0xae, 0xd3, 0xf8, 0x31, 0x30, 0xc5, 0x33, 0xe5, 0xf7, 0x80, 0xcf, 0x33, 0x6d, + 0x50, 0xf0, 0xba, 0xa0, 0xd0, 0x86, 0x75, 0x21, 0xb9, 0x28, 0x02, 0x20, 0xf1, 0x7f, 0x1c, 0xe7, + 0xdb, 0xe6, 0x10, 0x5e, 0x5c, 0xf0, 0xea, 0x55, 0x89, 0x41, 0x1d, 0x93, 0x60, 0x59, 0x3a, 0x58, + 0x54, 0x93, 0x7c, 0x09, 0x62, 0xc0, 0x2d, 0x60, 0x8e, 0x49, 0x5e, 0x23, 0xe6, 0x90, 0x67, 0xe8, + 0x99, 0xb5, 0xe3, 0xf3, 0xb4, 0x9f, 0x29, 0xe7, 0x6b, 0xc9, 0x32, 0xd5, 0x98, 0xde, 0xb9, 0xad, + 0xd2, 0x28, 0x9b, 0xc6, 0x8e, 0xeb, 0x8a, 0xb0, 0xf3, 0x6d, 0x86, 0x71, 0x70, 0xba, 0x77, 0xf0, + 0xad, 0x28, 0x46, 0x02, 0xd0, 0xb3, 0xf2, 0xe8, 0x29, 0xc7, 0x9e, 0x08, 0xf4, 0x8d, 0xa8, 0xff, + 0x10, 0xc5, 0xb0, 0xad, 0x8b, 0x67, 0x1d, 0x67, 0xf1, 0x2d, 0xf5, 0x5e, 0xee, 0x31, 0x5e, 0x4b, + 0x76, 0x78, 0xaf, 0xd1, 0x06, 0x3a, 0xed, 0xf3, 0x57, 0x07, 0x53, 0x44, 0xd6, 0x54, 0xe8, 0xb4, + 0xcf, 0xd2, 0xc6, 0x1d, 0xc4, 0xeb, 0xd8, 0xc4, 0x89, 0x78, 0x41, 0x12, 0x33, 0x06, 0xfa, 0xf5, + 0xec, 0x13, 0xe5, 0x90, 0xd9, 0xad, 0x6e, 0x26, 0x89, 0xf9, 0x7f, 0x7f, 0x0a, 0x3b, 0xe5, 0xf8, + 0x40, 0x88, 0x10, 0x08, 0x40, 0xc8, 0x31, 0x84, 0x8f, 0x18, 0x5c, 0xe6, 0x60, 0xa0, 0x3a, 0x94, + 0xc7, 0x45, 0xf8, 0xbc, 0x90, 0x2c, 0x2d, 0x92, 0x41, 0x6e, 0xe0, 0xb5, 0xe4, 0x85, 0x69, 0xfc, + 0xef, 0xd6, 0xdb, 0xe9, 0x73, 0x73, 0x42, 0x5f, 0x0f, 0x08, 0xec, 0xd6, 0xd7, 0x92, 0xa6, 0x7f, + 0xfb, 0xa1, 0x31, 0x7d, 0x57, 0x44, 0xdf, 0xfa, 0xf8, 0xaf, 0x2e, 0x5a, 0x00, 0xa2, 0x6a, 0x2b, + 0x9d, 0x05, 0xf5, 0xba, 0xd4, 0x19, 0x07, 0xd2, 0x1e, 0x85, 0x67, 0xf1, 0x51, 0x96, 0xe0, 0x44, + 0xba, 0x76, 0xf4, 0x4e, 0xa0, 0x2b, 0xb0, 0x6e, 0xe8, 0xd9, 0xb1, 0xd3, 0xcd, 0x85, 0xd0, 0x45, + 0x70, 0x70, 0x1c, 0x94, 0xcc, 0x7e, 0x6b, 0x81, 0x19, 0x07, 0xdd, 0x05, 0x91, 0xc2, 0x78, 0x32, + 0x72, 0x09, 0x62, 0x30, 0xf0, 0x73, 0x7b, 0xbc, 0x5e, 0x7d, 0x3d, 0xfe, 0x0d, 0x8b, 0xef, 0x31, + 0xdb, 0x8e, 0x28, 0x20, 0xae, 0x0e, 0xe0, 0x7d, 0x63, 0x79, 0x05, 0x1b, 0x13, 0x8a, 0x8d, 0x15 +}; + +static unsigned char rsa_e_4096[] = { + 0x01, 0x00, 0x01 +}; + +static unsigned char rsa_p_4096[] = { + 0xff, 0x0f, 0x4f, 0x6c, 0xdd, 0x59, 0xd8, 0x48, 0x87, 0xc3, 0x24, 0x04, 0x87, 0x63, 0xbe, 0xcd, + 0xa6, 0x51, 0xb6, 0xb8, 0xda, 0x31, 0x8f, 0xb0, 0xf7, 0x29, 0x08, 0x28, 0x60, 0xb0, 0xb1, 0x52, + 0xe4, 0x73, 0xf1, 0xdb, 0x10, 0xe3, 0xbc, 0xfc, 0x2d, 0x88, 0x43, 0xab, 0x2a, 0x2e, 0x41, 0x80, + 0x0f, 0x25, 0x62, 0x53, 0x8f, 0x09, 0x82, 0xd1, 0xe4, 0x12, 0xe3, 0x9f, 0xae, 0xe9, 0x5b, 0xe4, + 0x89, 0x97, 0xf7, 0x40, 0x0c, 0x78, 0x86, 0xd1, 0x23, 0xe7, 0xd3, 0x45, 0xc9, 0x15, 0xf8, 0xbf, + 0xe9, 0x3d, 0x44, 0x57, 0x21, 0x61, 0x62, 0xe1, 0xad, 0x9d, 0x28, 0x5c, 0x99, 0xfc, 0xec, 0xe1, + 0xcb, 0x93, 0x70, 0x28, 0x8d, 0xc2, 0x97, 0xc4, 0xc4, 0xaa, 0xb1, 0xe3, 0xb6, 0x61, 0x84, 0x0c, + 0x03, 0xc9, 0xf7, 0x96, 0xdf, 0x04, 0xdc, 0x15, 0x94, 0x35, 0x60, 0xfa, 0xe7, 0xc4, 0xc1, 0xc7, + 0x80, 0xfb, 0xa6, 0xa6, 0x3e, 0x00, 0x42, 0x4a, 0x51, 0x91, 0xd3, 0x32, 0xee, 0x60, 0x2a, 0xda, + 0x13, 0xa9, 0x5b, 0xf8, 0x8a, 0xcd, 0x4a, 0x80, 0x23, 0x3a, 0x77, 0xf7, 0x10, 0xdf, 0x4e, 0x13, + 0x6e, 0xb6, 0x24, 0xe5, 0xd6, 0x97, 0x0d, 0x6e, 0xe8, 0xb3, 0xfd, 0x8a, 0x3b, 0xdb, 0x66, 0x8b, + 0x8a, 0x49, 0x56, 0xfa, 0xff, 0x16, 0xb6, 0x6c, 0xea, 0xc1, 0xed, 0xbe, 0x54, 0x3c, 0x5f, 0x28, + 0x4a, 0x62, 0x15, 0x9c, 0x71, 0xc0, 0xce, 0xa5, 0x59, 0x0f, 0x53, 0xf3, 0xa1, 0xf5, 0x38, 0x04, + 0x90, 0xa8, 0x88, 0x6d, 0x90, 0xf4, 0x61, 0xdf, 0xb2, 0xd1, 0x8f, 0x8e, 0x48, 0x68, 0x19, 0xd0, + 0xd8, 0x3b, 0x9f, 0xbe, 0xbe, 0x56, 0x12, 0xf9, 0x6e, 0x1a, 0x6d, 0xbc, 0xac, 0xa5, 0xc3, 0xb6, + 0x53, 0x1e, 0xed, 0x57, 0xfd, 0x53, 0xe9, 0x9d, 0xf7, 0xe3, 0xac, 0xe6, 0xe8, 0x87, 0xc5, 0xa7 +}; + +static unsigned char rsa_q_4096[] = { + 0xe8, 0x98, 0x10, 0x31, 0x2a, 0xde, 0xbf, 0xa0, 0xec, 0xbf, 0x77, 0xfd, 0x5d, 0x8e, 0x0e, 0xf7, + 0xa2, 0x81, 0xc9, 0xc1, 0x98, 0xde, 0x5c, 0x22, 0x8b, 0x7d, 0x9f, 0xf3, 0x7a, 0x41, 0xc9, 0x2b, + 0xa7, 0xbc, 0x7f, 0xcf, 0x41, 0x6d, 0xf8, 0x88, 0xbd, 0x90, 0x17, 0x9e, 0xc9, 0xdc, 0x79, 0x85, + 0x20, 0x97, 0x87, 0x06, 0xf4, 0x39, 0xf6, 0x6e, 0x47, 0x0a, 0x74, 0xe0, 0x83, 0x74, 0x7c, 0xc8, + 0x62, 0xe9, 0x64, 0x1c, 0xde, 0x8a, 0x2f, 0x58, 0x1d, 0xe7, 0x11, 0xb1, 0xb0, 0xf1, 0x78, 0x58, + 0x4f, 0xa1, 0x17, 0x97, 0xfc, 0x81, 0x2c, 0x11, 0x53, 0x3d, 0x43, 0x32, 0xb7, 0xd9, 0xb9, 0x4e, + 0x5b, 0x2b, 0xa8, 0x02, 0x03, 0x4c, 0x18, 0xd9, 0x8c, 0xa0, 0x2e, 0x5f, 0x22, 0xbe, 0x2e, 0x4a, + 0x9e, 0x29, 0xf6, 0x38, 0x54, 0x53, 0x14, 0xdf, 0x1b, 0x06, 0xec, 0x6c, 0x27, 0x2b, 0x8c, 0x55, + 0x22, 0x47, 0xcd, 0x90, 0xf5, 0xe1, 0x6f, 0xfc, 0x63, 0xa3, 0xa2, 0xc3, 0xe7, 0x22, 0xa7, 0x9a, + 0x96, 0x7f, 0xec, 0x24, 0xdd, 0xc5, 0xc0, 0x75, 0xe0, 0x31, 0x87, 0xe6, 0xbb, 0x6d, 0x6b, 0x78, + 0x43, 0x8b, 0x8f, 0xc4, 0x1c, 0x5e, 0xd7, 0x22, 0x50, 0x66, 0x4a, 0x6a, 0x08, 0xbe, 0xaf, 0x06, + 0xfd, 0x41, 0xbf, 0xc8, 0xab, 0x54, 0xa0, 0x0f, 0x5b, 0x16, 0x8a, 0xc8, 0x91, 0x65, 0x3e, 0x2a, + 0xb7, 0xbb, 0x3d, 0xff, 0xe3, 0xc9, 0xb9, 0xcf, 0x64, 0x12, 0xc5, 0x7d, 0x3c, 0x5a, 0xbc, 0x53, + 0x00, 0xf0, 0xeb, 0x7d, 0x2b, 0x03, 0xec, 0xfd, 0x56, 0x8d, 0x1c, 0xed, 0x8e, 0xd4, 0x23, 0xfe, + 0xe7, 0x98, 0xd4, 0xe7, 0x58, 0xdb, 0xd9, 0x00, 0x6e, 0xbb, 0x91, 0xc3, 0x7d, 0x2c, 0x87, 0xa6, + 0xe3, 0x6d, 0x60, 0xec, 0x6b, 0xa9, 0x1e, 0x0b, 0xf7, 0x7b, 0xd8, 0xa8, 0xdf, 0x2a, 0x50, 0x6f +}; + +static unsigned char rsa_dp_4096[] = { + 0xec, 0x30, 0x31, 0x4c, 0x8e, 0x6d, 0x74, 0x6b, 0x35, 0xcc, 0xee, 0xbd, 0x82, 0xe2, 0x4a, 0xfe, + 0x04, 0xd6, 0x06, 0x6e, 0x87, 0x1e, 0xfe, 0x00, 0xd1, 0xdf, 0x9d, 0x3e, 0x46, 0xcb, 0x58, 0x69, + 0x7a, 0x44, 0x23, 0xe2, 0xc8, 0x71, 0x1b, 0xc0, 0x2a, 0x29, 0xd4, 0xff, 0xdb, 0xbf, 0x99, 0xc8, + 0x0c, 0x3e, 0x82, 0x1e, 0xfe, 0x85, 0xc0, 0x2e, 0xbd, 0x15, 0x00, 0xd4, 0x0e, 0x14, 0xea, 0x93, + 0x67, 0x16, 0xe2, 0x4e, 0xdd, 0x3d, 0x7f, 0x1a, 0x8c, 0x35, 0x50, 0xdf, 0x7e, 0xa6, 0x6a, 0x02, + 0xcc, 0xe9, 0x7f, 0x2f, 0x70, 0x29, 0xce, 0x77, 0x4d, 0x5e, 0x0a, 0xd2, 0x35, 0x86, 0x91, 0x95, + 0x45, 0xfe, 0xf2, 0x0d, 0x9b, 0xb8, 0x66, 0xf2, 0x3f, 0x6c, 0x11, 0xee, 0xdc, 0x24, 0xd1, 0x32, + 0x8f, 0x0f, 0xa7, 0xc6, 0x7e, 0x1e, 0xf1, 0xee, 0xc9, 0x9f, 0xe4, 0x7e, 0x73, 0xc1, 0x2f, 0xf0, + 0x9e, 0xf0, 0x6a, 0x11, 0xe7, 0xb8, 0x35, 0xaa, 0xbc, 0x7e, 0x5d, 0x24, 0xfc, 0xb8, 0xf0, 0xf5, + 0xa0, 0xdf, 0x63, 0xdb, 0x74, 0x2d, 0x46, 0xa0, 0x01, 0xff, 0x52, 0xb7, 0xe7, 0x57, 0xe1, 0xe4, + 0xfc, 0xd0, 0x8e, 0xba, 0x87, 0x4c, 0xb9, 0x93, 0xca, 0xc9, 0x62, 0x2f, 0x6f, 0xde, 0x6b, 0xc7, + 0x2b, 0xf7, 0x5e, 0x24, 0x6f, 0xb3, 0x88, 0x9a, 0xb3, 0x89, 0x81, 0xae, 0x8e, 0x32, 0x99, 0xab, + 0xa5, 0xb5, 0xce, 0x6d, 0x60, 0xa9, 0x3a, 0xb2, 0xc3, 0x15, 0xfe, 0x97, 0xcd, 0x92, 0x56, 0x9d, + 0x63, 0x97, 0xad, 0x3e, 0x48, 0xcd, 0x05, 0x15, 0x31, 0x71, 0xfd, 0x8d, 0xb4, 0x5f, 0x32, 0x08, + 0xc3, 0x33, 0xf3, 0x69, 0x9e, 0xb7, 0xf6, 0x3a, 0x24, 0x4b, 0x34, 0xf3, 0x52, 0xac, 0xed, 0xdf, + 0x18, 0x79, 0xbb, 0x2f, 0x8f, 0xd6, 0xf4, 0xae, 0xe3, 0xae, 0x61, 0x9e, 0x32, 0x16, 0x08, 0x61 +}; + +static unsigned char rsa_dq_4096[] = { + 0xb8, 0x1a, 0x74, 0xe6, 0x96, 0x0a, 0x4e, 0x1f, 0xf0, 0x84, 0xf5, 0x52, 0xe4, 0xd4, 0x66, 0xe0, + 0x78, 0x0e, 0xc7, 0x45, 0xa7, 0xdc, 0x89, 0x8d, 0x06, 0x60, 0x5f, 0x54, 0xf7, 0x36, 0x4f, 0x27, + 0x70, 0xd3, 0x71, 0x4e, 0xf9, 0x79, 0x34, 0x39, 0xf7, 0xe1, 0xaf, 0xf0, 0x8d, 0xd3, 0x27, 0x94, + 0xca, 0x61, 0x66, 0x0d, 0x89, 0x0e, 0xc0, 0x12, 0x35, 0xc4, 0xff, 0x12, 0x1e, 0xba, 0xfb, 0x72, + 0x19, 0x68, 0xa7, 0x47, 0x7a, 0x96, 0x62, 0x37, 0x1b, 0x24, 0x25, 0x0b, 0x43, 0x05, 0x3e, 0xbe, + 0x97, 0xf8, 0xe8, 0x95, 0xf2, 0xd5, 0xc3, 0xad, 0xca, 0xf7, 0x38, 0xd3, 0x52, 0x56, 0xd1, 0xa8, + 0x45, 0xdd, 0xde, 0x54, 0x09, 0x8c, 0x18, 0x37, 0x4a, 0x6a, 0x17, 0x8a, 0x52, 0x13, 0xba, 0xcc, + 0x71, 0x38, 0xc1, 0x9d, 0x80, 0x91, 0x6a, 0x79, 0xd6, 0x08, 0xba, 0xe6, 0x38, 0x72, 0xed, 0xd7, + 0x0d, 0x15, 0x4c, 0x8f, 0x2b, 0x30, 0x4f, 0xd5, 0xb4, 0x80, 0x77, 0x7b, 0x1c, 0xde, 0x7f, 0x4f, + 0x8b, 0x44, 0xa2, 0x03, 0xe4, 0x4e, 0x7c, 0xb2, 0x50, 0xcc, 0xa3, 0xc7, 0x6c, 0x1f, 0x85, 0xeb, + 0x61, 0x7b, 0x7c, 0x46, 0x3c, 0x36, 0x8d, 0x8e, 0xa9, 0x98, 0xed, 0xd9, 0xd4, 0x26, 0x2a, 0xa0, + 0x1b, 0xa2, 0x09, 0x4d, 0xaa, 0xdf, 0x86, 0xf9, 0xe0, 0x9d, 0x8d, 0x28, 0x88, 0x7d, 0x5c, 0xa1, + 0xaf, 0x60, 0x54, 0x08, 0xd1, 0xa2, 0x80, 0xa2, 0xb9, 0x91, 0x6a, 0x24, 0x60, 0xbb, 0x69, 0x49, + 0x41, 0xfb, 0x70, 0x4a, 0x58, 0xdb, 0xf8, 0x9f, 0xe5, 0xfc, 0x38, 0x23, 0x88, 0xe4, 0x3d, 0xc1, + 0xac, 0x4b, 0x7a, 0x69, 0xcc, 0x19, 0xe8, 0x3f, 0xc1, 0x66, 0x52, 0x50, 0x2c, 0x2a, 0x2d, 0x0d, + 0x5a, 0x02, 0xdf, 0xaf, 0x02, 0xe0, 0x8f, 0xd9, 0xe5, 0x00, 0x70, 0x53, 0xea, 0xa0, 0xb1, 0x9d +}; + +static unsigned char rsa_qinv_4096[] = { + 0x11, 0xc1, 0x35, 0xf3, 0xe0, 0x74, 0x80, 0x68, 0x32, 0xdd, 0x15, 0xdb, 0x92, 0x72, 0xad, 0xd8, + 0xfd, 0xfe, 0x78, 0xee, 0xfd, 0x8a, 0xaa, 0xd4, 0x47, 0x07, 0xc3, 0xcf, 0x35, 0xbd, 0x23, 0x3d, + 0x2b, 0x09, 0xed, 0xbe, 0xb6, 0x3d, 0xc1, 0xb7, 0x25, 0x79, 0x5e, 0x0c, 0x7c, 0x25, 0x2c, 0x8f, + 0x98, 0x34, 0x19, 0xc7, 0xdf, 0x74, 0x67, 0x6a, 0x2e, 0x3b, 0x99, 0x3d, 0x41, 0xee, 0x44, 0xe8, + 0xc5, 0x75, 0xc2, 0x05, 0xdc, 0x85, 0x04, 0x59, 0x45, 0x14, 0x70, 0xc2, 0x9c, 0xa8, 0xa9, 0x2b, + 0x04, 0x65, 0xe1, 0xba, 0x83, 0x5e, 0x03, 0x04, 0x78, 0xe4, 0x16, 0x2d, 0x14, 0xfa, 0x10, 0xeb, + 0xe4, 0x3e, 0x6d, 0x75, 0xb1, 0xe5, 0xc5, 0xe7, 0x98, 0x69, 0x9a, 0x1b, 0xab, 0x87, 0x05, 0x51, + 0x84, 0x73, 0x31, 0xd5, 0x61, 0x67, 0xdc, 0x70, 0xce, 0x12, 0xdc, 0x53, 0xa5, 0xe6, 0x12, 0xb2, + 0x85, 0x00, 0x14, 0x6f, 0x56, 0x5c, 0x35, 0xc7, 0xd0, 0xea, 0x51, 0xf7, 0xba, 0xe4, 0x6b, 0x13, + 0x0c, 0x4d, 0x3d, 0x82, 0xe0, 0x7b, 0xac, 0x4b, 0x7e, 0xfb, 0x95, 0x47, 0xa3, 0x90, 0x84, 0xdc, + 0x9b, 0xf1, 0x4a, 0x36, 0x85, 0x7a, 0x5e, 0x9e, 0x74, 0x59, 0x1c, 0x59, 0xaa, 0x7e, 0x30, 0x5b, + 0x0c, 0x03, 0x3a, 0xb3, 0x80, 0xc5, 0x0b, 0xf4, 0x04, 0x41, 0x21, 0x77, 0xdc, 0x89, 0x10, 0x09, + 0x32, 0xa2, 0xd3, 0xa8, 0xb2, 0x3f, 0x9e, 0xc8, 0x62, 0x68, 0x59, 0x83, 0x68, 0xf3, 0xe4, 0x1f, + 0x20, 0x64, 0x0e, 0x2c, 0x18, 0x5a, 0xd1, 0x16, 0x02, 0x1c, 0x73, 0x4e, 0xc4, 0x92, 0x79, 0x56, + 0x9f, 0x66, 0x7c, 0xa6, 0xf2, 0x5e, 0xb5, 0x04, 0xf6, 0xa2, 0xf6, 0x59, 0xe2, 0x8c, 0x85, 0x95, + 0x62, 0xd6, 0x20, 0x8d, 0x3d, 0x87, 0x88, 0xa1, 0xa2, 0xea, 0x68, 0xe1, 0x29, 0x99, 0xd3, 0x7e +}; + +static unsigned char rsa_d_4096[] = { + 0x15, 0x49, 0x6c, 0x18, 0x59, 0x19, 0x8d, 0x47, 0xa9, 0xf4, 0x83, 0xd9, 0x13, 0xa8, 0x60, 0xb7, + 0xcf, 0x53, 0x9d, 0xe1, 0xe8, 0xb2, 0x90, 0x3b, 0x2e, 0x9a, 0xd4, 0xed, 0x7f, 0xce, 0x16, 0x92, + 0xcb, 0xa4, 0x89, 0x38, 0xe8, 0x88, 0x1d, 0x7c, 0x7f, 0x8a, 0xdf, 0xa2, 0x7f, 0xf5, 0xcd, 0x18, + 0xd4, 0x51, 0xf7, 0x31, 0x8b, 0x54, 0x19, 0x0d, 0xfc, 0xfe, 0x87, 0x8b, 0x62, 0x94, 0x0c, 0xe2, + 0x50, 0x23, 0xbe, 0x22, 0xda, 0x5c, 0xbf, 0x00, 0xc7, 0xce, 0x0b, 0x1d, 0x0d, 0x9b, 0x74, 0x2e, + 0xad, 0xcd, 0x80, 0x2b, 0x69, 0x1b, 0x92, 0x86, 0xe9, 0x5b, 0x9e, 0x3a, 0xf2, 0x66, 0xd1, 0x64, + 0x93, 0xcb, 0x72, 0xb7, 0x86, 0x7b, 0x32, 0x4a, 0xeb, 0x52, 0x75, 0x51, 0xb4, 0x5f, 0xb0, 0x23, + 0x53, 0xc8, 0x40, 0x60, 0xc8, 0x2a, 0x40, 0x98, 0xb2, 0x27, 0x9c, 0xea, 0x21, 0xb0, 0x71, 0x53, + 0xf8, 0x64, 0x3b, 0xd9, 0x6e, 0xba, 0xca, 0xeb, 0x77, 0xdf, 0xc9, 0x65, 0xaa, 0xdb, 0xd9, 0x92, + 0xda, 0x76, 0x3d, 0xf6, 0x91, 0xbd, 0xe1, 0x52, 0x8c, 0x09, 0x0e, 0x2d, 0x42, 0xa7, 0x33, 0x57, + 0xf5, 0x4c, 0xe6, 0x78, 0xb4, 0x89, 0xfe, 0x1f, 0xcc, 0xab, 0x45, 0xb0, 0xae, 0xc0, 0x1f, 0x16, + 0xcb, 0x2f, 0x6d, 0xd1, 0x66, 0x36, 0x17, 0x72, 0xcd, 0x8e, 0xf8, 0x52, 0xf5, 0xb3, 0x88, 0xd9, + 0x18, 0xa5, 0x76, 0x07, 0x1c, 0x97, 0xb6, 0xbb, 0x56, 0xa9, 0xee, 0xab, 0x7e, 0xa1, 0x6a, 0x21, + 0x43, 0xb5, 0x68, 0xd7, 0x5a, 0xd4, 0x5c, 0xc8, 0xaa, 0xd9, 0x8f, 0xaf, 0xe9, 0x8d, 0x37, 0xac, + 0xde, 0x21, 0xfc, 0xdd, 0xed, 0x75, 0xcc, 0x35, 0x87, 0x11, 0x84, 0x6c, 0xfd, 0x67, 0xef, 0x18, + 0x55, 0xa0, 0x62, 0xa3, 0x13, 0x5e, 0x66, 0x83, 0xcd, 0x82, 0xcf, 0xe9, 0xd1, 0x1e, 0xa2, 0x89, + 0x5c, 0xe8, 0x67, 0x2f, 0x7c, 0x80, 0x18, 0x6f, 0x9d, 0xcc, 0x4f, 0x6f, 0xfe, 0x33, 0x97, 0x5b, + 0xc2, 0x38, 0xf3, 0x22, 0xdb, 0xce, 0x47, 0x6b, 0x0e, 0xba, 0x85, 0x5a, 0x67, 0x97, 0x21, 0xbc, + 0xea, 0xa2, 0xae, 0x86, 0x82, 0x71, 0xd3, 0xb3, 0xa2, 0x8e, 0xc0, 0x38, 0xfd, 0xfe, 0x76, 0x3c, + 0x19, 0x95, 0x50, 0x6c, 0xc0, 0x48, 0xf2, 0x33, 0xae, 0x54, 0xde, 0x36, 0x10, 0xcc, 0x99, 0xea, + 0x3b, 0xec, 0xdc, 0x35, 0xa5, 0xa0, 0x59, 0x32, 0xd4, 0x38, 0xc2, 0x31, 0xf4, 0xbc, 0xa9, 0x4b, + 0xbb, 0xdb, 0x00, 0x84, 0x44, 0x2f, 0x69, 0x7d, 0xf6, 0xd4, 0x9c, 0x5f, 0x18, 0xbc, 0x94, 0x07, + 0x1b, 0x72, 0xf8, 0x97, 0xac, 0xf1, 0x2f, 0xd1, 0x1c, 0xa4, 0xa6, 0x11, 0x54, 0x52, 0x29, 0xf8, + 0x12, 0x3c, 0x3f, 0x1b, 0x07, 0x9a, 0x70, 0x7a, 0x5f, 0x68, 0xd8, 0x1a, 0xd3, 0xbd, 0x3b, 0x3d, + 0xfa, 0x62, 0x66, 0xf2, 0x77, 0xe7, 0x40, 0x39, 0x18, 0x34, 0x66, 0x77, 0xd2, 0x2b, 0x5b, 0x6d, + 0x7a, 0x1e, 0x89, 0x30, 0xdd, 0xed, 0x38, 0xab, 0xdd, 0x28, 0x7b, 0xf2, 0xcb, 0xc1, 0xd4, 0x2c, + 0x5b, 0xc6, 0xf5, 0x75, 0x89, 0xdd, 0x27, 0x1c, 0x03, 0x10, 0x37, 0x61, 0xb6, 0xd0, 0xb3, 0xbf, + 0x4a, 0xbc, 0x47, 0x37, 0xf0, 0x67, 0xd8, 0x0b, 0xfb, 0xe0, 0x34, 0x71, 0x62, 0xfb, 0x18, 0x86, + 0x03, 0x33, 0x25, 0x6f, 0x97, 0x4a, 0x48, 0xf1, 0x36, 0xd7, 0x60, 0x1c, 0x17, 0x5e, 0x17, 0xcb, + 0xc3, 0x1a, 0x49, 0x4a, 0xf3, 0xe3, 0x86, 0x5e, 0xc4, 0x16, 0x61, 0x5c, 0x80, 0x7a, 0x4d, 0x81, + 0x95, 0x8e, 0xa8, 0x15, 0x32, 0x2f, 0x46, 0x8c, 0x89, 0xe6, 0x2c, 0x75, 0x11, 0x16, 0xd5, 0xea, + 0xbf, 0x0c, 0x21, 0x75, 0x3a, 0xad, 0x9a, 0xd1, 0x3e, 0xd8, 0x4d, 0xee, 0x89, 0xe3, 0x6b, 0x51 +}; + +static unsigned char rsa_n_4096[] = { + 0xe7, 0xbd, 0x61, 0x33, 0xc2, 0xd8, 0x4c, 0x41, 0xa0, 0x3d, 0xd2, 0xa6, 0xad, 0x39, 0x2b, 0x62, + 0x26, 0x3f, 0x7f, 0xa3, 0xbe, 0xdf, 0x35, 0xd3, 0x62, 0x67, 0x3b, 0x09, 0xe5, 0x9d, 0xf4, 0x21, + 0x6f, 0x0b, 0xf1, 0x9a, 0x5a, 0xe0, 0x72, 0x80, 0xcf, 0x27, 0x99, 0x25, 0xea, 0x3d, 0x73, 0x70, + 0x7f, 0x03, 0x61, 0x9d, 0xca, 0x25, 0xf2, 0xd2, 0x29, 0x04, 0x1a, 0xf5, 0x08, 0xa6, 0xac, 0xc0, + 0x6d, 0x1f, 0x0e, 0x0e, 0xfd, 0x6e, 0x73, 0xe7, 0x1d, 0x60, 0x92, 0x13, 0xc3, 0x20, 0x39, 0x95, + 0x9a, 0x1e, 0x31, 0x07, 0x07, 0x45, 0x62, 0x97, 0xe4, 0xe4, 0x41, 0x98, 0xf2, 0x4c, 0x06, 0x9b, + 0xb1, 0x13, 0x28, 0x70, 0xa8, 0x2c, 0x99, 0x59, 0x8a, 0x85, 0x0b, 0x92, 0xde, 0x35, 0x9a, 0x68, + 0x9b, 0x9f, 0x8f, 0x70, 0x1e, 0x68, 0x22, 0x25, 0x32, 0xdf, 0x78, 0xac, 0xc3, 0x0b, 0x2f, 0x4e, + 0x26, 0x1c, 0x6a, 0xb9, 0x2d, 0x98, 0xa6, 0x48, 0x94, 0xce, 0x37, 0x01, 0x08, 0x0f, 0x28, 0x42, + 0x2b, 0x97, 0x93, 0xae, 0x56, 0xf0, 0xa6, 0xb7, 0x41, 0x4d, 0x26, 0x33, 0x67, 0xc7, 0xc8, 0x2b, + 0xe9, 0xc0, 0xe2, 0x21, 0x77, 0xb1, 0xde, 0x0e, 0x68, 0x3b, 0x4b, 0x85, 0xb7, 0x92, 0x5d, 0x2b, + 0x21, 0xc6, 0x35, 0x72, 0x4e, 0xe7, 0x93, 0x83, 0xb3, 0x30, 0xba, 0x82, 0xe4, 0x8c, 0xc7, 0xe4, + 0xd8, 0xfc, 0x5f, 0x1c, 0x2d, 0x89, 0x69, 0x6b, 0xe7, 0x0c, 0xa4, 0xe3, 0x23, 0x6b, 0x5d, 0x7f, + 0xa7, 0x26, 0xce, 0x5d, 0x07, 0xd0, 0x03, 0xf4, 0xc2, 0x02, 0x26, 0x2a, 0x3c, 0xc6, 0x0c, 0x55, + 0xfa, 0x2a, 0xfe, 0x20, 0x13, 0xe3, 0xd5, 0x9d, 0xd2, 0x5f, 0x67, 0x86, 0xf7, 0x88, 0xc8, 0x0c, + 0x72, 0xad, 0x83, 0x4b, 0x44, 0xf4, 0x00, 0xc6, 0x2a, 0xce, 0x64, 0x37, 0x27, 0xfe, 0x1d, 0x43, + 0xb5, 0xb8, 0x37, 0xa3, 0xa1, 0xcd, 0xa3, 0xfa, 0x0c, 0xbf, 0x0c, 0x1d, 0xb0, 0xb4, 0xcd, 0xe9, + 0xc0, 0xc6, 0xcd, 0x5a, 0xef, 0x9f, 0x9f, 0x56, 0x94, 0x11, 0x7b, 0x95, 0x01, 0xa0, 0x09, 0x61, + 0x4e, 0x6d, 0x0c, 0x81, 0xb5, 0x80, 0x68, 0x5b, 0x2b, 0x7e, 0x88, 0xdd, 0x5a, 0x96, 0xbb, 0x78, + 0x2a, 0x86, 0x65, 0x1a, 0x95, 0xe0, 0x69, 0x49, 0xb7, 0x78, 0x5f, 0x42, 0x68, 0x92, 0x5a, 0x3d, + 0xed, 0x51, 0x39, 0x73, 0x1b, 0xe9, 0xff, 0x44, 0xdf, 0xa4, 0xa4, 0x71, 0xbb, 0xa0, 0xf5, 0x47, + 0x63, 0x82, 0x85, 0x68, 0x41, 0xee, 0xb4, 0xf0, 0xa2, 0xba, 0x3c, 0xc5, 0x1e, 0x48, 0xd1, 0x8c, + 0xd5, 0x5b, 0x6a, 0xf2, 0x7f, 0xbe, 0x6f, 0x65, 0xdd, 0x30, 0x74, 0xac, 0x12, 0x41, 0x79, 0x47, + 0xac, 0x2c, 0x1e, 0x6d, 0x56, 0x9d, 0xdb, 0x0c, 0x27, 0x4a, 0xe9, 0x07, 0xa0, 0x34, 0xcf, 0xdd, + 0x42, 0x7e, 0x31, 0xe9, 0xed, 0xb4, 0x1d, 0x74, 0x24, 0x84, 0x80, 0x2d, 0xf9, 0x32, 0x6e, 0xd0, + 0x12, 0xf1, 0x75, 0xad, 0x1a, 0xed, 0x79, 0xe9, 0x80, 0xf8, 0x60, 0xf6, 0x73, 0x31, 0xad, 0x0d, + 0x23, 0xda, 0xad, 0x8a, 0x73, 0xab, 0x99, 0xc5, 0xe0, 0x52, 0x01, 0xf4, 0x88, 0x10, 0x69, 0x99, + 0xf3, 0x07, 0x2c, 0xb7, 0x67, 0x0c, 0xf3, 0xa6, 0x74, 0x4a, 0x73, 0x7d, 0xdb, 0x72, 0x22, 0xba, + 0xc1, 0xdd, 0xbc, 0x82, 0x2b, 0x6f, 0xaa, 0xcb, 0x7a, 0xfd, 0x50, 0x30, 0xb7, 0xf6, 0x72, 0x4b, + 0x71, 0xe0, 0xbd, 0xca, 0xf9, 0xd2, 0x4d, 0x42, 0x85, 0x40, 0x49, 0x9b, 0xba, 0x44, 0x7d, 0x98, + 0x16, 0x40, 0x32, 0xd0, 0x5f, 0x2a, 0xcf, 0x0d, 0x1a, 0x5b, 0x74, 0xd6, 0x4c, 0xb0, 0x0f, 0xe5, + 0x81, 0x01, 0x03, 0xfd, 0xd3, 0x14, 0xbc, 0xc5, 0x64, 0x4c, 0x29, 0xd4, 0x27, 0x08, 0xe3, 0x69 +}; + +static unsigned char dh_g_5[] = {0x05}; +static unsigned char dh_g_2[] = {0x02}; + +static unsigned char dh_p_768[] = { + 0xdd, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x01, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7 +}; + +static unsigned char dh_xa_768[] = { + 0xe0, 0x80, 0x86, 0x24, 0xe2, 0x20, 0x35, 0x97, 0xda, 0x0e, 0x68, 0x39, 0x01, 0xdd, 0x01, 0x87, + 0xa2, 0x47, 0xd2, 0x0d, 0xee, 0xfe, 0xdc, 0x5a, 0x37, 0x23, 0xeb, 0x3d, 0xe8, 0x1e, 0x39, 0x2d, + 0xbf, 0xa6, 0xe9, 0x17, 0x48, 0xe2, 0xea, 0xef, 0x1d, 0x2f, 0xe2, 0xaf, 0x3c, 0xbc, 0xae, 0xa7, + 0x42, 0x9b, 0xa5, 0x7d, 0x47, 0x8a, 0x20, 0xc5, 0xae, 0xa1, 0xe4, 0xe8, 0x1c, 0x05, 0xc0, 0x0a, + 0x05, 0xdc, 0x01, 0x74, 0xde, 0xad, 0xad, 0x07, 0xec, 0x6e, 0x6a, 0xc7, 0xee, 0x0f, 0xb8, 0xbe, + 0xaa, 0x46, 0x61, 0x8c, 0x12, 0x5a, 0xaf, 0x05, 0xff, 0x1b, 0x35, 0x6b, 0xe2, 0x3d, 0x48, 0x4f +}; + +static unsigned char dh_except_a_pubkey_768[] = { + 0xba, 0xe7, 0x3, 0x5b, 0xe4, 0x70, 0x8b, 0xe0, 0xe1, 0x92, 0x13, 0x86, 0x74, 0x4, 0xdc, 0x6a, + 0x0a, 0x2a, 0x20, 0xec, 0x6d, 0xbf, 0xf0, 0x46, 0xf7, 0x9, 0x2, 0xdb, 0x2f, 0x70, 0x11, 0xdd, + 0xb0, 0x13, 0xa2, 0xc1, 0x58, 0x74, 0x29, 0x19, 0x8d, 0x4a, 0x94, 0x80, 0x0b, 0xd7, 0x25, 0x85, + 0x10, 0x35, 0x97, 0x48, 0x6e, 0x70, 0x28, 0xae, 0x58, 0x97, 0x7d, 0xf2, 0x19, 0x27, 0x13, 0xab, + 0x47, 0x9b, 0x54, 0xdf, 0xc3, 0x5b, 0x5f, 0x5e, 0xb4, 0x64, 0x47, 0xce, 0x40, 0x3b, 0x0c, 0x4a, + 0x62, 0x52, 0xba, 0xc7, 0xf0, 0x36, 0x87, 0x9c, 0x79, 0x9a, 0x83, 0x11, 0x61, 0x0c, 0x1b, 0x6b +}; + +static unsigned char dh_except_b_pubkey_768[] = { + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x1, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7 +}; + +static unsigned char dh_share_key_768[] = { + 0x55, 0x9, 0x6b, 0x9c, 0xc6, 0x37, 0xa9, 0x9b, 0xdf, 0x67, 0x73, 0x7b, 0x46, 0xf9, 0x63, 0x47, + 0xcb, 0xa0, 0x57, 0x2a, 0xed, 0x97, 0x2f, 0xfe, 0x92, 0xf2, 0x20, 0x2c, 0x7e, 0xee, 0x7d, 0x11, + 0x78, 0xe6, 0xb9, 0x9, 0xd1, 0x94, 0xce, 0xd1, 0x5b, 0xf4, 0x44, 0xa9, 0xcb, 0x26, 0x2, 0x36, + 0x57, 0x2c, 0xa2, 0xbe, 0x37, 0xde, 0x86, 0x46, 0x20, 0x27, 0x9d, 0xa0, 0x2f, 0x4, 0xc1, 0xcd, + 0xff, 0x81, 0xe5, 0xe6, 0x2c, 0x9e, 0x39, 0x82, 0x31, 0x54, 0x33, 0xf8, 0xe7, 0xa0, 0xe5, 0x96, + 0xa4, 0x40, 0xc4, 0x44, 0xfe, 0x93, 0x66, 0xe2, 0xda, 0xaa, 0xb8, 0xfb, 0x2f, 0x3b, 0x8c, 0xce, +}; + +static unsigned char dh_p_1024[] = { + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x07, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x03, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x01, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7 +}; + +static unsigned char dh_xa_1024[] = { + 0x0f, 0x2a, 0x77, 0x25, 0x4b, 0xb3, 0xd3, 0x2d, 0xfd, 0x94, 0x8b, 0x53, 0x02, 0x21, 0x40, 0xd7, + 0x36, 0x76, 0xf3, 0xc8, 0xc0, 0x36, 0x3d, 0x23, 0xc9, 0xbd, 0x92, 0x51, 0xf2, 0x4b, 0x83, 0x15, + 0xe0, 0x80, 0x86, 0x24, 0xe2, 0x20, 0x35, 0x97, 0xda, 0x0e, 0x68, 0x39, 0x01, 0xdd, 0x01, 0x87, + 0xa2, 0x47, 0xd2, 0x0d, 0xee, 0xfe, 0xdc, 0x5a, 0x37, 0x23, 0xeb, 0x3d, 0xe8, 0x1e, 0x39, 0x2d, + 0xbf, 0xa6, 0xe9, 0x17, 0x48, 0xe2, 0xea, 0xef, 0x1d, 0x2f, 0xe2, 0xaf, 0x3c, 0xbc, 0xae, 0xa7, + 0x42, 0x9b, 0xa5, 0x7d, 0x47, 0x8a, 0x20, 0xc5, 0xae, 0xa1, 0xe4, 0xe8, 0x1c, 0x05, 0xc0, 0x0a, + 0x05, 0xdc, 0x01, 0x74, 0xde, 0xad, 0xad, 0x07, 0xec, 0x6e, 0x6a, 0xc7, 0xee, 0x0f, 0xb8, 0xbe, + 0xaa, 0x46, 0x61, 0x8c, 0x12, 0x5a, 0xaf, 0x05, 0xff, 0x1b, 0x35, 0x6b, 0xe2, 0x3d, 0x48, 0x4f +}; + +static unsigned char dh_except_a_pubkey_1024[] = { + 0x5d, 0xa6, 0x7, 0x56, 0x93, 0x89, 0xe5, 0x0f, 0x2a, 0xb5, 0x67, 0x3a, 0xcf, 0xc3, 0x82, 0x83, + 0xf6, 0x88, 0x52, 0x0b, 0xfc, 0x6a, 0x5b, 0x1a, 0x57, 0x87, 0x86, 0xef, 0xda, 0x47, 0xdb, 0x4d, + 0xba, 0xe7, 0x3, 0x5b, 0xe4, 0x70, 0x8b, 0xe0, 0xe1, 0x92, 0x13, 0x86, 0x74, 0x4, 0xdc, 0x6a, + 0x0a, 0x2a, 0x20, 0xec, 0x6d, 0xbf, 0xf0, 0x46, 0xf7, 0x9, 0x2, 0xdb, 0x2f, 0x70, 0x11, 0xdd, + 0xb0, 0x13, 0xa2, 0xc1, 0x58, 0x74, 0x29, 0x19, 0x8d, 0x4a, 0x94, 0x80, 0x0b, 0xd7, 0x25, 0x85, + 0x10, 0x35, 0x97, 0x48, 0x6e, 0x70, 0x28, 0xae, 0x58, 0x97, 0x7d, 0xf2, 0x19, 0x27, 0x13, 0xab, + 0x47, 0x9b, 0x54, 0xdf, 0xc3, 0x5b, 0x5f, 0x5e, 0xb4, 0x64, 0x47, 0xce, 0x40, 0x3b, 0x0c, 0x4a, + 0x62, 0x52, 0xba, 0xc7, 0xf0, 0x36, 0x87, 0x9c, 0x79, 0x9a, 0x83, 0x11, 0x61, 0x0c, 0x1b, 0x6b +}; + +static unsigned char dh_except_b_pubkey_1024[] = { + 0x4a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x7, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x3, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x1, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7 +}; + +static unsigned char dh_share_key_1024[] = { + 0xcc, 0x48, 0x97, 0xe4, 0x21, 0x65, 0xa6, 0x55, 0xb8, 0xf3, 0xb2, 0x7b, 0x91, 0xd7, 0xca, 0xb9, + 0x17, 0x58, 0x31, 0x71, 0xc0, 0xc9, 0x69, 0x1e, 0xf0, 0x9e, 0x3f, 0xe2, 0x37, 0x4, 0x2d, 0xa8, + 0x55, 0x9, 0x6b, 0x9c, 0xc6, 0x37, 0xa9, 0x9b, 0xdf, 0x67, 0x73, 0x7b, 0x46, 0xf9, 0x63, 0x47, + 0xcb, 0xa0, 0x57, 0x2a, 0xed, 0x97, 0x2f, 0xfe, 0x92, 0xf2, 0x20, 0x2c, 0x7e, 0xee, 0x7d, 0x11, + 0x78, 0xe6, 0xb9, 0x9, 0xd1, 0x94, 0xce, 0xd1, 0x5b, 0xf4, 0x44, 0xa9, 0xcb, 0x26, 0x2, 0x36, + 0x57, 0x2c, 0xa2, 0xbe, 0x37, 0xde, 0x86, 0x46, 0x20, 0x27, 0x9d, 0xa0, 0x2f, 0x4, 0xc1, 0xcd, + 0xff, 0x81, 0xe5, 0xe6, 0x2c, 0x9e, 0x39, 0x82, 0x31, 0x54, 0x33, 0xf8, 0xe7, 0xa0, 0xe5, 0x96, + 0xa4, 0x40, 0xc4, 0x44, 0xfe, 0x93, 0x66, 0xe2, 0xda, 0xaa, 0xb8, 0xfb, 0x2f, 0x3b, 0x8c, 0xce, +}; + +static unsigned char dh_p_1536[] = { + 0xe3,0x7d,0xa7,0x4a,0xcc,0xef,0xce,0xa6,0xde,0x1d,0x3d,0xc5,0x2b,0xaa,0x6b,0x83, + 0xec,0x87,0x60,0xcd,0xc6,0xe4,0x16,0x0d,0xe7,0xb9,0x20,0x0e,0x10,0x50,0x35,0x22, + 0xd6,0xdb,0xbf,0x6,0xcc,0x7b,0x8e,0xe1,0x68,0x38,0x76,0x5f,0x0a,0x68,0xa8,0xfd, + 0x3f,0x40,0x51,0x46,0x45,0x64,0x53,0x22,0xcf,0x8,0xe2,0xef,0xd2,0x6f,0x28,0x84, + 0x14,0xb3,0xa6,0x24,0x49,0x6f,0x49,0x6c,0x0a,0x13,0xb6,0x78,0x4f,0xa4,0xd0,0xc4, + 0x20,0x6c,0x7,0x4c,0x6b,0xf7,0x8c,0x72,0x16,0x6c,0x99,0xd2,0x44,0x9e,0x63,0x5, + 0xfc,0x3a,0xa9,0x33,0x16,0x0b,0xc4,0x1a,0xf0,0xc7,0x25,0xcd,0xc6,0x3a,0x8e,0x66, + 0xa2,0xeb,0x70,0xb9,0x59,0xd9,0xb7,0xdd,0x68,0x45,0x26,0x20,0xfa,0x58,0x6f,0xd6, + 0x3f,0xd8,0xf2,0x52,0xd5,0x3a,0x16,0x7,0xdd,0xb4,0x63,0x0c,0xfe,0x8,0x67,0xd0, + 0x9f,0x8a,0xe0,0xe9,0x25,0xa0,0x0e,0x5,0x8e,0xe5,0x56,0xa6,0xc3,0x5b,0x0b,0xb5, + 0x41,0x33,0xd0,0xdb,0x89,0xbd,0x3b,0xaf,0x33,0x7e,0xae,0xff,0x20,0xef,0xa9,0x3c, + 0xd7,0xb5,0x45,0x61,0x50,0x76,0x60,0x89,0x6a,0xbb,0x9c,0x3e,0xcb,0xcb,0xdb,0x0b, +}; + +static unsigned char dh_xa_1536[] = { + 0x56,0x68,0x23,0x22,0x49,0x24,0xf2,0x21,0xee,0x5f,0x12,0x46,0xe2,0xea,0x69,0x93, + 0x0,0xf5,0x10,0x1d,0x4d,0x96,0x7b,0xa4,0x9d,0xab,0xbe,0xdf,0x8e,0xcc,0xa5,0x0e, + 0x84,0x12,0x4e,0x77,0xc0,0x46,0x6b,0x51,0x11,0x46,0x4f,0x73,0x1e,0x1c,0x1c,0xd1, + 0x3,0xea,0x0e,0x11,0xdb,0xa3,0xa6,0x14,0xdb,0xdc,0x3e,0xc5,0x7f,0x7d,0x7a,0x69, + 0xa1,0x38,0x70,0x95,0xa5,0x2d,0x47,0xa3,0x0f,0xcf,0xf9,0x7c,0x2,0x4e,0x52,0x4c, + 0xd6,0x5b,0x9e,0xf3,0x7f,0x64,0x70,0x13,0x59,0x8e,0x44,0x31,0x92,0x1b,0xb4,0xaa, + 0xf9,0x64,0xfd,0xb7,0x3c,0x81,0xc0,0xf9,0x66,0x5d,0xff,0x9,0x3e,0x26,0xaf,0x1a, + 0xc0,0xd2,0xd9,0x7c,0x0e,0x6f,0x81,0x12,0x82,0x90,0x1b,0x37,0xb7,0x1a,0x7e,0x36, + 0x79,0x15,0xb1,0xe1,0xd5,0x2d,0x72,0xd4,0x47,0xf7,0x30,0x3c,0x17,0xe1,0x76,0x15, + 0xbc,0x17,0xdc,0x9d,0xd9,0xfc,0xfd,0xb6,0xe6,0xbd,0x8e,0x47,0x8d,0xbb,0xa8,0x8a, + 0xe7,0xe7,0x57,0xf2,0xd8,0x80,0x4c,0xdd,0xe7,0xaf,0x29,0xee,0x40,0x4e,0x2,0xad, + 0xec,0xb3,0x18,0x8e,0x4b,0x2d,0xd2,0x28,0x4e,0x58,0x85,0x29,0xe3,0x93,0x1b,0xa7, +}; + +static unsigned char dh_except_a_pubkey_1536[] = { + 0x97,0x1e,0x6d,0xf7,0xb1,0x2f,0xa7,0x82,0x9e,0x99,0x22,0xfb,0xf3,0x4e,0x2a,0x73, + 0xcc,0xd9,0x2b,0x10,0x1,0xfb,0xac,0xf1,0x81,0xfe,0x78,0x3d,0x23,0xb0,0xcf,0x5c, + 0x95,0x69,0x36,0xc0,0x99,0x6a,0xd2,0x9c,0xf0,0x85,0x8d,0xda,0x5d,0xba,0x8e,0x0f, + 0xa3,0xce,0xbe,0x9b,0xe8,0x3b,0xad,0x71,0xfd,0xfd,0x53,0x25,0xee,0x61,0x26,0x15, + 0x0a,0x46,0x9e,0xce,0x85,0xb1,0x5c,0xf1,0xa0,0x8f,0xe7,0x89,0xe3,0x4f,0x7c,0xea, + 0x18,0xd3,0xa9,0x44,0xce,0x35,0x9,0x86,0x80,0x8c,0x30,0x1,0xbc,0x6d,0xf6,0x6a, + 0x3a,0xa6,0xad,0xbe,0xfa,0x73,0x6b,0xb0,0x35,0x8c,0x63,0x80,0xb6,0x58,0x51,0x6e, + 0x4c,0x5d,0x4a,0xe9,0xa9,0x72,0x6,0x9f,0xa2,0x3e,0x64,0xaf,0x70,0x63,0xee,0x2a, + 0x5d,0x73,0xf3,0xdc,0xa3,0x32,0x0f,0x8,0x48,0xcf,0x13,0x80,0x0d,0xdb,0x91,0xdf, + 0x87,0x99,0xa4,0x8a,0x50,0xe9,0x75,0x43,0xfb,0x56,0xd7,0x89,0xc3,0x10,0x7e,0xd0, + 0xb7,0x46,0xd8,0x41,0x91,0xdf,0xb1,0x91,0x8e,0xc1,0x58,0xd7,0x7c,0x33,0x1e,0xb3, + 0xa3,0xda,0xcb,0xf5,0x0,0x76,0xe4,0xee,0x20,0xd6,0x9d,0x8a,0x28,0xa4,0xdb,0xf9, +}; + +static unsigned char dh_except_b_pubkey_1536[] = { + 0x44, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x9, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x4, 0xe8, 0x9a, 0xd2, 0x0, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x0, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x5, + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x7, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x3, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, +}; + +static unsigned char dh_share_key_1536[] = { + 0xaf, 0xd4, 0xf6, 0x45, 0x63, 0x21, 0x8d, 0x98, 0xc4, 0xab, 0x18, 0xd7, 0x2b, 0x3c, 0x1d, 0xde, + 0xe7, 0x1f, 0xe1, 0xc5, 0x79, 0x57, 0x60, 0x20, 0xfa, 0x99, 0xbd, 0x7b, 0xa2, 0x94, 0x0b, 0xa3, + 0xb4, 0xb3, 0x33, 0x4a, 0x2f, 0xd0, 0x17, 0x7, 0x2e, 0x70, 0x19, 0x84, 0x1f, 0x8e, 0xe9, 0x61, + 0xe5, 0x52, 0x3, 0x96, 0xea, 0xd8, 0xb6, 0x3, 0x9f, 0xc4, 0x3e, 0x23, 0x77, 0x17, 0x54, 0xfb, + 0x13, 0xf0, 0x3e, 0x9a, 0x27, 0x5d, 0x12, 0x99, 0x58, 0x8d, 0x41, 0x46, 0xd9, 0xc9, 0x29, 0xbd, + 0x40, 0xd1, 0x4f, 0xef, 0x63, 0x7b, 0x54, 0xe6, 0x59, 0x6d, 0xe2, 0x30, 0xe8, 0x2c, 0x2f, 0xf9, + 0x66, 0xa2, 0x12, 0xf5, 0x58, 0x61, 0xac, 0x43, 0xec, 0x7e, 0xf9, 0x2e, 0x27, 0x70, 0x35, 0x75, + 0xb4, 0x10, 0x29, 0xac, 0x0a, 0xab, 0x59, 0xb6, 0x68, 0x4c, 0x16, 0xaf, 0xf0, 0x4f, 0x21, 0xcd, + 0xcc, 0x48, 0x97, 0xe4, 0x21, 0x65, 0xa6, 0x55, 0xb8, 0xf3, 0xb2, 0x7b, 0x91, 0xd7, 0xca, 0xb9, + 0x17, 0x58, 0x31, 0x71, 0xc0, 0xc9, 0x69, 0x1e, 0xf0, 0x9e, 0x3f, 0xe2, 0x37, 0x4, 0x2d, 0xa8, + 0x55, 0x9, 0x6b, 0x9c, 0xc6, 0x37, 0xa9, 0x9b, 0xdf, 0x67, 0x73, 0x7b, 0x46, 0xf9, 0x63, 0x47, + 0xcb, 0xa0, 0x57, 0x2a, 0xed, 0x97, 0x2f, 0xfe, 0x92, 0xf2, 0x20, 0x2c, 0x7e, 0xee, 0x7d, 0x11, +}; + +static unsigned char dh_p_2048[] = { + 0xce, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x09, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x04, 0xe8, 0x9a, 0xd2, 0x00, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x00, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x05, + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x07, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x03, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x01, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7 +}; + +static unsigned char dh_xa_2048[] = { + 0x6b, 0x1f, 0xc4, 0x85, 0x98, 0xc3, 0x01, 0xda, 0x39, 0xf0, 0x1b, 0x76, 0x5d, 0x81, 0x1d, 0x1f, + 0xc9, 0x93, 0x95, 0xc1, 0xf8, 0xd1, 0x67, 0x2c, 0xd4, 0x0a, 0x67, 0xf0, 0x40, 0x86, 0x82, 0x7f, + 0x8f, 0x9d, 0x79, 0x04, 0xee, 0x4a, 0x54, 0xc9, 0x9c, 0x7f, 0xda, 0x15, 0x13, 0xc6, 0x95, 0xfb, + 0xfc, 0x7b, 0xe7, 0xd8, 0xde, 0x2a, 0xd8, 0xfd, 0xff, 0xdb, 0xa4, 0x7f, 0x4b, 0x37, 0x5d, 0x42, + 0xb6, 0x46, 0x4c, 0xbc, 0x34, 0x23, 0x99, 0x74, 0xf8, 0x80, 0x1b, 0xc1, 0x97, 0x34, 0xdf, 0x23, + 0x15, 0xa2, 0x8b, 0xec, 0xf3, 0x3e, 0x20, 0x93, 0x63, 0x88, 0x17, 0x70, 0x75, 0xbb, 0x9d, 0xb8, + 0x32, 0xb0, 0xae, 0xb5, 0x24, 0x6a, 0x86, 0xf6, 0xc1, 0x60, 0x41, 0xc4, 0xf4, 0x95, 0x6e, 0x10, + 0x2f, 0xd8, 0x58, 0x56, 0x42, 0x82, 0x71, 0x85, 0x19, 0xde, 0x91, 0xf0, 0x2f, 0x30, 0x0c, 0x63, + 0x0f, 0x2a, 0x77, 0x25, 0x4b, 0xb3, 0xd3, 0x2d, 0xfd, 0x94, 0x8b, 0x53, 0x02, 0x21, 0x40, 0xd7, + 0x36, 0x76, 0xf3, 0xc8, 0xc0, 0x36, 0x3d, 0x23, 0xc9, 0xbd, 0x92, 0x51, 0xf2, 0x4b, 0x83, 0x15, + 0xe0, 0x80, 0x86, 0x24, 0xe2, 0x20, 0x35, 0x97, 0xda, 0x0e, 0x68, 0x39, 0x01, 0xdd, 0x01, 0x87, + 0xa2, 0x47, 0xd2, 0x0d, 0xee, 0xfe, 0xdc, 0x5a, 0x37, 0x23, 0xeb, 0x3d, 0xe8, 0x1e, 0x39, 0x2d, + 0xbf, 0xa6, 0xe9, 0x17, 0x48, 0xe2, 0xea, 0xef, 0x1d, 0x2f, 0xe2, 0xaf, 0x3c, 0xbc, 0xae, 0xa7, + 0x42, 0x9b, 0xa5, 0x7d, 0x47, 0x8a, 0x20, 0xc5, 0xae, 0xa1, 0xe4, 0xe8, 0x1c, 0x05, 0xc0, 0x0a, + 0x05, 0xdc, 0x01, 0x74, 0xde, 0xad, 0xad, 0x07, 0xec, 0x6e, 0x6a, 0xc7, 0xee, 0x0f, 0xb8, 0xbe, + 0xaa, 0x46, 0x61, 0x8c, 0x12, 0x5a, 0xaf, 0x05, 0xff, 0x1b, 0x35, 0x6b, 0xe2, 0x3d, 0x48, 0x4f +}; + +static unsigned char dh_except_a_pubkey_2048[] = { + 0xa5, 0x24, 0x63, 0x20, 0xb2, 0x56, 0x9a, 0x94, 0x97, 0xf7, 0x88, 0x41, 0x35, 0xeb, 0x52, 0x37, + 0xa4, 0xf2, 0x74, 0x1b, 0x38, 0xe4, 0x4c, 0x8b, 0x4b, 0xd2, 0xa5, 0xad, 0xb8, 0x2f, 0x7b, 0x5a, + 0xfd, 0xbc, 0x9c, 0xe0, 0xea, 0x9e, 0x82, 0x3, 0x62, 0xe2, 0xdc, 0x6c, 0x56, 0x9, 0x2, 0x28, + 0xb8, 0x2d, 0xb8, 0x46, 0xaf, 0x3a, 0xf4, 0x51, 0xf7, 0x4d, 0xc4, 0xd9, 0xa9, 0x1d, 0x67, 0x9d, + 0x2b, 0x18, 0x56, 0x86, 0x2a, 0x3, 0x19, 0xe9, 0x6, 0xeb, 0x4a, 0x6f, 0x2a, 0x40, 0x28, 0xbb, + 0x3e, 0x87, 0xc1, 0xce, 0x39, 0x6e, 0x3b, 0x1f, 0xb0, 0x9, 0x33, 0x67, 0x19, 0x0e, 0x1a, 0xb2, + 0xb3, 0x7d, 0xd3, 0xe6, 0x33, 0xf4, 0x7c, 0x82, 0x73, 0x7b, 0xb6, 0x16, 0x55, 0xff, 0x76, 0xaf, + 0x7f, 0xc2, 0x42, 0x51, 0xa9, 0xad, 0x1e, 0x72, 0xc9, 0x63, 0xab, 0x41, 0x5a, 0x26, 0x32, 0x39, + 0x5d, 0xa6, 0x7, 0x56, 0x93, 0x89, 0xe5, 0x0f, 0x2a, 0xb5, 0x67, 0x3a, 0xcf, 0xc3, 0x82, 0x83, + 0xf6, 0x88, 0x52, 0x0b, 0xfc, 0x6a, 0x5b, 0x1a, 0x57, 0x87, 0x86, 0xef, 0xda, 0x47, 0xdb, 0x4d, + 0xba, 0xe7, 0x3, 0x5b, 0xe4, 0x70, 0x8b, 0xe0, 0xe1, 0x92, 0x13, 0x86, 0x74, 0x4, 0xdc, 0x6a, + 0x0a, 0x2a, 0x20, 0xec, 0x6d, 0xbf, 0xf0, 0x46, 0xf7, 0x9, 0x2, 0xdb, 0x2f, 0x70, 0x11, 0xdd, + 0xb0, 0x13, 0xa2, 0xc1, 0x58, 0x74, 0x29, 0x19, 0x8d, 0x4a, 0x94, 0x80, 0x0b, 0xd7, 0x25, 0x85, + 0x10, 0x35, 0x97, 0x48, 0x6e, 0x70, 0x28, 0xae, 0x58, 0x97, 0x7d, 0xf2, 0x19, 0x27, 0x13, 0xab, + 0x47, 0x9b, 0x54, 0xdf, 0xc3, 0x5b, 0x5f, 0x5e, 0xb4, 0x64, 0x47, 0xce, 0x40, 0x3b, 0x0c, 0x4a, + 0x62, 0x52, 0xba, 0xc7, 0xf0, 0x36, 0x87, 0x9c, 0x79, 0x9a, 0x83, 0x11, 0x61, 0x0c, 0x1b, 0x6b +}; + +static unsigned char dh_except_b_pubkey_2048[] = { + 0x44, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x9, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x4, 0xe8, 0x9a, 0xd2, 0x0, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x0, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x5, + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x7, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x3, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x1, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7 +}; + +static unsigned char dh_share_key_2048[] = { + 0xaf, 0xd4, 0xf6, 0x45, 0x63, 0x21, 0x8d, 0x98, 0xc4, 0xab, 0x18, 0xd7, 0x2b, 0x3c, 0x1d, 0xde, + 0xe7, 0x1f, 0xe1, 0xc5, 0x79, 0x57, 0x60, 0x20, 0xfa, 0x99, 0xbd, 0x7b, 0xa2, 0x94, 0x0b, 0xa3, + 0xb4, 0xb3, 0x33, 0x4a, 0x2f, 0xd0, 0x17, 0x7, 0x2e, 0x70, 0x19, 0x84, 0x1f, 0x8e, 0xe9, 0x61, + 0xe5, 0x52, 0x3, 0x96, 0xea, 0xd8, 0xb6, 0x3, 0x9f, 0xc4, 0x3e, 0x23, 0x77, 0x17, 0x54, 0xfb, + 0x13, 0xf0, 0x3e, 0x9a, 0x27, 0x5d, 0x12, 0x99, 0x58, 0x8d, 0x41, 0x46, 0xd9, 0xc9, 0x29, 0xbd, + 0x40, 0xd1, 0x4f, 0xef, 0x63, 0x7b, 0x54, 0xe6, 0x59, 0x6d, 0xe2, 0x30, 0xe8, 0x2c, 0x2f, 0xf9, + 0x66, 0xa2, 0x12, 0xf5, 0x58, 0x61, 0xac, 0x43, 0xec, 0x7e, 0xf9, 0x2e, 0x27, 0x70, 0x35, 0x75, + 0xb4, 0x10, 0x29, 0xac, 0x0a, 0xab, 0x59, 0xb6, 0x68, 0x4c, 0x16, 0xaf, 0xf0, 0x4f, 0x21, 0xcd, + 0xcc, 0x48, 0x97, 0xe4, 0x21, 0x65, 0xa6, 0x55, 0xb8, 0xf3, 0xb2, 0x7b, 0x91, 0xd7, 0xca, 0xb9, + 0x17, 0x58, 0x31, 0x71, 0xc0, 0xc9, 0x69, 0x1e, 0xf0, 0x9e, 0x3f, 0xe2, 0x37, 0x4, 0x2d, 0xa8, + 0x55, 0x9, 0x6b, 0x9c, 0xc6, 0x37, 0xa9, 0x9b, 0xdf, 0x67, 0x73, 0x7b, 0x46, 0xf9, 0x63, 0x47, + 0xcb, 0xa0, 0x57, 0x2a, 0xed, 0x97, 0x2f, 0xfe, 0x92, 0xf2, 0x20, 0x2c, 0x7e, 0xee, 0x7d, 0x11, + 0x78, 0xe6, 0xb9, 0x9, 0xd1, 0x94, 0xce, 0xd1, 0x5b, 0xf4, 0x44, 0xa9, 0xcb, 0x26, 0x2, 0x36, + 0x57, 0x2c, 0xa2, 0xbe, 0x37, 0xde, 0x86, 0x46, 0x20, 0x27, 0x9d, 0xa0, 0x2f, 0x4, 0xc1, 0xcd, + 0xff, 0x81, 0xe5, 0xe6, 0x2c, 0x9e, 0x39, 0x82, 0x31, 0x54, 0x33, 0xf8, 0xe7, 0xa0, 0xe5, 0x96, + 0xa4, 0x40, 0xc4, 0x44, 0xfe, 0x93, 0x66, 0xe2, 0xda, 0xaa, 0xb8, 0xfb, 0x2f, 0x3b, 0x8c, 0xce, +}; + +static unsigned char dh_p_3072[] = { + 0xce, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x09, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x04, 0xe8, 0x9a, 0xd2, 0x00, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x00, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x05, + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x07, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x03, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x01, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7, + 0xce, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x09, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x04, 0xe8, 0x9a, 0xd2, 0x00, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x00, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x05, +}; + +static unsigned char dh_xa_3072[] = { + 0x6b, 0x1f, 0xc4, 0x85, 0x98, 0xc3, 0x01, 0xda, 0x39, 0xf0, 0x1b, 0x76, 0x5d, 0x81, 0x1d, 0x1f, + 0xc9, 0x93, 0x95, 0xc1, 0xf8, 0xd1, 0x67, 0x2c, 0xd4, 0x0a, 0x67, 0xf0, 0x40, 0x86, 0x82, 0x7f, + 0x8f, 0x9d, 0x79, 0x04, 0xee, 0x4a, 0x54, 0xc9, 0x9c, 0x7f, 0xda, 0x15, 0x13, 0xc6, 0x95, 0xfb, + 0xfc, 0x7b, 0xe7, 0xd8, 0xde, 0x2a, 0xd8, 0xfd, 0xff, 0xdb, 0xa4, 0x7f, 0x4b, 0x37, 0x5d, 0x42, + 0xb6, 0x46, 0x4c, 0xbc, 0x34, 0x23, 0x99, 0x74, 0xf8, 0x80, 0x1b, 0xc1, 0x97, 0x34, 0xdf, 0x23, + 0x15, 0xa2, 0x8b, 0xec, 0xf3, 0x3e, 0x20, 0x93, 0x63, 0x88, 0x17, 0x70, 0x75, 0xbb, 0x9d, 0xb8, + 0x32, 0xb0, 0xae, 0xb5, 0x24, 0x6a, 0x86, 0xf6, 0xc1, 0x60, 0x41, 0xc4, 0xf4, 0x95, 0x6e, 0x10, + 0x2f, 0xd8, 0x58, 0x56, 0x42, 0x82, 0x71, 0x85, 0x19, 0xde, 0x91, 0xf0, 0x2f, 0x30, 0x0c, 0x63, + 0x0f, 0x2a, 0x77, 0x25, 0x4b, 0xb3, 0xd3, 0x2d, 0xfd, 0x94, 0x8b, 0x53, 0x02, 0x21, 0x40, 0xd7, + 0x36, 0x76, 0xf3, 0xc8, 0xc0, 0x36, 0x3d, 0x23, 0xc9, 0xbd, 0x92, 0x51, 0xf2, 0x4b, 0x83, 0x15, + 0xe0, 0x80, 0x86, 0x24, 0xe2, 0x20, 0x35, 0x97, 0xda, 0x0e, 0x68, 0x39, 0x01, 0xdd, 0x01, 0x87, + 0xa2, 0x47, 0xd2, 0x0d, 0xee, 0xfe, 0xdc, 0x5a, 0x37, 0x23, 0xeb, 0x3d, 0xe8, 0x1e, 0x39, 0x2d, + 0xbf, 0xa6, 0xe9, 0x17, 0x48, 0xe2, 0xea, 0xef, 0x1d, 0x2f, 0xe2, 0xaf, 0x3c, 0xbc, 0xae, 0xa7, + 0x42, 0x9b, 0xa5, 0x7d, 0x47, 0x8a, 0x20, 0xc5, 0xae, 0xa1, 0xe4, 0xe8, 0x1c, 0x05, 0xc0, 0x0a, + 0x05, 0xdc, 0x01, 0x74, 0xde, 0xad, 0xad, 0x07, 0xec, 0x6e, 0x6a, 0xc7, 0xee, 0x0f, 0xb8, 0xbe, + 0xaa, 0x46, 0x61, 0x8c, 0x12, 0x5a, 0xaf, 0x05, 0xff, 0x1b, 0x35, 0x6b, 0xe2, 0x3d, 0x48, 0x4f, + 0x6b, 0x1f, 0xc4, 0x85, 0x98, 0xc3, 0x01, 0xda, 0x39, 0xf0, 0x1b, 0x76, 0x5d, 0x81, 0x1d, 0x1f, + 0xc9, 0x93, 0x95, 0xc1, 0xf8, 0xd1, 0x67, 0x2c, 0xd4, 0x0a, 0x67, 0xf0, 0x40, 0x86, 0x82, 0x7f, + 0x8f, 0x9d, 0x79, 0x04, 0xee, 0x4a, 0x54, 0xc9, 0x9c, 0x7f, 0xda, 0x15, 0x13, 0xc6, 0x95, 0xfb, + 0xfc, 0x7b, 0xe7, 0xd8, 0xde, 0x2a, 0xd8, 0xfd, 0xff, 0xdb, 0xa4, 0x7f, 0x4b, 0x37, 0x5d, 0x42, + 0xb6, 0x46, 0x4c, 0xbc, 0x34, 0x23, 0x99, 0x74, 0xf8, 0x80, 0x1b, 0xc1, 0x97, 0x34, 0xdf, 0x23, + 0x15, 0xa2, 0x8b, 0xec, 0xf3, 0x3e, 0x20, 0x93, 0x63, 0x88, 0x17, 0x70, 0x75, 0xbb, 0x9d, 0xb8, + 0x32, 0xb0, 0xae, 0xb5, 0x24, 0x6a, 0x86, 0xf6, 0xc1, 0x60, 0x41, 0xc4, 0xf4, 0x95, 0x6e, 0x10, + 0x2f, 0xd8, 0x58, 0x56, 0x42, 0x82, 0x71, 0x85, 0x19, 0xde, 0x91, 0xf0, 0x2f, 0x30, 0x0c, 0x63, +}; + +static unsigned char dh_except_a_pubkey_3072[] = { + 0xa5, 0x24, 0x63, 0x20, 0xb2, 0x56, 0x9a, 0x94, 0x97, 0xf7, 0x88, 0x41, 0x35, 0xeb, 0x52, 0x37, + 0xa4, 0xf2, 0x74, 0x1b, 0x38, 0xe4, 0x4c, 0x8b, 0x4b, 0xd2, 0xa5, 0xad, 0xb8, 0x2f, 0x7b, 0x5a, + 0xfd, 0xbc, 0x9c, 0xe0, 0xea, 0x9e, 0x82, 0x3, 0x62, 0xe2, 0xdc, 0x6c, 0x56, 0x9, 0x2, 0x28, + 0xb8, 0x2d, 0xb8, 0x46, 0xaf, 0x3a, 0xf4, 0x51, 0xf7, 0x4d, 0xc4, 0xd9, 0xa9, 0x1d, 0x67, 0x9d, + 0x2b, 0x18, 0x56, 0x86, 0x2a, 0x3, 0x19, 0xe9, 0x6, 0xeb, 0x4a, 0x6f, 0x2a, 0x40, 0x28, 0xbb, + 0x3e, 0x87, 0xc1, 0xce, 0x39, 0x6e, 0x3b, 0x1f, 0xb0, 0x9, 0x33, 0x67, 0x19, 0x0e, 0x1a, 0xb2, + 0xb3, 0x7d, 0xd3, 0xe6, 0x33, 0xf4, 0x7c, 0x82, 0x73, 0x7b, 0xb6, 0x16, 0x55, 0xff, 0x76, 0xaf, + 0x7f, 0xc2, 0x42, 0x51, 0xa9, 0xad, 0x1e, 0x72, 0xc9, 0x63, 0xab, 0x41, 0x5a, 0x26, 0x32, 0x39, + 0x5d, 0xa6, 0x7, 0x56, 0x93, 0x89, 0xe5, 0x0f, 0x2a, 0xb5, 0x67, 0x3a, 0xcf, 0xc3, 0x82, 0x83, + 0xf6, 0x88, 0x52, 0x0b, 0xfc, 0x6a, 0x5b, 0x1a, 0x57, 0x87, 0x86, 0xef, 0xda, 0x47, 0xdb, 0x4d, + 0xba, 0xe7, 0x3, 0x5b, 0xe4, 0x70, 0x8b, 0xe0, 0xe1, 0x92, 0x13, 0x86, 0x74, 0x4, 0xdc, 0x6a, + 0x0a, 0x2a, 0x20, 0xec, 0x6d, 0xbf, 0xf0, 0x46, 0xf7, 0x9, 0x2, 0xdb, 0x2f, 0x70, 0x11, 0xdd, + 0xb0, 0x13, 0xa2, 0xc1, 0x58, 0x74, 0x29, 0x19, 0x8d, 0x4a, 0x94, 0x80, 0x0b, 0xd7, 0x25, 0x85, + 0x10, 0x35, 0x97, 0x48, 0x6e, 0x70, 0x28, 0xae, 0x58, 0x97, 0x7d, 0xf2, 0x19, 0x27, 0x13, 0xab, + 0x47, 0x9b, 0x54, 0xdf, 0xc3, 0x5b, 0x5f, 0x5e, 0xb4, 0x64, 0x47, 0xce, 0x40, 0x3b, 0x0c, 0x4a, + 0x62, 0x52, 0xba, 0xc7, 0xf0, 0x36, 0x87, 0x9c, 0x79, 0x9a, 0x83, 0x11, 0x61, 0x0c, 0x1b, 0x6b, + 0xa5, 0x24, 0x63, 0x20, 0xb2, 0x56, 0x9a, 0x94, 0x97, 0xf7, 0x88, 0x41, 0x35, 0xeb, 0x52, 0x37, + 0xa4, 0xf2, 0x74, 0x1b, 0x38, 0xe4, 0x4c, 0x8b, 0x4b, 0xd2, 0xa5, 0xad, 0xb8, 0x2f, 0x7b, 0x5a, + 0xfd, 0xbc, 0x9c, 0xe0, 0xea, 0x9e, 0x82, 0x3, 0x62, 0xe2, 0xdc, 0x6c, 0x56, 0x9, 0x2, 0x28, + 0xb8, 0x2d, 0xb8, 0x46, 0xaf, 0x3a, 0xf4, 0x51, 0xf7, 0x4d, 0xc4, 0xd9, 0xa9, 0x1d, 0x67, 0x9d, + 0x2b, 0x18, 0x56, 0x86, 0x2a, 0x3, 0x19, 0xe9, 0x6, 0xeb, 0x4a, 0x6f, 0x2a, 0x40, 0x28, 0xbb, + 0x3e, 0x87, 0xc1, 0xce, 0x39, 0x6e, 0x3b, 0x1f, 0xb0, 0x9, 0x33, 0x67, 0x19, 0x0e, 0x1a, 0xb2, + 0xb3, 0x7d, 0xd3, 0xe6, 0x33, 0xf4, 0x7c, 0x82, 0x73, 0x7b, 0xb6, 0x16, 0x55, 0xff, 0x76, 0xaf, + 0x7f, 0xc2, 0x42, 0x51, 0xa9, 0xad, 0x1e, 0x72, 0xc9, 0x63, 0xab, 0x41, 0x5a, 0x26, 0x32, 0x39, +}; + +static unsigned char dh_except_b_pubkey_3072[] = { + 0x44, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x9, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x4, 0xe8, 0x9a, 0xd2, 0x0, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x0, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x5, + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x7, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x3, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x1, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7, + 0x44, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x9, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x4, 0xe8, 0x9a, 0xd2, 0x0, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x0, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x5, +}; + +static unsigned char dh_share_key_3072[] = { + 0xaf, 0xd4, 0xf6, 0x45, 0x63, 0x21, 0x8d, 0x98, 0xc4, 0xab, 0x18, 0xd7, 0x2b, 0x3c, 0x1d, 0xde, + 0xe7, 0x1f, 0xe1, 0xc5, 0x79, 0x57, 0x60, 0x20, 0xfa, 0x99, 0xbd, 0x7b, 0xa2, 0x94, 0x0b, 0xa3, + 0xb4, 0xb3, 0x33, 0x4a, 0x2f, 0xd0, 0x17, 0x7, 0x2e, 0x70, 0x19, 0x84, 0x1f, 0x8e, 0xe9, 0x61, + 0xe5, 0x52, 0x3, 0x96, 0xea, 0xd8, 0xb6, 0x3, 0x9f, 0xc4, 0x3e, 0x23, 0x77, 0x17, 0x54, 0xfb, + 0x13, 0xf0, 0x3e, 0x9a, 0x27, 0x5d, 0x12, 0x99, 0x58, 0x8d, 0x41, 0x46, 0xd9, 0xc9, 0x29, 0xbd, + 0x40, 0xd1, 0x4f, 0xef, 0x63, 0x7b, 0x54, 0xe6, 0x59, 0x6d, 0xe2, 0x30, 0xe8, 0x2c, 0x2f, 0xf9, + 0x66, 0xa2, 0x12, 0xf5, 0x58, 0x61, 0xac, 0x43, 0xec, 0x7e, 0xf9, 0x2e, 0x27, 0x70, 0x35, 0x75, + 0xb4, 0x10, 0x29, 0xac, 0x0a, 0xab, 0x59, 0xb6, 0x68, 0x4c, 0x16, 0xaf, 0xf0, 0x4f, 0x21, 0xcd, + 0xcc, 0x48, 0x97, 0xe4, 0x21, 0x65, 0xa6, 0x55, 0xb8, 0xf3, 0xb2, 0x7b, 0x91, 0xd7, 0xca, 0xb9, + 0x17, 0x58, 0x31, 0x71, 0xc0, 0xc9, 0x69, 0x1e, 0xf0, 0x9e, 0x3f, 0xe2, 0x37, 0x4, 0x2d, 0xa8, + 0x55, 0x9, 0x6b, 0x9c, 0xc6, 0x37, 0xa9, 0x9b, 0xdf, 0x67, 0x73, 0x7b, 0x46, 0xf9, 0x63, 0x47, + 0xcb, 0xa0, 0x57, 0x2a, 0xed, 0x97, 0x2f, 0xfe, 0x92, 0xf2, 0x20, 0x2c, 0x7e, 0xee, 0x7d, 0x11, + 0x78, 0xe6, 0xb9, 0x9, 0xd1, 0x94, 0xce, 0xd1, 0x5b, 0xf4, 0x44, 0xa9, 0xcb, 0x26, 0x2, 0x36, + 0x57, 0x2c, 0xa2, 0xbe, 0x37, 0xde, 0x86, 0x46, 0x20, 0x27, 0x9d, 0xa0, 0x2f, 0x4, 0xc1, 0xcd, + 0xff, 0x81, 0xe5, 0xe6, 0x2c, 0x9e, 0x39, 0x82, 0x31, 0x54, 0x33, 0xf8, 0xe7, 0xa0, 0xe5, 0x96, + 0xa4, 0x40, 0xc4, 0x44, 0xfe, 0x93, 0x66, 0xe2, 0xda, 0xaa, 0xb8, 0xfb, 0x2f, 0x3b, 0x8c, 0xce, + 0xaf, 0xd4, 0xf6, 0x45, 0x63, 0x21, 0x8d, 0x98, 0xc4, 0xab, 0x18, 0xd7, 0x2b, 0x3c, 0x1d, 0xde, + 0xe7, 0x1f, 0xe1, 0xc5, 0x79, 0x57, 0x60, 0x20, 0xfa, 0x99, 0xbd, 0x7b, 0xa2, 0x94, 0x0b, 0xa3, + 0xb4, 0xb3, 0x33, 0x4a, 0x2f, 0xd0, 0x17, 0x7, 0x2e, 0x70, 0x19, 0x84, 0x1f, 0x8e, 0xe9, 0x61, + 0xe5, 0x52, 0x3, 0x96, 0xea, 0xd8, 0xb6, 0x3, 0x9f, 0xc4, 0x3e, 0x23, 0x77, 0x17, 0x54, 0xfb, + 0x13, 0xf0, 0x3e, 0x9a, 0x27, 0x5d, 0x12, 0x99, 0x58, 0x8d, 0x41, 0x46, 0xd9, 0xc9, 0x29, 0xbd, + 0x40, 0xd1, 0x4f, 0xef, 0x63, 0x7b, 0x54, 0xe6, 0x59, 0x6d, 0xe2, 0x30, 0xe8, 0x2c, 0x2f, 0xf9, + 0x66, 0xa2, 0x12, 0xf5, 0x58, 0x61, 0xac, 0x43, 0xec, 0x7e, 0xf9, 0x2e, 0x27, 0x70, 0x35, 0x75, + 0xb4, 0x10, 0x29, 0xac, 0x0a, 0xab, 0x59, 0xb6, 0x68, 0x4c, 0x16, 0xaf, 0xf0, 0x4f, 0x21, 0xcd, +}; + +static unsigned char dh_p_4096[] = { + 0xce, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x09, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x04, 0xe8, 0x9a, 0xd2, 0x00, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x00, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x05, + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x07, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x03, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x01, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7, + 0xce, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x09, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x04, 0xe8, 0x9a, 0xd2, 0x00, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x00, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x05, + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x07, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x03, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x01, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7 +}; + +static unsigned char dh_xa_4096[] = { + 0x6b, 0x1f, 0xc4, 0x85, 0x98, 0xc3, 0x01, 0xda, 0x39, 0xf0, 0x1b, 0x76, 0x5d, 0x81, 0x1d, 0x1f, + 0xc9, 0x93, 0x95, 0xc1, 0xf8, 0xd1, 0x67, 0x2c, 0xd4, 0x0a, 0x67, 0xf0, 0x40, 0x86, 0x82, 0x7f, + 0x8f, 0x9d, 0x79, 0x04, 0xee, 0x4a, 0x54, 0xc9, 0x9c, 0x7f, 0xda, 0x15, 0x13, 0xc6, 0x95, 0xfb, + 0xfc, 0x7b, 0xe7, 0xd8, 0xde, 0x2a, 0xd8, 0xfd, 0xff, 0xdb, 0xa4, 0x7f, 0x4b, 0x37, 0x5d, 0x42, + 0xb6, 0x46, 0x4c, 0xbc, 0x34, 0x23, 0x99, 0x74, 0xf8, 0x80, 0x1b, 0xc1, 0x97, 0x34, 0xdf, 0x23, + 0x15, 0xa2, 0x8b, 0xec, 0xf3, 0x3e, 0x20, 0x93, 0x63, 0x88, 0x17, 0x70, 0x75, 0xbb, 0x9d, 0xb8, + 0x32, 0xb0, 0xae, 0xb5, 0x24, 0x6a, 0x86, 0xf6, 0xc1, 0x60, 0x41, 0xc4, 0xf4, 0x95, 0x6e, 0x10, + 0x2f, 0xd8, 0x58, 0x56, 0x42, 0x82, 0x71, 0x85, 0x19, 0xde, 0x91, 0xf0, 0x2f, 0x30, 0x0c, 0x63, + 0x0f, 0x2a, 0x77, 0x25, 0x4b, 0xb3, 0xd3, 0x2d, 0xfd, 0x94, 0x8b, 0x53, 0x02, 0x21, 0x40, 0xd7, + 0x36, 0x76, 0xf3, 0xc8, 0xc0, 0x36, 0x3d, 0x23, 0xc9, 0xbd, 0x92, 0x51, 0xf2, 0x4b, 0x83, 0x15, + 0xe0, 0x80, 0x86, 0x24, 0xe2, 0x20, 0x35, 0x97, 0xda, 0x0e, 0x68, 0x39, 0x01, 0xdd, 0x01, 0x87, + 0xa2, 0x47, 0xd2, 0x0d, 0xee, 0xfe, 0xdc, 0x5a, 0x37, 0x23, 0xeb, 0x3d, 0xe8, 0x1e, 0x39, 0x2d, + 0xbf, 0xa6, 0xe9, 0x17, 0x48, 0xe2, 0xea, 0xef, 0x1d, 0x2f, 0xe2, 0xaf, 0x3c, 0xbc, 0xae, 0xa7, + 0x42, 0x9b, 0xa5, 0x7d, 0x47, 0x8a, 0x20, 0xc5, 0xae, 0xa1, 0xe4, 0xe8, 0x1c, 0x05, 0xc0, 0x0a, + 0x05, 0xdc, 0x01, 0x74, 0xde, 0xad, 0xad, 0x07, 0xec, 0x6e, 0x6a, 0xc7, 0xee, 0x0f, 0xb8, 0xbe, + 0xaa, 0x46, 0x61, 0x8c, 0x12, 0x5a, 0xaf, 0x05, 0xff, 0x1b, 0x35, 0x6b, 0xe2, 0x3d, 0x48, 0x4f, + 0x6b, 0x1f, 0xc4, 0x85, 0x98, 0xc3, 0x01, 0xda, 0x39, 0xf0, 0x1b, 0x76, 0x5d, 0x81, 0x1d, 0x1f, + 0xc9, 0x93, 0x95, 0xc1, 0xf8, 0xd1, 0x67, 0x2c, 0xd4, 0x0a, 0x67, 0xf0, 0x40, 0x86, 0x82, 0x7f, + 0x8f, 0x9d, 0x79, 0x04, 0xee, 0x4a, 0x54, 0xc9, 0x9c, 0x7f, 0xda, 0x15, 0x13, 0xc6, 0x95, 0xfb, + 0xfc, 0x7b, 0xe7, 0xd8, 0xde, 0x2a, 0xd8, 0xfd, 0xff, 0xdb, 0xa4, 0x7f, 0x4b, 0x37, 0x5d, 0x42, + 0xb6, 0x46, 0x4c, 0xbc, 0x34, 0x23, 0x99, 0x74, 0xf8, 0x80, 0x1b, 0xc1, 0x97, 0x34, 0xdf, 0x23, + 0x15, 0xa2, 0x8b, 0xec, 0xf3, 0x3e, 0x20, 0x93, 0x63, 0x88, 0x17, 0x70, 0x75, 0xbb, 0x9d, 0xb8, + 0x32, 0xb0, 0xae, 0xb5, 0x24, 0x6a, 0x86, 0xf6, 0xc1, 0x60, 0x41, 0xc4, 0xf4, 0x95, 0x6e, 0x10, + 0x2f, 0xd8, 0x58, 0x56, 0x42, 0x82, 0x71, 0x85, 0x19, 0xde, 0x91, 0xf0, 0x2f, 0x30, 0x0c, 0x63, + 0x0f, 0x2a, 0x77, 0x25, 0x4b, 0xb3, 0xd3, 0x2d, 0xfd, 0x94, 0x8b, 0x53, 0x02, 0x21, 0x40, 0xd7, + 0x36, 0x76, 0xf3, 0xc8, 0xc0, 0x36, 0x3d, 0x23, 0xc9, 0xbd, 0x92, 0x51, 0xf2, 0x4b, 0x83, 0x15, + 0xe0, 0x80, 0x86, 0x24, 0xe2, 0x20, 0x35, 0x97, 0xda, 0x0e, 0x68, 0x39, 0x01, 0xdd, 0x01, 0x87, + 0xa2, 0x47, 0xd2, 0x0d, 0xee, 0xfe, 0xdc, 0x5a, 0x37, 0x23, 0xeb, 0x3d, 0xe8, 0x1e, 0x39, 0x2d, + 0xbf, 0xa6, 0xe9, 0x17, 0x48, 0xe2, 0xea, 0xef, 0x1d, 0x2f, 0xe2, 0xaf, 0x3c, 0xbc, 0xae, 0xa7, + 0x42, 0x9b, 0xa5, 0x7d, 0x47, 0x8a, 0x20, 0xc5, 0xae, 0xa1, 0xe4, 0xe8, 0x1c, 0x05, 0xc0, 0x0a, + 0x05, 0xdc, 0x01, 0x74, 0xde, 0xad, 0xad, 0x07, 0xec, 0x6e, 0x6a, 0xc7, 0xee, 0x0f, 0xb8, 0xbe, + 0xaa, 0x46, 0x61, 0x8c, 0x12, 0x5a, 0xaf, 0x05, 0xff, 0x1b, 0x35, 0x6b, 0xe2, 0x3d, 0x48, 0x4f +}; + +static unsigned char dh_except_a_pubkey_4096[] = { + 0xa5, 0x24, 0x63, 0x20, 0xb2, 0x56, 0x9a, 0x94, 0x97, 0xf7, 0x88, 0x41, 0x35, 0xeb, 0x52, 0x37, + 0xa4, 0xf2, 0x74, 0x1b, 0x38, 0xe4, 0x4c, 0x8b, 0x4b, 0xd2, 0xa5, 0xad, 0xb8, 0x2f, 0x7b, 0x5a, + 0xfd, 0xbc, 0x9c, 0xe0, 0xea, 0x9e, 0x82, 0x3, 0x62, 0xe2, 0xdc, 0x6c, 0x56, 0x9, 0x2, 0x28, + 0xb8, 0x2d, 0xb8, 0x46, 0xaf, 0x3a, 0xf4, 0x51, 0xf7, 0x4d, 0xc4, 0xd9, 0xa9, 0x1d, 0x67, 0x9d, + 0x2b, 0x18, 0x56, 0x86, 0x2a, 0x3, 0x19, 0xe9, 0x6, 0xeb, 0x4a, 0x6f, 0x2a, 0x40, 0x28, 0xbb, + 0x3e, 0x87, 0xc1, 0xce, 0x39, 0x6e, 0x3b, 0x1f, 0xb0, 0x9, 0x33, 0x67, 0x19, 0x0e, 0x1a, 0xb2, + 0xb3, 0x7d, 0xd3, 0xe6, 0x33, 0xf4, 0x7c, 0x82, 0x73, 0x7b, 0xb6, 0x16, 0x55, 0xff, 0x76, 0xaf, + 0x7f, 0xc2, 0x42, 0x51, 0xa9, 0xad, 0x1e, 0x72, 0xc9, 0x63, 0xab, 0x41, 0x5a, 0x26, 0x32, 0x39, + 0x5d, 0xa6, 0x7, 0x56, 0x93, 0x89, 0xe5, 0x0f, 0x2a, 0xb5, 0x67, 0x3a, 0xcf, 0xc3, 0x82, 0x83, + 0xf6, 0x88, 0x52, 0x0b, 0xfc, 0x6a, 0x5b, 0x1a, 0x57, 0x87, 0x86, 0xef, 0xda, 0x47, 0xdb, 0x4d, + 0xba, 0xe7, 0x3, 0x5b, 0xe4, 0x70, 0x8b, 0xe0, 0xe1, 0x92, 0x13, 0x86, 0x74, 0x4, 0xdc, 0x6a, + 0x0a, 0x2a, 0x20, 0xec, 0x6d, 0xbf, 0xf0, 0x46, 0xf7, 0x9, 0x2, 0xdb, 0x2f, 0x70, 0x11, 0xdd, + 0xb0, 0x13, 0xa2, 0xc1, 0x58, 0x74, 0x29, 0x19, 0x8d, 0x4a, 0x94, 0x80, 0x0b, 0xd7, 0x25, 0x85, + 0x10, 0x35, 0x97, 0x48, 0x6e, 0x70, 0x28, 0xae, 0x58, 0x97, 0x7d, 0xf2, 0x19, 0x27, 0x13, 0xab, + 0x47, 0x9b, 0x54, 0xdf, 0xc3, 0x5b, 0x5f, 0x5e, 0xb4, 0x64, 0x47, 0xce, 0x40, 0x3b, 0x0c, 0x4a, + 0x62, 0x52, 0xba, 0xc7, 0xf0, 0x36, 0x87, 0x9c, 0x79, 0x9a, 0x83, 0x11, 0x61, 0x0c, 0x1b, 0x6b, + 0xa5, 0x24, 0x63, 0x20, 0xb2, 0x56, 0x9a, 0x94, 0x97, 0xf7, 0x88, 0x41, 0x35, 0xeb, 0x52, 0x37, + 0xa4, 0xf2, 0x74, 0x1b, 0x38, 0xe4, 0x4c, 0x8b, 0x4b, 0xd2, 0xa5, 0xad, 0xb8, 0x2f, 0x7b, 0x5a, + 0xfd, 0xbc, 0x9c, 0xe0, 0xea, 0x9e, 0x82, 0x3, 0x62, 0xe2, 0xdc, 0x6c, 0x56, 0x9, 0x2, 0x28, + 0xb8, 0x2d, 0xb8, 0x46, 0xaf, 0x3a, 0xf4, 0x51, 0xf7, 0x4d, 0xc4, 0xd9, 0xa9, 0x1d, 0x67, 0x9d, + 0x2b, 0x18, 0x56, 0x86, 0x2a, 0x3, 0x19, 0xe9, 0x6, 0xeb, 0x4a, 0x6f, 0x2a, 0x40, 0x28, 0xbb, + 0x3e, 0x87, 0xc1, 0xce, 0x39, 0x6e, 0x3b, 0x1f, 0xb0, 0x9, 0x33, 0x67, 0x19, 0x0e, 0x1a, 0xb2, + 0xb3, 0x7d, 0xd3, 0xe6, 0x33, 0xf4, 0x7c, 0x82, 0x73, 0x7b, 0xb6, 0x16, 0x55, 0xff, 0x76, 0xaf, + 0x7f, 0xc2, 0x42, 0x51, 0xa9, 0xad, 0x1e, 0x72, 0xc9, 0x63, 0xab, 0x41, 0x5a, 0x26, 0x32, 0x39, + 0x5d, 0xa6, 0x7, 0x56, 0x93, 0x89, 0xe5, 0x0f, 0x2a, 0xb5, 0x67, 0x3a, 0xcf, 0xc3, 0x82, 0x83, + 0xf6, 0x88, 0x52, 0x0b, 0xfc, 0x6a, 0x5b, 0x1a, 0x57, 0x87, 0x86, 0xef, 0xda, 0x47, 0xdb, 0x4d, + 0xba, 0xe7, 0x3, 0x5b, 0xe4, 0x70, 0x8b, 0xe0, 0xe1, 0x92, 0x13, 0x86, 0x74, 0x4, 0xdc, 0x6a, + 0x0a, 0x2a, 0x20, 0xec, 0x6d, 0xbf, 0xf0, 0x46, 0xf7, 0x9, 0x2, 0xdb, 0x2f, 0x70, 0x11, 0xdd, + 0xb0, 0x13, 0xa2, 0xc1, 0x58, 0x74, 0x29, 0x19, 0x8d, 0x4a, 0x94, 0x80, 0x0b, 0xd7, 0x25, 0x85, + 0x10, 0x35, 0x97, 0x48, 0x6e, 0x70, 0x28, 0xae, 0x58, 0x97, 0x7d, 0xf2, 0x19, 0x27, 0x13, 0xab, + 0x47, 0x9b, 0x54, 0xdf, 0xc3, 0x5b, 0x5f, 0x5e, 0xb4, 0x64, 0x47, 0xce, 0x40, 0x3b, 0x0c, 0x4a, + 0x62, 0x52, 0xba, 0xc7, 0xf0, 0x36, 0x87, 0x9c, 0x79, 0x9a, 0x83, 0x11, 0x61, 0x0c, 0x1b, 0x6b +}; + +static unsigned char dh_except_b_pubkey_4096[] = { + 0x44, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x9, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x4, 0xe8, 0x9a, 0xd2, 0x0, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x0, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x5, + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x7, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x3, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x1, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7, + 0x44, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x9, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x4, 0xe8, 0x9a, 0xd2, 0x0, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x0, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x5, + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x7, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x3, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x1, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7 +}; + +static unsigned char dh_share_key_4096[] = { + 0xaf, 0xd4, 0xf6, 0x45, 0x63, 0x21, 0x8d, 0x98, 0xc4, 0xab, 0x18, 0xd7, 0x2b, 0x3c, 0x1d, 0xde, + 0xe7, 0x1f, 0xe1, 0xc5, 0x79, 0x57, 0x60, 0x20, 0xfa, 0x99, 0xbd, 0x7b, 0xa2, 0x94, 0x0b, 0xa3, + 0xb4, 0xb3, 0x33, 0x4a, 0x2f, 0xd0, 0x17, 0x7, 0x2e, 0x70, 0x19, 0x84, 0x1f, 0x8e, 0xe9, 0x61, + 0xe5, 0x52, 0x3, 0x96, 0xea, 0xd8, 0xb6, 0x3, 0x9f, 0xc4, 0x3e, 0x23, 0x77, 0x17, 0x54, 0xfb, + 0x13, 0xf0, 0x3e, 0x9a, 0x27, 0x5d, 0x12, 0x99, 0x58, 0x8d, 0x41, 0x46, 0xd9, 0xc9, 0x29, 0xbd, + 0x40, 0xd1, 0x4f, 0xef, 0x63, 0x7b, 0x54, 0xe6, 0x59, 0x6d, 0xe2, 0x30, 0xe8, 0x2c, 0x2f, 0xf9, + 0x66, 0xa2, 0x12, 0xf5, 0x58, 0x61, 0xac, 0x43, 0xec, 0x7e, 0xf9, 0x2e, 0x27, 0x70, 0x35, 0x75, + 0xb4, 0x10, 0x29, 0xac, 0x0a, 0xab, 0x59, 0xb6, 0x68, 0x4c, 0x16, 0xaf, 0xf0, 0x4f, 0x21, 0xcd, + 0xcc, 0x48, 0x97, 0xe4, 0x21, 0x65, 0xa6, 0x55, 0xb8, 0xf3, 0xb2, 0x7b, 0x91, 0xd7, 0xca, 0xb9, + 0x17, 0x58, 0x31, 0x71, 0xc0, 0xc9, 0x69, 0x1e, 0xf0, 0x9e, 0x3f, 0xe2, 0x37, 0x4, 0x2d, 0xa8, + 0x55, 0x9, 0x6b, 0x9c, 0xc6, 0x37, 0xa9, 0x9b, 0xdf, 0x67, 0x73, 0x7b, 0x46, 0xf9, 0x63, 0x47, + 0xcb, 0xa0, 0x57, 0x2a, 0xed, 0x97, 0x2f, 0xfe, 0x92, 0xf2, 0x20, 0x2c, 0x7e, 0xee, 0x7d, 0x11, + 0x78, 0xe6, 0xb9, 0x9, 0xd1, 0x94, 0xce, 0xd1, 0x5b, 0xf4, 0x44, 0xa9, 0xcb, 0x26, 0x2, 0x36, + 0x57, 0x2c, 0xa2, 0xbe, 0x37, 0xde, 0x86, 0x46, 0x20, 0x27, 0x9d, 0xa0, 0x2f, 0x4, 0xc1, 0xcd, + 0xff, 0x81, 0xe5, 0xe6, 0x2c, 0x9e, 0x39, 0x82, 0x31, 0x54, 0x33, 0xf8, 0xe7, 0xa0, 0xe5, 0x96, + 0xa4, 0x40, 0xc4, 0x44, 0xfe, 0x93, 0x66, 0xe2, 0xda, 0xaa, 0xb8, 0xfb, 0x2f, 0x3b, 0x8c, 0xce, + 0xaf, 0xd4, 0xf6, 0x45, 0x63, 0x21, 0x8d, 0x98, 0xc4, 0xab, 0x18, 0xd7, 0x2b, 0x3c, 0x1d, 0xde, + 0xe7, 0x1f, 0xe1, 0xc5, 0x79, 0x57, 0x60, 0x20, 0xfa, 0x99, 0xbd, 0x7b, 0xa2, 0x94, 0x0b, 0xa3, + 0xb4, 0xb3, 0x33, 0x4a, 0x2f, 0xd0, 0x17, 0x7, 0x2e, 0x70, 0x19, 0x84, 0x1f, 0x8e, 0xe9, 0x61, + 0xe5, 0x52, 0x3, 0x96, 0xea, 0xd8, 0xb6, 0x3, 0x9f, 0xc4, 0x3e, 0x23, 0x77, 0x17, 0x54, 0xfb, + 0x13, 0xf0, 0x3e, 0x9a, 0x27, 0x5d, 0x12, 0x99, 0x58, 0x8d, 0x41, 0x46, 0xd9, 0xc9, 0x29, 0xbd, + 0x40, 0xd1, 0x4f, 0xef, 0x63, 0x7b, 0x54, 0xe6, 0x59, 0x6d, 0xe2, 0x30, 0xe8, 0x2c, 0x2f, 0xf9, + 0x66, 0xa2, 0x12, 0xf5, 0x58, 0x61, 0xac, 0x43, 0xec, 0x7e, 0xf9, 0x2e, 0x27, 0x70, 0x35, 0x75, + 0xb4, 0x10, 0x29, 0xac, 0x0a, 0xab, 0x59, 0xb6, 0x68, 0x4c, 0x16, 0xaf, 0xf0, 0x4f, 0x21, 0xcd, + 0xcc, 0x48, 0x97, 0xe4, 0x21, 0x65, 0xa6, 0x55, 0xb8, 0xf3, 0xb2, 0x7b, 0x91, 0xd7, 0xca, 0xb9, + 0x17, 0x58, 0x31, 0x71, 0xc0, 0xc9, 0x69, 0x1e, 0xf0, 0x9e, 0x3f, 0xe2, 0x37, 0x4, 0x2d, 0xa8, + 0x55, 0x9, 0x6b, 0x9c, 0xc6, 0x37, 0xa9, 0x9b, 0xdf, 0x67, 0x73, 0x7b, 0x46, 0xf9, 0x63, 0x47, + 0xcb, 0xa0, 0x57, 0x2a, 0xed, 0x97, 0x2f, 0xfe, 0x92, 0xf2, 0x20, 0x2c, 0x7e, 0xee, 0x7d, 0x11, + 0x78, 0xe6, 0xb9, 0x9, 0xd1, 0x94, 0xce, 0xd1, 0x5b, 0xf4, 0x44, 0xa9, 0xcb, 0x26, 0x2, 0x36, + 0x57, 0x2c, 0xa2, 0xbe, 0x37, 0xde, 0x86, 0x46, 0x20, 0x27, 0x9d, 0xa0, 0x2f, 0x4, 0xc1, 0xcd, + 0xff, 0x81, 0xe5, 0xe6, 0x2c, 0x9e, 0x39, 0x82, 0x31, 0x54, 0x33, 0xf8, 0xe7, 0xa0, 0xe5, 0x96, + 0xa4, 0x40, 0xc4, 0x44, 0xfe, 0x93, 0x66, 0xe2, 0xda, 0xaa, 0xb8, 0xfb, 0x2f, 0x3b, 0x8c, 0xce, +}; + +/******************************************* ECDH ********************************************/ +static char ecdh_a_secp128r1[] = { + 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc +}; + +static char ecdh_b_secp128r1[] = { + 0xe8, 0x75, 0x79, 0xc1, 0x10, 0x79, 0xf4, 0x3d, 0xd8, 0x24, 0x99, 0x3c, 0x2c, 0xee, 0x5e, 0xd3 +}; + +static char ecdh_p_secp128r1[] = { + 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +static char ecdh_n_secp128r1[] = { + 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x75, 0xa3, 0x0d, 0x1b, 0x90, 0x38, 0xa1, 0x15 +}; + +static char ecdh_g_secp128r1[] = { + 0x16, 0x1f, 0xf7, 0x52, 0x8b, 0x89, 0x9b, 0x2d, 0x0c, 0x28, 0x60, 0x7c, 0xa5, 0x2c, 0x5b, 0x86, + 0xcf, 0x5a, 0xc8, 0x39, 0x5b, 0xaf, 0xeb, 0x13, 0xc0, 0x2d, 0xa2, 0x92, 0xdd, 0xed, 0x7a, 0x83 +}; + +static char ecdh_da_secp128r1[] = { + 0xfe, 0x4e, 0xc2, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x78, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static char ecdh_cp_pubkey_secp128r1[] = { + 0x04, + 0xcc, 0x40, 0x99, 0x3b, 0xcd, 0x0b, 0xcf, 0xcb, 0x9a, 0x96, 0x08, 0x56, 0xc2, 0x96, 0x2c, 0xe1, + 0xdf, 0x69, 0x2a, 0x71, 0xaf, 0x96, 0xe2, 0xeb, 0x5a, 0x26, 0x7f, 0xd3, 0x7a, 0xe8, 0x70, 0xf3 +}; + +static char ecdh_except_b_pubkey_secp128r1[] = { + 0x04, + 0xcc, 0x40, 0x99, 0x3b, 0xcd, 0x0b, 0xcf, 0xcb, 0x9a, 0x96, 0x08, 0x56, 0xc2, 0x96, 0x2c, 0xe1, + 0xdf, 0x69, 0x2a, 0x71, 0xaf, 0x96, 0xe2, 0xeb, 0x5a, 0x26, 0x7f, 0xd3, 0x7a, 0xe8, 0x70, 0xf3 +}; + +static char ecdh_cp_sharekey_secp128r1[] = { + 0x68, 0x55, 0x71, 0xa4, 0xd7, 0x51, 0x49, 0xa8, 0x78, 0xa8, 0x3a, 0xc1, 0x3f, 0xb3, 0x8c, 0xcb +}; + +/* ecc sign or verf*/ +static char ecc_except_kinv_secp128r1[] = { + 0xfe, 0x4e, 0xc2, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x78, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static char ecc_except_e_secp128r1[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x4 +}; + +static char ecc_cp_sign_secp128r1[] = { + 0x2e, 0x69, 0xad, 0x4f, 0xd5, 0xd4, 0x62, 0xec, 0xf2, 0xde, 0x21, 0x4f, 0xbc, 0x1f, 0xe8, 0x19, + 0x7b, 0x98, 0x8d, 0xaf, 0xe4, 0x6c, 0x60, 0x73, 0x00, 0xb0, 0x8b, 0xef, 0x89, 0x65, 0x35, 0x84 +}; + +static char ecdh_a_secp192k1[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static char ecdh_b_secp192k1[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03 +}; + +static char ecdh_p_secp192k1[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xee, 0x37 +}; + +static char ecdh_n_secp192k1[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x26, 0xf2, 0xfc, 0x17, + 0x0f, 0x69, 0x46, 0x6a, 0x74, 0xde, 0xfd, 0x8d +}; + +static char ecdh_g_secp192k1[] = { + 0xdb, 0x4f, 0xf1, 0x0e, 0xc0, 0x57, 0xe9, 0xae, 0x26, 0xb0, 0x7d, 0x02, 0x80, 0xb7, 0xf4, 0x34, + 0x1d, 0xa5, 0xd1, 0xb1, 0xea, 0xe0, 0x6c, 0x7d, + 0x9b, 0x2f, 0x2f, 0x6d, 0x9c, 0x56, 0x28, 0xa7, 0x84, 0x41, 0x63, 0xd0, 0x15, 0xbe, 0x86, 0x34, + 0x40, 0x82, 0xaa, 0x88, 0xd9, 0x5e, 0x2f, 0x9d +}; + +static char ecdh_da_secp192k1[] = { + 0x2b, 0x58, 0xc2, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x58, 0xc2, 0x5e, 0x00, 0x00, 0x00, 0x00, + 0x67, 0x6a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static char ecdh_cp_pubkey_secp192k1[] = { + 0x04, + 0xec, 0x0e, 0x64, 0xac, 0x04, 0x2a, 0x88, 0x86, 0xed, 0xc1, 0xf2, 0x50, 0x0f, 0xe1, 0x27, 0x63, + 0x86, 0x63, 0x9e, 0xb2, 0x82, 0x21, 0x6e, 0x3f, 0x48, 0x59, 0x76, 0xb9, 0x4e, 0xd9, 0xe2, 0x02, + 0xb4, 0xdb, 0xfc, 0x8f, 0x49, 0xe7, 0x24, 0x9b, 0xbe, 0x33, 0xee, 0xc8, 0xcc, 0x9e, 0x00, 0x9a +}; + +static char ecdh_cp_sharekey_secp192k1[] = { + 0x79, 0xd3, 0x1c, 0x98, 0xfb, 0xd2, 0xb6, 0x7c, 0x60, 0x4b, 0x6e, 0x4c, 0xa9, 0x95, 0xcb, 0xac, + 0xb0, 0xf9, 0x05, 0xed, 0x9a, 0xcb, 0x2e, 0x5b +}; + +static char ecdh_except_b_pubkey_secp192k1[] = { + 0x04, + 0xec, 0x0e, 0x64, 0xac, 0x04, 0x2a, 0x88, 0x86, 0xed, 0xc1, 0xf2, 0x50, 0x0f, 0xe1, 0x27, 0x63, + 0x86, 0x63, 0x9e, 0xb2, 0x82, 0x21, 0x6e, 0x3f, 0x48, 0x59, 0x76, 0xb9, 0x4e, 0xd9, 0xe2, 0x02, + 0xb4, 0xdb, 0xfc, 0x8f, 0x49, 0xe7, 0x24, 0x9b, 0xbe, 0x33, 0xee, 0xc8, 0xcc, 0x9e, 0x00, 0x9a +}; + +/* ecc sign or verf*/ +static unsigned char ecc_except_kinv_secp192k1[] = { + 0x71, 0x71, 0xb4, 0x5b, 0x79, 0x51, 0x94, 0x70, 0x53, 0xf9, 0x77, 0x02, 0x64, 0xef, 0xc4, 0xdb, + 0x64, 0xfc, 0xbe, 0x4e, 0x44, 0x4a, 0xc6, 0x54 +}; + +static unsigned char ecc_except_e_secp192k1[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04 +}; + +/* 224 */ +static char ecdh_a_secp224r1[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE +}; + +static char ecdh_b_secp224r1[] = { + 0xB4, 0x05, 0x0A, 0x85, 0x0C, 0x04, 0xB3, 0xAB, 0xF5, 0x41, 0x32, 0x56, 0x50, 0x44, + 0xB0, 0xB7, 0xD7, 0xBF, 0xD8, 0xBA, 0x27, 0x0B, 0x39, 0x43, 0x23, 0x55, 0xFF, 0xB4 +}; + +static char ecdh_p_secp224r1[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 +}; + +static char ecdh_n_secp224r1[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x16, 0xA2, 0xE0, 0xB8, 0xF0, 0x3E, 0x13, 0xDD, 0x29, 0x45, 0x5C, 0x5C, 0x2A, 0x3D +}; + +static char ecdh_g_secp224r1[] = { + 0xB7, 0x0E, 0x0C, 0xBD, 0x6B, 0xB4, 0xBF, 0x7F, 0x32, 0x13, 0x90, 0xB9, 0x4A, 0x03, + 0xC1, 0xD3, 0x56, 0xC2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xD6, 0x11, 0x5C, 0x1D, 0x21, + 0xBD, 0x37, 0x63, 0x88, 0xB5, 0xF7, 0x23, 0xFB, 0x4C, 0x22, 0xDF, 0xE6, 0xCD, 0x43, + 0x75, 0xA0, 0x5A, 0x07, 0x47, 0x64, 0x44, 0xD5, 0x81, 0x99, 0x85, 0x00, 0x7E, 0x34 +}; + +static char ecdh_da_secp224r1[] = { + 0x41, 0x5c, 0x8c, 0x34, 0xfd, 0x70, 0x76, 0x3c, 0x6a, 0x81, 0x8e, 0x33, 0x7c, 0xa5, + 0x59, 0x6b, 0xfb, 0x58, 0x8e, 0x74, 0xb8, 0xc7, 0x3c, 0xcf, 0xde, 0xe3, 0x81, 0x60 +}; + +static char ecdh_cp_pubkey_secp224r1[] = { + 0x04, + 0x5b, 0x46, 0x50, 0x7c, 0x7a, 0x37, 0x82, 0x05, 0x5a, 0xc7, 0xd0, 0x29, 0xf8, 0xdd, + 0xe6, 0x3e, 0xb4, 0xc2, 0x31, 0x59, 0xfd, 0xa4, 0xb7, 0xee, 0x61, 0x83, 0x7c, 0x80, + 0xf1, 0x51, 0xf0, 0x5b, 0xfb, 0xc6, 0x63, 0x23, 0x9a, 0x13, 0xfa, 0x47, 0x68, 0x7b, + 0x3e, 0x47, 0xb3, 0x88, 0xca, 0x3e, 0x4b, 0x71, 0x24, 0x17, 0xc7, 0x4c, 0xd0, 0x06 +}; + +static char ecdh_except_b_pubkey_secp224r1[] = { + 0x04, + 0x5b, 0x46, 0x50, 0x7c, 0x7a, 0x37, 0x82, 0x05, 0x5a, 0xc7, 0xd0, 0x29, 0xf8, 0xdd, + 0xe6, 0x3e, 0xb4, 0xc2, 0x31, 0x59, 0xfd, 0xa4, 0xb7, 0xee, 0x61, 0x83, 0x7c, 0x80, + 0xf1, 0x51, 0xf0, 0x5b, 0xfb, 0xc6, 0x63, 0x23, 0x9a, 0x13, 0xfa, 0x47, 0x68, 0x7b, + 0x3e, 0x47, 0xb3, 0x88, 0xca, 0x3e, 0x4b, 0x71, 0x24, 0x17, 0xc7, 0x4c, 0xd0, 0x06 +}; + +static char ecdh_cp_sharekey_secp224r1[] = { + 0x2f, 0xc0, 0x04, 0x34, 0x0e, 0x03, 0xb0, 0xd2, 0x84, 0xe1, 0x4f, 0x4f, 0x7b, 0xac, + 0x53, 0xaa, 0x32, 0x5c, 0xbd, 0xe5, 0xbc, 0x2a, 0xe3, 0xda, 0x48, 0x38, 0x67, 0x16 +}; + + +/* 256 */ +static char ecdh_a_secp256k1[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static char ecdh_b_secp256k1[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07 +}; + +static char ecdh_p_secp256k1[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f +}; + +static char ecdh_n_secp256k1[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, + 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41 +}; + +static char ecdh_g_secp256k1[] = { + 0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B, 0x07, + 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9, 0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98, + 0x48, 0x3a, 0xda, 0x77, 0x26, 0xa3, 0xc4, 0x65, 0x5d, 0xa4, 0xfb, 0xfc, 0x0e, 0x11, 0x08, 0xa8, + 0xfd, 0x17, 0xb4, 0x48, 0xa6, 0x85, 0x54, 0x19, 0x9c, 0x47, 0xd0, 0x8f, 0xfb, 0x10, 0xd4, 0xb8 +}; + +static char ecdh_da_secp256k1[] = { + 0x71, 0x71, 0xb4, 0x5b, 0x79, 0x51, 0x94, 0x70, 0x53, 0xf9, 0x77, 0x02, 0x64, 0xef, 0xc4, 0xdb, + 0x64, 0xfc, 0xbe, 0x4e, 0x44, 0x4a, 0xc6, 0x54, 0x71, 0x69, 0x2e, 0x4a, 0x46, 0xa7, 0x2d, 0xa3 +}; + +#if 0 +static char ecdh_db_secp256k1[] = { + 0xe2, 0x74, 0x69, 0xc8, 0x17, 0x6c, 0x0d, 0xca, 0xdd, 0x9e, 0xf6, 0x2f, 0x30, 0x9f, 0xad, 0xf3, + 0xdd, 0x16, 0xcc, 0x0c, 0xb1, 0xd0, 0x7b, 0xf4, 0xde, 0x9d, 0xf2, 0x5d, 0x22, 0x03, 0xce, 0x41 +}; +#endif + +static char ecdh_cp_pubkey_secp256k1[] = { + 0x04, + 0x68, 0xae, 0x87, 0x7c, 0x45, 0xb3, 0x8b, 0xa8, 0xa8, 0x8e, 0x4b, 0xe5, 0x1f, 0x4e, 0xe6, 0x89, + 0x67, 0x73, 0x71, 0x96, 0x92, 0x2e, 0x57, 0x07, 0xc4, 0x30, 0xa5, 0xcf, 0x9f, 0x58, 0xb0, 0x6f, + 0x26, 0xd3, 0x58, 0xa4, 0xb6, 0xfc, 0xb6, 0x4b, 0x0f, 0x63, 0xd9, 0xa6, 0xa0, 0x1b, 0xba, 0x10, + 0x10, 0xa4, 0xab, 0x28, 0x6e, 0xab, 0x51, 0x34, 0xac, 0x3d, 0x2b, 0x39, 0xf1, 0xd7, 0x21, 0x48 +}; + +static char ecdh_except_b_pubkey_secp256k1[] = { + 0x04, + 0x90, 0x34, 0x99, 0xc8, 0x9e, 0x32, 0xdb, 0xcd, 0x24, 0x4e, 0x31, 0x51, 0x1c, 0x83, 0x4b, 0xf7, + 0x68, 0xf0, 0xbb, 0xa3, 0x91, 0x38, 0xa8, 0xf1, 0xab, 0x76, 0x36, 0xcd, 0x23, 0x3f, 0x57, 0x3b, + 0x22, 0x1a, 0x3f, 0x2e, 0x40, 0x8b, 0xe2, 0x7b, 0xd4, 0x91, 0xe4, 0xf2, 0x36, 0x00, 0xbe, 0xae, + 0x9c, 0xf2, 0xfc, 0xb4, 0xb9, 0x8b, 0x5b, 0xa7, 0x39, 0x88, 0xf2, 0x3b, 0xe2, 0xe5, 0xab, 0x1b +}; + +static char ecdh_cp_sharekey_secp256k1[] = { + 0xd8, 0x9d, 0x1e, 0x25, 0xa2, 0x5, 0xd8, 0xad, 0x0f, 0x1c, 0x7a, 0x44, 0xd4, 0xe6, 0x96, 0xc2, + 0xd3, 0xbc, 0x05, 0xa1, 0x8d, 0x4a, 0x2, 0x11, 0x0e, 0x93, 0xcd, 0xb9, 0x56, 0xd6, 0x44, 0x1c, +}; + +/* ecc sign or verf*/ +static unsigned char ecc_except_kinv_secp256k1[] = { + 0x71, 0x71, 0xb4, 0x5b, 0x79, 0x51, 0x94, 0x70, 0x53, 0xf9, 0x77, 0x02, 0x64, 0xef, 0xc4, 0xdb, + 0x64, 0xfc, 0xbe, 0x4e, 0x44, 0x4a, 0xc6, 0x54, 0x71, 0x69, 0x2e, 0x4a, 0x46, 0xa7, 0x2d, 0xa3 +}; + +static unsigned char ecc_except_e_secp256k1[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04 +}; + +static unsigned char ecc_cp_sign_secp256k1[] = { + 0x30,0x45,0x02,0x20,0x68,0xae,0x87,0x7c,0x45,0xb3,0x8b,0xa8,0xa8,0x8e,0x4b,0xe5, + 0x1f,0x4e,0xe6,0x89,0x67,0x73,0x71,0x96,0x92,0x2e,0x57,0x07,0xc4,0x30,0xa5,0xcf, + 0x9f,0x58,0xb0,0x6f,0x02,0x21,0x00,0xdb,0x14,0xac,0x48,0x0d,0x0a,0xe9,0xe4,0x1d, + 0x8d,0xca,0x47,0xb6,0x0e,0x44,0xf6,0xfb,0xde,0x86,0x9b,0x38,0x76,0x98,0x67,0x12, + 0x7f,0x1d,0x09,0x97,0xab,0xc2,0xcb +}; + +static char ecdh_a_secp320k1[] = { + 0x3e, 0xe3, 0x0b, 0x56, 0x8f, 0xba, 0xb0, 0xf8, 0x83, 0xcc, 0xeb, 0xd4, 0x6d, 0x3f, 0x3b, 0xb8, + 0xa2, 0xa7, 0x35, 0x13, 0xf5, 0xeb, 0x79, 0xda, 0x66, 0x19, 0x0e, 0xb0, 0x85, 0xff, 0xa9, 0xf4, + 0x92, 0xf3, 0x75, 0xa9, 0x7d, 0x86, 0x0e, 0xb4 +}; + +static char ecdh_b_secp320k1[] = { + 0x52, 0x08, 0x83, 0x94, 0x9d, 0xfd, 0xbc, 0x42, 0xd3, 0xad, 0x19, 0x86, 0x40, 0x68, 0x8a, 0x6f, + 0xe1, 0x3f, 0x41, 0x34, 0x95, 0x54, 0xb4, 0x9a, 0xcc, 0x31, 0xdc, 0xcd, 0x88, 0x45, 0x39, 0x81, + 0x6f, 0x5e, 0xb4, 0xac, 0x8f, 0xb1, 0xf1, 0xa6 +}; + +static char ecdh_p_secp320k1[] = { + 0xd3, 0x5e, 0x47, 0x20, 0x36, 0xbc, 0x4f, 0xb7, 0xe1, 0x3c, 0x78, 0x5e, 0xd2, 0x01, 0xe0, 0x65, + 0xf9, 0x8f, 0xcf, 0xa6, 0xf6, 0xf4, 0x0d, 0xef, 0x4f, 0x92, 0xb9, 0xec, 0x78, 0x93, 0xec, 0x28, + 0xfc, 0xd4, 0x12, 0xb1, 0xf1, 0xb3, 0x2e, 0x27 +}; + +static char ecdh_n_secp320k1[] = { + 0xd3, 0x5e, 0x47, 0x20, 0x36, 0xbc, 0x4f, 0xb7, 0xe1, 0x3c, 0x78, 0x5e, 0xd2, 0x01, 0xe0, 0x65, + 0xf9, 0x8f, 0xcf, 0xa5, 0xb6, 0x8f, 0x12, 0xa3, 0x2d, 0x48, 0x2e, 0xc7, 0xee, 0x86, 0x58, 0xe9, + 0x86, 0x91, 0x55, 0x5b, 0x44, 0xc5, 0x93, 0x11 +}; + +static char ecdh_g_secp320k1[] = { + 0x43, 0xbd, 0x7e, 0x9a, 0xfb, 0x53, 0xd8, 0xb8, 0x52, 0x89, 0xbc, 0xc4, 0x8e, 0xe5, 0xbf, 0xe6, + 0xf2, 0x01, 0x37, 0xd1, 0x0a, 0x08, 0x7e, 0xb6, 0xe7, 0x87, 0x1e, 0x2a, 0x10, 0xa5, 0x99, 0xc7, + 0x10, 0xaf, 0x8d, 0x0d, 0x39, 0xe2, 0x06, 0x11, + 0x14, 0xfd, 0xd0, 0x55, 0x45, 0xec, 0x1c, 0xc8, 0xab, 0x40, 0x93, 0x24, 0x7f, 0x77, 0x27, 0x5e, + 0x07, 0x43, 0xff, 0xed, 0x11, 0x71, 0x82, 0xea, 0xa9, 0xc7, 0x78, 0x77, 0xaa, 0xac, 0x6a, 0xc7, + 0xd3, 0x52, 0x45, 0xd1, 0x69, 0x2e, 0x8e, 0xe1, +}; + +static char ecdh_da_secp320k1[] = { + 0x6a, 0x5b, 0xc2, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x21, 0x8e, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x31, 0x00, 0xa0, 0xff, 0xff, 0x00, 0x00, 0x6a, 0x5b, 0xc2, 0x5e, 0x00, 0x00, 0x00, 0x00, + 0x21, 0x8e, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static char ecdh_cp_pubkey_secp320k1[] = { + 0x04, + 0x5f, 0x25, 0x77, 0xa9, 0xb5, 0x0a, 0x6f, 0xd3, 0xcb, 0x43, 0x93, 0xe0, 0xb7, 0x41, 0x3b, 0x56, + 0xc3, 0xfe, 0x1e, 0x5c, 0xb9, 0x32, 0x3a, 0x74, 0x68, 0xf8, 0x69, 0xea, 0xcf, 0x5b, 0x82, 0xd2, + 0x38, 0x8c, 0x96, 0x87, 0x97, 0xc3, 0x89, 0x9d, 0x13, 0x02, 0x40, 0xba, 0x88, 0xfa, 0x0c, 0x5a, + 0x64, 0x52, 0x7c, 0x36, 0xbd, 0xa6, 0x92, 0xb7, 0x6f, 0xb1, 0xd5, 0x81, 0xdb, 0xd5, 0x78, 0x96, + 0x50, 0x6a, 0x48, 0xec, 0x75, 0x04, 0x01, 0x3e, 0x86, 0x07, 0x74, 0x5b, 0xa7, 0x72, 0x44, 0x27 +}; + +static char ecdh_except_b_pubkey_secp320k1[] = { + 0x04, + 0x5f, 0x25, 0x77, 0xa9, 0xb5, 0x0a, 0x6f, 0xd3, 0xcb, 0x43, 0x93, 0xe0, 0xb7, 0x41, 0x3b, 0x56, + 0xc3, 0xfe, 0x1e, 0x5c, 0xb9, 0x32, 0x3a, 0x74, 0x68, 0xf8, 0x69, 0xea, 0xcf, 0x5b, 0x82, 0xd2, + 0x38, 0x8c, 0x96, 0x87, 0x97, 0xc3, 0x89, 0x9d, 0x13, 0x02, 0x40, 0xba, 0x88, 0xfa, 0x0c, 0x5a, + 0x64, 0x52, 0x7c, 0x36, 0xbd, 0xa6, 0x92, 0xb7, 0x6f, 0xb1, 0xd5, 0x81, 0xdb, 0xd5, 0x78, 0x96, + 0x50, 0x6a, 0x48, 0xec, 0x75, 0x04, 0x01, 0x3e, 0x86, 0x07, 0x74, 0x5b, 0xa7, 0x72, 0x44, 0x27 +}; + +static char ecdh_cp_sharekey_secp320k1[] = { + 0x69, 0x8a, 0x70, 0x4e, 0xf8, 0x4a, 0x9a, 0x80, 0xe8, 0x48, 0xc9, 0xb9, 0xac, 0x2a, 0x74, 0xf0, + 0xe5, 0x29, 0x60, 0x6d, 0xf3, 0x4e, 0x01, 0xa6, 0x20, 0x37, 0xc2, 0x0f, 0xba, 0x98, 0x91, 0x3b, + 0xc2, 0x75, 0xa3, 0xc6, 0x75, 0x90, 0x79, 0xb4 +}; + +/* ecc sign or verf*/ +static unsigned char ecc_except_kinv_secp320k1[] = { + 0x71, 0x71, 0xb4, 0x5b, 0x79, 0x51, 0x94, 0x70, 0x53, 0xf9, 0x77, 0x02, 0x64, 0xef, 0xc4, 0xdb, + 0x64, 0xfc, 0xbe, 0x4e, 0x44, 0x4a, 0xc6, 0x54, 0x71, 0x69, 0x2e, 0x4a, 0x46, 0xa7, 0x2d, 0xa3 +}; + +static unsigned char ecc_except_e_secp320k1[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04 +}; + +/* 384 */ +static char ecdh_a_secp384r1[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFC +}; + +static char ecdh_b_secp384r1[] = { + 0xB3, 0x31, 0x2F, 0xA7, 0xE2, 0x3E, 0xE7, 0xE4, 0x98, 0x8E, 0x05, 0x6B, + 0xE3, 0xF8, 0x2D, 0x19, 0x18, 0x1D, 0x9C, 0x6E, 0xFE, 0x81, 0x41, 0x12, + 0x03, 0x14, 0x08, 0x8F, 0x50, 0x13, 0x87, 0x5A, 0xC6, 0x56, 0x39, 0x8D, + 0x8A, 0x2E, 0xD1, 0x9D, 0x2A, 0x85, 0xC8, 0xED, 0xD3, 0xEC, 0x2A, 0xEF +}; + +static char ecdh_p_secp384r1[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF +}; + +static char ecdh_n_secp384r1[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC7, 0x63, 0x4D, 0x81, 0xF4, 0x37, 0x2D, 0xDF, 0x58, 0x1A, 0x0D, 0xB2, + 0x48, 0xB0, 0xA7, 0x7A, 0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73 +}; + +static char ecdh_g_secp384r1[] = { + 0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37, 0x8E, 0xB1, 0xC7, 0x1E, + 0xF3, 0x20, 0xAD, 0x74, 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98, + 0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38, 0x55, 0x02, 0xF2, 0x5D, + 0xBF, 0x55, 0x29, 0x6C, 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7, + 0x36, 0x17, 0xDE, 0x4A, 0x96, 0x26, 0x2C, 0x6F, 0x5D, 0x9E, 0x98, 0xBF, + 0x92, 0x92, 0xDC, 0x29, 0xF8, 0xF4, 0x1D, 0xBD, 0x28, 0x9A, 0x14, 0x7C, + 0xE9, 0xDA, 0x31, 0x13, 0xB5, 0xF0, 0xB8, 0xC0, 0x0A, 0x60, 0xB1, 0xCE, + 0x1D, 0x7E, 0x81, 0x9D, 0x7A, 0x43, 0x1D, 0x7C, 0x90, 0xEA, 0x0E, 0x5F +}; + +static char ecdh_da_secp384r1[] = { + 0xee, 0x57, 0xd7, 0xad, 0xbc, 0x8c, 0x5d, 0x82, 0x65, 0x7f, 0x03, 0xcb, 0x12, 0xc1, 0x38, 0x0d, + 0x02, 0x5c, 0xb7, 0x8f, 0xa4, 0x36, 0x56, 0x27, 0x25, 0x85, 0xaa, 0x3e, 0xdf, 0x22, 0x88, 0x7b, + 0xe3, 0xe7, 0xc5, 0xf1, 0xd7, 0x37, 0x8c, 0xc7, 0x56, 0xca, 0xa7, 0x93, 0x37, 0xbd, 0xf9, 0x37 +}; + +static char ecdh_cp_pubkey_secp384r1[] = { + 0x04, + 0x7d, 0x54, 0xd0, 0x72, 0x45, 0x4b, 0x5a, 0x48, 0xed, 0xc6, 0x19, 0xde, 0x8f, 0x1b, 0xa6, 0xfd, + 0xe5, 0x00, 0xbc, 0x74, 0xbb, 0xee, 0xdc, 0x6b, 0x1c, 0x6d, 0x36, 0xf1, 0x2a, 0x6a, 0x3c, 0xcd, + 0xd5, 0xb9, 0xf8, 0x3c, 0x57, 0xe8, 0xc2, 0xb2, 0xe6, 0x60, 0x58, 0x03, 0x3e, 0x48, 0xf4, 0xc4, + 0x4b, 0x80, 0x58, 0x8c, 0xc7, 0x65, 0x2e, 0xdd, 0x23, 0x31, 0xd2, 0xae, 0x62, 0x62, 0xc3, 0xb4, + 0x57, 0x88, 0xc6, 0x84, 0x51, 0xaf, 0x8c, 0x7b, 0x94, 0x2a, 0x43, 0x68, 0x31, 0xbd, 0x3d, 0x4f, + 0x43, 0xae, 0x79, 0x50, 0x80, 0x60, 0x09, 0xfa, 0x42, 0xfe, 0x9d, 0x18, 0xce, 0xbe, 0xfd, 0x64 +}; + +static char ecdh_except_b_pubkey_secp384r1[] = { + 0x04, + 0x7d, 0x54, 0xd0, 0x72, 0x45, 0x4b, 0x5a, 0x48, 0xed, 0xc6, 0x19, 0xde, 0x8f, 0x1b, 0xa6, 0xfd, + 0xe5, 0x00, 0xbc, 0x74, 0xbb, 0xee, 0xdc, 0x6b, 0x1c, 0x6d, 0x36, 0xf1, 0x2a, 0x6a, 0x3c, 0xcd, + 0xd5, 0xb9, 0xf8, 0x3c, 0x57, 0xe8, 0xc2, 0xb2, 0xe6, 0x60, 0x58, 0x03, 0x3e, 0x48, 0xf4, 0xc4, + 0x4b, 0x80, 0x58, 0x8c, 0xc7, 0x65, 0x2e, 0xdd, 0x23, 0x31, 0xd2, 0xae, 0x62, 0x62, 0xc3, 0xb4, + 0x57, 0x88, 0xc6, 0x84, 0x51, 0xaf, 0x8c, 0x7b, 0x94, 0x2a, 0x43, 0x68, 0x31, 0xbd, 0x3d, 0x4f, + 0x43, 0xae, 0x79, 0x50, 0x80, 0x60, 0x09, 0xfa, 0x42, 0xfe, 0x9d, 0x18, 0xce, 0xbe, 0xfd, 0x64 +}; + +static char ecdh_cp_sharekey_secp384r1[] = { + 0x82, 0x80, 0x4b, 0x00, 0x8c, 0x3c, 0x29, 0x51, 0xc8, 0x77, 0x1f, 0x72, 0xe2, 0x8c, 0x9d, 0x2a, + 0x3c, 0xf3, 0xe3, 0x7c, 0xc0, 0xc9, 0x80, 0x20, 0xe2, 0x1a, 0x45, 0xb6, 0x20, 0x13, 0x18, 0x91, + 0x61, 0xfa, 0xf1, 0x9d, 0x9f, 0xf2, 0x95, 0x78, 0xdd, 0xfe, 0x73, 0x9f, 0x09, 0x24, 0xa1, 0x4b +}; + +/* ecc sign or verf*/ +static unsigned char ecc_except_kinv_secp384r1[] = { + /* + 0x71, 0x71, 0xb4, 0x5b, 0x79, 0x51, 0x94, 0x70, 0x53, 0xf9, 0x77, 0x02, 0x64, 0xef, 0xc4, 0xdb, + 0x64, 0xfc, 0xbe, 0x4e, 0x44, 0x4a, 0xc6, 0x54, 0x71, 0x69, 0x2e, 0x4a, 0x46, 0xa7, 0x2d, 0xa3*/ +}; + +static unsigned char ecc_except_e_secp384r1[] = { + /* + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04*/ +}; + +/* 521 */ +static char ecdh_a_secp521r1[] = { + 0x01, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc +}; + +static char ecdh_b_secp521r1[] = { + 0x00, 0xe6, 0x15, 0x1c, 0x79, 0x17, 0x8d, 0x1b, 0x5c, 0xfa, + 0xbc, 0x7e, 0x53, 0x82, 0xb9, 0x33, 0xbc, 0x16, 0x2c, 0x9f, 0x27, 0xed, 0x6d, 0x79, 0x34, 0xf2, + 0xba, 0x07, 0x92, 0x9e, 0x96, 0xea, 0xe9, 0xdd, 0xb5, 0xae, 0x57, 0x7a, 0x54, 0xe1, 0x3c, 0x71, + 0xa9, 0x6e, 0x3e, 0x3d, 0x88, 0xaf, 0x92, 0x77, 0xe8, 0xe6, 0x61, 0xfe, 0xed, 0x39, 0xbd, 0x11, + 0x19, 0x25, 0x3f, 0x09, 0x4e, 0x71, 0x25, 0xcc +}; + +static char ecdh_p_secp521r1[] = { + 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +static char ecdh_n_secp521r1[] = { + 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x51, 0x86, 0x87, 0x83, 0xbf, 0x2f, 0x96, 0x6b, + 0x7f, 0xcc, 0x01, 0x48, 0xf7, 0x09, 0xa5, 0xd0, 0x3b, 0xb5, 0xc9, 0xb8, 0x89, 0x9c, 0x47, 0xae, + 0xbb, 0x6f, 0xb7, 0x1e, 0x91, 0x38, 0x64, 0x09 +}; + +static char ecdh_g_secp521r1[] = { + 0x00, 0xc6, + 0x85, 0x8e, 0x06, 0xb7, 0x04, 0x04, 0xe9, 0xcd, 0x9e, 0x3e, 0xcb, 0x66, 0x23, 0x95, 0xb4, 0x42, + 0x9c, 0x64, 0x81, 0x39, 0x05, 0x3f, 0xb5, 0x21, 0xf8, 0x28, 0xaf, 0x60, 0x6b, 0x4d, 0x3d, 0xba, + 0xa1, 0x4b, 0x5e, 0x77, 0xef, 0xe7, 0x59, 0x28, 0xfe, 0x1d, 0xc1, 0x27, 0xa2, 0xff, 0xa8, 0xde, + 0x33, 0x48, 0xb3, 0xc1, 0x85, 0x6a, 0x42, 0x9b, 0xf9, 0x7e, 0x7e, 0x31, 0xc2, 0xe5, 0xbd, 0x66, + + 0x01, 0x18, 0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b, 0xc0, 0x04, + 0x5c, 0x8a, 0x5f, 0xb4, 0x2c, 0x7d, 0x1b, 0xd9, 0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b, 0x44, 0x68, + 0x17, 0xaf, 0xbd, 0x17, 0x27, 0x3e, 0x66, 0x2c, 0x97, 0xee, 0x72, 0x99, 0x5e, 0xf4, 0x26, 0x40, + 0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad, 0x07, 0x61, 0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72, 0xc2, 0x40, + 0x88, 0xbe, 0x94, 0x76, 0x9f, 0xd1, 0x66, 0x50 +}; + +static char ecdh_da_secp521r1[] = { + 0x00, 0xe6, 0x15, 0x1c, 0x79, 0x17, 0x8d, 0x1b, 0x5c, 0xfa, + 0xbc, 0x7e, 0x53, 0x82, 0xb9, 0x33, 0xbc, 0x16, 0x2c, 0x9f, 0x27, 0xed, 0x6d, 0x79, 0x34, 0xf2, + 0xba, 0x07, 0x92, 0x9e, 0x96, 0xea, 0xe9, 0xdd, 0xb5, 0xae, 0x57, 0x7a, 0x54, 0xe1, 0x3c, 0x71, + 0xa9, 0x6e, 0x3e, 0x3d, 0x88, 0xaf, 0x92, 0x77, 0xe8, 0xe6, 0x61, 0xfe, 0xed, 0x39, 0xbd, 0x11, + 0x19, 0x25, 0x3f, 0x09, 0x4e, 0x71, 0x25, 0xcc +}; + +static char ecdh_except_b_pubkey_secp521r1[] = { + 0x04, + 0x01, 0x16, 0x0a, 0x52, 0xaa, 0x18, 0x96, 0x56, 0xf6, 0x27, 0xd1, 0x59, 0xbd, 0x7d, 0x0f, 0x57, + 0xfd, 0x34, 0xfa, 0x52, 0x1b, 0x04, 0xbd, 0x9a, 0x90, 0xd5, 0x8d, 0xad, 0x41, 0x32, 0x80, 0x14, + 0x6e, 0x73, 0x58, 0x83, 0x98, 0xeb, 0xb0, 0x6b, 0xb5, 0x63, 0x8e, 0xa1, 0x06, 0x04, 0x86, 0x94, + 0x9e, 0x34, 0x53, 0xf4, 0x93, 0x37, 0x1c, 0xbc, 0xbb, 0x7b, 0x4c, 0x97, 0x87, 0x32, 0x92, 0xf2, + 0x36, 0xdd, 0x01, 0x30, 0xa1, 0xa7, 0x68, 0x5a, 0x3e, 0x40, 0xe9, 0xbf, 0x3d, 0x2a, 0x1b, 0xbf, + 0x09, 0xa0, 0x51, 0xe8, 0x1d, 0x23, 0x27, 0x9c, 0x70, 0xb2, 0x18, 0x42, 0x02, 0x09, 0x02, 0x66, + 0xc7, 0xdb, 0x1a, 0xec, 0xe5, 0x20, 0x68, 0x31, 0x31, 0x6e, 0x70, 0xbe, 0x09, 0x72, 0x79, 0x42, + 0xe2, 0x3b, 0x3b, 0xd3, 0x0a, 0xe4, 0x9c, 0x34, 0x4c, 0x61, 0x74, 0x7c, 0xed, 0xe1, 0x84, 0x89, + 0x4b, 0xf4, 0xd5, 0xc3 +}; + +static char ecdh_cp_pubkey_secp521r1[] = { + 0x04, + 0x01, 0x16, 0x0a, 0x52, 0xaa, 0x18, 0x96, 0x56, 0xf6, 0x27, 0xd1, 0x59, 0xbd, 0x7d, 0x0f, 0x57, + 0xfd, 0x34, 0xfa, 0x52, 0x1b, 0x04, 0xbd, 0x9a, 0x90, 0xd5, 0x8d, 0xad, 0x41, 0x32, 0x80, 0x14, + 0x6e, 0x73, 0x58, 0x83, 0x98, 0xeb, 0xb0, 0x6b, 0xb5, 0x63, 0x8e, 0xa1, 0x06, 0x04, 0x86, 0x94, + 0x9e, 0x34, 0x53, 0xf4, 0x93, 0x37, 0x1c, 0xbc, 0xbb, 0x7b, 0x4c, 0x97, 0x87, 0x32, 0x92, 0xf2, + 0x36, 0xdd, 0x01, 0x30, 0xa1, 0xa7, 0x68, 0x5a, 0x3e, 0x40, 0xe9, 0xbf, 0x3d, 0x2a, 0x1b, 0xbf, + 0x09, 0xa0, 0x51, 0xe8, 0x1d, 0x23, 0x27, 0x9c, 0x70, 0xb2, 0x18, 0x42, 0x02, 0x09, 0x02, 0x66, + 0xc7, 0xdb, 0x1a, 0xec, 0xe5, 0x20, 0x68, 0x31, 0x31, 0x6e, 0x70, 0xbe, 0x09, 0x72, 0x79, 0x42, + 0xe2, 0x3b, 0x3b, 0xd3, 0x0a, 0xe4, 0x9c, 0x34, 0x4c, 0x61, 0x74, 0x7c, 0xed, 0xe1, 0x84, 0x89, + 0x4b, 0xf4, 0xd5, 0xc3 +}; + +static char ecdh_cp_sharekey_secp521r1[] = { + 0x01, 0xaf, 0x53, 0x84, 0x60, 0x59, 0x79, 0x64, 0x09, 0x5f, 0x2b, 0x4e, 0x82, 0xc4, 0x79, 0x21, + 0x55, 0x9c, 0xb0, 0x2f, 0x7d, 0xd4, 0x2f, 0x5d, 0xca, 0xfc, 0x4f, 0x70, 0x28, 0x6e, 0x2b, 0x13, + 0x2e, 0x5f, 0xf0, 0x1f, 0x50, 0x87, 0xf5, 0x82, 0x2f, 0xa7, 0x31, 0x5b, 0xfd, 0x5c, 0x0e, 0xef, + 0xaf, 0x5c, 0x80, 0x53, 0x48, 0xed, 0xcf, 0x14, 0xdc, 0x91, 0xc5, 0xc9, 0x1b, 0xff, 0xa8, 0x16, + 0x42, 0xa8 +}; + +/* ecc sign or verf*/ +static unsigned char ecc_except_kinv_secp521r1[] = { + 0x71, 0x71, 0xb4, 0x5b, 0x79, 0x51, 0x94, 0x70, 0x53, 0xf9, 0x77, 0x02, 0x64, 0xef, 0xc4, 0xdb, + 0x64, 0xfc, 0xbe, 0x4e, 0x44, 0x4a, 0xc6, 0x54, 0x71, 0x69, 0x2e, 0x4a, 0x46, 0xa7, 0x2d, 0xa3 +}; + +static unsigned char ecc_except_e_secp521r1[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04 +}; + +static unsigned char sm2_k[] = { + 0x7c, 0x47, 0x81, 0x10, 0x54, 0xc6, 0xf9, 0x96, 0x13, 0xa5, 0x78, 0xeb, 0x84, 0x53, 0x70, 0x6c, + 0xcb, 0x96, 0x38, 0x4f, 0xe7, 0xdf, 0x5c, 0x17, 0x16, 0x71, 0xe7, 0x60, 0xbf, 0xa8, 0xbe, 0x3a +}; + +static unsigned char sm2_id[] = { + 0x41, 0x4c, 0x49, 0x43, 0x45, 0x31, 0x32, 0x33, 0x40, 0x59, 0x41, 0x48, 0x4f, 0x4f, 0x2e, 0x43, + 0x4f, 0x4d +}; + +static unsigned char sm2_plaintext[] = { + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74 +}; + +static unsigned char sm2_plaintext_l[513] = { + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74 +}; + +static unsigned char sm2_sign_data[] = { + /* r */ + 0xe6, 0xcd, 0x2d, 0xf9, 0x4f, 0x57, 0x40, 0x9e, 0x6b, 0xec, 0x8c, 0x0e, 0xf0, 0x44, 0x5c, 0xa4, + 0xfa, 0xea, 0x24, 0xe3, 0xf2, 0x28, 0x0e, 0xad, 0xc1, 0xa4, 0x1c, 0xf6, 0x24, 0x88, 0xaf, 0xd2, + + /* s */ + 0x98, 0x0e, 0x4f, 0xda, 0xbd, 0xe9, 0x9e, 0xc1, 0x6d, 0x59, 0x87, 0xd0, 0x23, 0x19, 0x84, 0xd1, + 0x94, 0x07, 0x7b, 0xb5, 0x43, 0xa8, 0x93, 0x00, 0xd4, 0xbb, 0xc7, 0xf8, 0x83, 0xb3, 0xf0, 0xc3, +}; + +static unsigned char sm2_ciphertext[] = { + /* c1 x */ + 0xe6, 0xcd, 0x2d, 0xf9, 0x4f, 0x57, 0x40, 0x9e, 0x6b, 0xec, 0x8c, 0x0e, 0xf0, 0x44, 0x5c, 0xa4, + 0xfa, 0xe9, 0xb7, 0x7e, 0x7e, 0xb4, 0xad, 0x46, 0x5c, 0x83, 0xb8, 0x8c, 0xbd, 0x23, 0x3c, 0x5e, + /* c1 y */ + 0x80, 0x89, 0xf0, 0xea, 0x2c, 0x84, 0x63, 0x45, 0xd8, 0x99, 0x7b, 0x5c, 0x2c, 0x75, 0x7d, 0x8e, + 0x5c, 0x99, 0x6e, 0x46, 0x85, 0x9f, 0x19, 0xd3, 0x7e, 0xb0, 0x3b, 0x24, 0xde, 0xab, 0xae, 0x30, + /* c3 */ + 0xfb, 0xcf, 0x24, 0x19, 0xf8, 0x61, 0x1c, 0xba, 0xb1, 0xd0, 0x6f, 0x4f, 0x84, 0xda, 0x9a, 0xe6, + 0x2d, 0x42, 0x27, 0xa1, 0x2b, 0x27, 0x26, 0x32, 0xc2, 0x6d, 0xda, 0x35, 0x54, 0xf9, 0xfc, 0xf8, + /* c2 */ + 0xdf, 0xe8, 0x59, 0xe8, 0x35, 0xb3, 0x98, 0x18, 0xca, 0x56, 0xaa, 0x29, 0x7b, 0x01, +}; + +static unsigned char sm2_ciphertext_l[609] = { + 0xe6, 0xcd, 0x2d, 0xf9, 0x4f, 0x57, 0x40, 0x9e, 0x6b, 0xec, 0x8c, 0x0e, 0xf0, 0x44, 0x5c, 0xa4, + 0xfa, 0xe9, 0xb7, 0x7e, 0x7e, 0xb4, 0xad, 0x46, 0x5c, 0x83, 0xb8, 0x8c, 0xbd, 0x23, 0x3c, 0x5e, + 0x80, 0x89, 0xf0, 0xea, 0x2c, 0x84, 0x63, 0x45, 0xd8, 0x99, 0x7b, 0x5c, 0x2c, 0x75, 0x7d, 0x8e, + 0x5c, 0x99, 0x6e, 0x46, 0x85, 0x9f, 0x19, 0xd3, 0x7e, 0xb0, 0x3b, 0x24, 0xde, 0xab, 0xae, 0x30, + 0xb6, 0x1b, 0x64, 0x56, 0x32, 0x5c, 0x33, 0x34, 0xa6, 0x68, 0x5f, 0x7a, 0x4c, 0x9b, 0xf0, 0x0c, + 0xbf, 0x4d, 0x2a, 0xbf, 0x2f, 0xc2, 0xf4, 0x42, 0x13, 0x61, 0xd4, 0xbb, 0x78, 0x29, 0x0c, 0x10, + 0xdf, 0xe8, 0x59, 0xe8, 0x35, 0xb3, 0x98, 0x18, 0xca, 0x56, 0xaa, 0x29, 0x7b, 0x01, 0xfc, 0xc3, + 0x78, 0xcd, 0x8e, 0x0f, 0x12, 0x24, 0xdc, 0xaf, 0xc1, 0x3c, 0x28, 0x3d, 0xeb, 0x7c, 0x46, 0x69, + 0x5f, 0x69, 0x4e, 0xc7, 0x86, 0x99, 0xa2, 0x41, 0x2b, 0xb4, 0xce, 0x91, 0xe5, 0x6c, 0x2e, 0x10, + 0x98, 0xcd, 0x1a, 0xf8, 0xac, 0x8a, 0x26, 0x92, 0xbd, 0x62, 0xe1, 0x27, 0x7e, 0xbd, 0xe1, 0xe6, + 0xec, 0x71, 0x9c, 0xa2, 0xfd, 0xf1, 0xa6, 0xaa, 0xf0, 0x4f, 0xa6, 0x05, 0x44, 0xd7, 0xc4, 0x8a, + 0xee, 0x61, 0x44, 0x41, 0xc5, 0x27, 0x76, 0x3e, 0x55, 0x0e, 0x70, 0xb7, 0xcc, 0x9d, 0x8e, 0xe4, + 0xea, 0x45, 0xc4, 0xce, 0xfc, 0x90, 0x44, 0xb7, 0xe9, 0x98, 0x63, 0x30, 0xfd, 0xca, 0x9f, 0x45, + 0x11, 0x08, 0x59, 0x80, 0xbd, 0xf2, 0xa5, 0x62, 0x9f, 0x5d, 0xb6, 0x1a, 0x5d, 0x3c, 0x72, 0x44, + 0x3e, 0x5a, 0x7c, 0xc4, 0x1a, 0xb1, 0x77, 0x3a, 0xb7, 0xfb, 0x01, 0x8b, 0xef, 0xc0, 0xf9, 0x87, + 0x46, 0x20, 0xb7, 0xef, 0x64, 0xc8, 0x9c, 0xeb, 0x26, 0x25, 0x8a, 0x6b, 0x4f, 0x75, 0x7c, 0x86, + 0xfd, 0xe4, 0x47, 0x40, 0x2c, 0xb7, 0x5c, 0x7e, 0x98, 0xad, 0xa3, 0x3f, 0x95, 0xa0, 0x1f, 0x47, + 0x3a, 0x1f, 0xde, 0xa0, 0x29, 0x78, 0x93, 0xcd, 0xc7, 0xc8, 0x29, 0xd6, 0xbe, 0x8d, 0xee, 0x76, + 0xd0, 0xed, 0x19, 0x2b, 0x0f, 0x57, 0x52, 0xf2, 0x19, 0x8a, 0x95, 0xcf, 0x23, 0x50, 0xbb, 0x13, + 0x5e, 0x89, 0xe6, 0x30, 0x87, 0x90, 0x28, 0xa5, 0x3a, 0xba, 0x16, 0x2f, 0x15, 0x98, 0x40, 0x82, + 0xd6, 0xbb, 0xc7, 0xaf, 0xa2, 0xf5, 0x33, 0xa7, 0xba, 0xb5, 0x29, 0x78, 0x53, 0x6a, 0x03, 0xd5, + 0x5a, 0x0d, 0x9c, 0xa4, 0x31, 0xab, 0x33, 0xc2, 0x19, 0x75, 0xbb, 0x25, 0x37, 0x44, 0x00, 0xd2, + 0xfb, 0xd9, 0xa0, 0xa0, 0xb6, 0x80, 0x4b, 0xd5, 0xc2, 0x2e, 0x80, 0xec, 0x86, 0x5a, 0x9f, 0x18, + 0x7b, 0x7f, 0x40, 0x92, 0xcb, 0x98, 0x60, 0x74, 0x60, 0x48, 0xd2, 0xe2, 0x56, 0x6d, 0xee, 0x2f, + 0x97, 0x96, 0x8b, 0xaa, 0x75, 0x94, 0xb7, 0x92, 0xfc, 0xd3, 0x37, 0xfd, 0x19, 0x6b, 0x1a, 0xba, + 0xf2, 0x33, 0x5e, 0x15, 0x93, 0xb0, 0xc9, 0x0f, 0x7c, 0x6e, 0x4b, 0xc0, 0xce, 0xf2, 0x22, 0x7f, + 0xfa, 0xff, 0x78, 0x90, 0xdb, 0x3c, 0xf5, 0x4d, 0x6a, 0x5d, 0x80, 0xcb, 0x62, 0x54, 0x67, 0xae, + 0x03, 0x82, 0xaa, 0xa3, 0x63, 0x4e, 0x01, 0x25, 0x32, 0x8f, 0xe9, 0x11, 0xe7, 0x12, 0x58, 0xda, + 0x3c, 0x4d, 0x5f, 0x1e, 0xae, 0x10, 0x6c, 0x12, 0x18, 0x5d, 0xa6, 0x7a, 0x37, 0x64, 0x83, 0x64, + 0xca, 0x78, 0xd6, 0x15, 0xbc, 0xb9, 0xb6, 0xfb, 0x54, 0xf3, 0xed, 0x13, 0xc3, 0x3e, 0xad, 0x3e, + 0x57, 0xb8, 0x8c, 0xc4, 0x9f, 0x7b, 0x1f, 0x40, 0x86, 0x13, 0x40, 0xfc, 0xba, 0x0a, 0x73, 0x98, + 0xf5, 0xee, 0xc7, 0x53, 0xbb, 0x87, 0xd6, 0x9d, 0x99, 0x78, 0x8b, 0xce, 0x4a, 0x1f, 0xf7, 0x46, + 0x93, 0xd5, 0x27, 0x7e, 0x69, 0xd1, 0xe9, 0xba, 0xfd, 0x06, 0x36, 0x44, 0x21, 0xee, 0x5a, 0x5a, + 0xb0, 0xdc, 0xd6, 0xe7, 0x4e, 0x28, 0x71, 0x36, 0x45, 0xa8, 0x89, 0x3b, 0x9e, 0xfd, 0x1f, 0x0b, + 0xcd, 0x86, 0xa7, 0xb9, 0xb1, 0x74, 0xd0, 0x51, 0x3d, 0x1e, 0x8d, 0xb3, 0x4f, 0x46, 0x9f, 0xfb, + 0x36, 0x43, 0x3d, 0xff, 0xaf, 0x19, 0x29, 0xb5, 0x41, 0x4c, 0x75, 0x4d, 0x75, 0x41, 0x5e, 0xe1, + 0x86, 0x5b, 0xbb, 0x94, 0x13, 0xd3, 0xa7, 0x23, 0xb4, 0xfb, 0x6f, 0x7f, 0x36, 0xfe, 0x9f, 0xec, + 0x80, 0x56, 0x5c, 0x79, 0x78, 0x9d, 0xed, 0xe0, 0x0a, 0x68, 0xd9, 0xc1, 0x19, 0x93, 0x94, 0x2c, + 0x3d, +}; + +static unsigned char sm2_pubkey[] = { + 0x04, + 0x09, 0xf9, 0xdf, 0x31, 0x1e, 0x54, 0x21, 0xa1, 0x50, 0xdd, 0x7d, 0x16, 0x1e, 0x4b, 0xc5, 0xc6, + 0x72, 0x17, 0x9f, 0xad, 0x18, 0x33, 0xfc, 0x07, 0x6b, 0xb0, 0x8f, 0xf3, 0x56, 0xf3, 0x50, 0x20, + 0xcc, 0xea, 0x49, 0x0c, 0xe2, 0x67, 0x75, 0xa5, 0x2d, 0xc6, 0xea, 0x71, 0x8c, 0xc1, 0xaa, 0x60, + 0x0a, 0xed, 0x05, 0xfb, 0xf3, 0x5e, 0x08, 0x4a, 0x66, 0x32, 0xf6, 0x07, 0x2d, 0xa9, 0xad, 0x13 +}; + +static unsigned char sm2_priv[] = { + 0x39, 0x45, 0x20, 0x8f, 0x7b, 0x21, 0x44, 0xb1, 0x3f, 0x36, 0xe3, 0x8a, 0xc6, 0xd3, 0x9f, 0x95, + 0x88, 0x93, 0x93, 0x69, 0x28, 0x60, 0xb5, 0x1a, 0x42, 0xfb, 0x81, 0xef, 0x4d, 0xf7, 0xc5, 0xb8 +}; + +static unsigned char sm2_digest[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74 +}; +#endif diff --git a/uadk/uadk_tool/benchmark/hpre_uadk_benchmark.c b/uadk/uadk_tool/benchmark/hpre_uadk_benchmark.c new file mode 100644 index 0000000..e722c36 --- /dev/null +++ b/uadk/uadk_tool/benchmark/hpre_uadk_benchmark.c @@ -0,0 +1,2433 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include "uadk_benchmark.h" + +#include "hpre_uadk_benchmark.h" +#include "hpre_protocol_data.h" +#include "include/wd.h" +#include "include/wd_rsa.h" +#include "include/wd_dh.h" +#include "include/wd_ecc.h" +#include "include/wd_sched.h" + +#define ECC_CURVE_ID 0x3 /* def set secp256k1 */ +#define HPRE_TST_PRT printf +#define ERR_OPTYPE 0xFF +#define SM2_DG_SZ 1024 + +struct hpre_rsa_key_in { + void *e; + void *p; + void *q; + u32 e_size; + u32 p_size; + u32 q_size; + void *data[]; +}; + +static __thread struct hpre_rsa_key_in *rsa_key_in = NULL; +static const char rsa_m[8] = {0x54, 0x85, 0x9b, 0x34, 0x2c, 0x49, 0xea, 0x2a}; + +struct rsa_async_tag { + handle_t sess; +}; + +//----------------------------------RSA param--------------------------------------// +struct hpre_dh_param { + const void *x; + const void *p; + const void *g; + const void *except_pub_key; + const void *pub_key; + const void *share_key; + u32 x_size; + u32 p_size; + u32 g_size; + u32 pub_key_size; + u32 share_key_size; + u32 except_pub_key_size; + u32 key_bits; + u32 optype; +}; + +//----------------------------------DH param-------------------------------------// +struct hpre_ecc_setup { + void *except_pub_key; // use in ecdh phase 2 + const void *pub_key; // use in ecdh phase 1 + const void *share_key; // use in ecdh phase 2 + const void *digest; //use in ecdsa sign + const void *k; // ecdsa sign in + const void *rp; // x coordinate of k*generator used in ecdsa + const void *sign; // ecdsa sign out or verf in + const void *priv_key; // use in ecdsa sign + void *msg; // sm2 plaintext,ciphertext or digest input + const void *userid; // sm2 user id + const void *ciphertext; // sm2 ciphertext + const void *plaintext; // sm2 plaintext + u32 key_size; + u32 share_key_size; + u32 except_pub_key_size; + u32 digest_size; + u32 k_size; + u32 rp_size; + u32 sign_size; + u32 priv_key_size; + u32 pub_key_size; + u32 msg_size; + u32 userid_size; + u32 ciphertext_size; + u32 plaintext_size; + u32 op_type; + u32 key_bits; + u32 nid; + u32 curve_id; // WD ecc curve_id +}; + +//----------------------------------ECC param-------------------------------------// + +typedef struct uadk_thread_res { + u32 subtype; + u32 keybits; + u32 kmode; + u32 optype; + u32 td_id; +} thread_data; + +static struct wd_ctx_config g_ctx_cfg; +static struct wd_sched *g_sched; +static unsigned int g_thread_num; +static unsigned int g_ctxnum; + +static const char* const alg_operations[] = { + "GenKey", "ShareKey", "Encrypt", "Decrypt", "Sign", "Verify", +}; + +static void get_dh_param(u32 algtype, u32 *keysize) +{ + switch(algtype) { + case DH_768: + *keysize = 768; + break; + case DH_1024: + *keysize = 1024; + break; + case DH_1536: + *keysize = 1536; + break; + case DH_2048: + *keysize = 2048; + break; + case DH_3072: + *keysize = 3072; + break; + case DH_4096: + *keysize = 4096; + break; + } +} + +static u32 get_dh_optype(u32 optype) +{ + u32 op_type = 0; + + switch(optype) { + case 0: //GENKEY1 + op_type = WD_DH_PHASE1; + break; + case 1: //GENKEY12 + op_type = WD_DH_PHASE2; + break; + default: + HPRE_TST_PRT("failed to set dh op_type\n"); + HPRE_TST_PRT("DH Gen1: 0\n"); + HPRE_TST_PRT("DH Gen2: 1\n"); + return ERR_OPTYPE; + } + + return op_type; +} + +static void get_rsa_param(u32 algtype, u32 *keysize, u32 *mode) +{ + switch(algtype) { + case RSA_1024: + *keysize = 1024; + *mode = 0; + break; + case RSA_2048: + *keysize = 2048; + *mode = 0; + break; + case RSA_3072: + *keysize = 3072; + *mode = 0; + break; + case RSA_4096: + *keysize = 4096; + *mode = 0; + break; + case RSA_1024_CRT: + *keysize = 1024; + *mode = 1; + break; + case RSA_2048_CRT: + *keysize = 2048; + *mode = 1; + break; + case RSA_3072_CRT: + *keysize = 3072; + *mode = 1; + break; + case RSA_4096_CRT: + *keysize = 4096; + *mode = 1; + break; + } +} + +static u32 get_rsa_optype(u32 optype) +{ + u32 op_type = 0; + + switch(optype) { + case 0: //GENKEY1 + op_type = WD_RSA_GENKEY; + break; + case 4: //Sign + op_type = WD_RSA_SIGN; + break; + case 5: //Verf + op_type = WD_RSA_VERIFY; + break; + default: + HPRE_TST_PRT("failed to set rsa op_type\n"); + HPRE_TST_PRT("RSA Gen: 0\n"); + HPRE_TST_PRT("RSA Sign: 4\n"); + HPRE_TST_PRT("RSA Verf: 5\n"); + return ERR_OPTYPE; + } + + return op_type; +} + +static void get_ecc_param(u32 algtype, u32 *keysize) +{ + switch(algtype) { + case ECDH_256: + *keysize = 256; + break; + case ECDH_384: + *keysize = 384; + break; + case ECDH_521: + *keysize = 521; + break; + case ECDSA_256: + *keysize = 256; + break; + case ECDSA_384: + *keysize = 384; + break; + case ECDSA_521: + *keysize = 521; + break; + case SM2_ALG: + *keysize = 256; + break; + case X25519_ALG: + *keysize = 256; + break; + case X448_ALG: + *keysize = 448; + break; + } +} + +static u32 get_ecc_optype(u32 subtype, u32 optype) +{ + u32 op_type = 0; + + if (subtype == SM2_TYPE) { + switch (optype) { + case 0: + op_type = WD_SM2_KG; + break; + case 2: + op_type = WD_SM2_ENCRYPT; + break; + case 3: + op_type = WD_SM2_DECRYPT; + break; + case 4: + op_type = WD_SM2_SIGN; + break; + case 5: + op_type = WD_SM2_VERIFY; + break; + default: + HPRE_TST_PRT("failed to set SM2 op_type\n"); + HPRE_TST_PRT("SM2 KeyGen: 0\n"); + HPRE_TST_PRT("SM2 Encrypt: 2\n"); + HPRE_TST_PRT("SM2 Decrypt: 3\n"); + HPRE_TST_PRT("SM2 Sign: 4\n"); + HPRE_TST_PRT("SM2 Verify: 5\n"); + return ERR_OPTYPE; + } + } else if (subtype == ECDH_TYPE || + subtype == X25519_TYPE || subtype == X448_TYPE) { + switch(optype) { + case 0: //GENKEY + op_type = WD_ECXDH_GEN_KEY; + break; + case 1: //COMPUTEKEY + op_type = WD_ECXDH_COMPUTE_KEY; + break; + default: + HPRE_TST_PRT("failed to set ECDH op_type\n"); + HPRE_TST_PRT("ECDH GenKey: 0\n"); + HPRE_TST_PRT("ECDH ShareKey: 1\n"); + return ERR_OPTYPE; + } + } else if (subtype == ECDSA_TYPE) { + switch(optype) { + case 4: //Sign + op_type = WD_ECDSA_SIGN; + break; + case 5: //Verf + op_type = WD_ECDSA_VERIFY; + break; + default: + HPRE_TST_PRT("failed to set ECDSA op_type\n"); + HPRE_TST_PRT("ECDSA Sign: 4\n"); + HPRE_TST_PRT("ECDSA Verf: 5\n"); + return ERR_OPTYPE; + } + } + + return op_type; +} + +static int hpre_uadk_param_parse(thread_data *tddata, struct acc_option *options) +{ + u32 algtype = options->algtype; + u32 optype = 0; + u32 keysize = 0; + u32 mode = 0; + + if (algtype >= RSA_1024 && algtype <= RSA_4096_CRT) { + get_rsa_param(algtype, &keysize, &mode); + optype = get_rsa_optype(options->optype); + } else if (algtype <= DH_4096) { + get_dh_param(algtype, &keysize); + optype = get_dh_optype(options->optype); + } else if (algtype <= X448_ALG) { + get_ecc_param(algtype, &keysize); + optype = get_ecc_optype(options->subtype, options->optype); + } else { + HPRE_TST_PRT("failed to set hpre alg!\n"); + return -EINVAL; + } + + if (optype == ERR_OPTYPE) + return -EINVAL; + + /* HPRE package length is keybits */ + options->pktlen = keysize >> 3; + tddata->keybits = keysize; + tddata->kmode = mode; + tddata->optype = optype; + + HPRE_TST_PRT("%s to run %s task!\n", options->algclass, + alg_operations[options->optype]); + + return 0; +} + +static int init_hpre_ctx_config(char *alg, int subtype, int mode) +{ + struct uacce_dev_list *list; + struct sched_params param; + int i, max_node; + int ret = 0; + + max_node = numa_max_node() + 1; + if (max_node <= 0) + return -EINVAL; + + list = wd_get_accel_list(alg); + if (!list) { + HPRE_TST_PRT("failed to get %s device\n", alg); + return -ENODEV; + } + memset(&g_ctx_cfg, 0, sizeof(struct wd_ctx_config)); + g_ctx_cfg.ctx_num = g_ctxnum; + g_ctx_cfg.ctxs = calloc(g_ctxnum, sizeof(struct wd_ctx)); + if (!g_ctx_cfg.ctxs) + return -ENOMEM; + + for (i = 0; i < g_ctxnum; i++) { + g_ctx_cfg.ctxs[i].ctx = wd_request_ctx(list->dev); + g_ctx_cfg.ctxs[i].op_type = 0; // default op_type + g_ctx_cfg.ctxs[i].ctx_mode = (__u8)mode; + } + + switch(subtype) { + case RSA_TYPE: + g_sched = wd_sched_rr_alloc(SCHED_POLICY_RR, 1, max_node, wd_rsa_poll_ctx); + break; + case DH_TYPE: + g_sched = wd_sched_rr_alloc(SCHED_POLICY_RR, 1, max_node, wd_dh_poll_ctx); + break; + case ECDH_TYPE: + case ECDSA_TYPE: + case SM2_TYPE: + case X25519_TYPE: + case X448_TYPE: + g_sched = wd_sched_rr_alloc(SCHED_POLICY_RR, 1, max_node, wd_ecc_poll_ctx); + break; + default: + HPRE_TST_PRT("failed to parse alg subtype!\n"); + g_sched = NULL; + } + if (!g_sched) { + HPRE_TST_PRT("failed to alloc sched!\n"); + goto out; + } + + /* If there is no numa, we defualt config to zero */ + if (list->dev->numa_id < 0) + list->dev->numa_id = 0; + + g_sched->name = SCHED_SINGLE; + param.numa_id = list->dev->numa_id; + param.type = 0; + param.mode = mode; + param.begin = 0; + param.end = g_ctxnum - 1; + ret = wd_sched_rr_instance(g_sched, ¶m); + if (ret) { + HPRE_TST_PRT("failed to fill hpre sched data!\n"); + goto out; + } + + /* init */ + switch(subtype) { + case RSA_TYPE: + ret = wd_rsa_init(&g_ctx_cfg, g_sched); + break; + case DH_TYPE: + ret = wd_dh_init(&g_ctx_cfg, g_sched); + break; + case ECDH_TYPE: + case ECDSA_TYPE: + case SM2_TYPE: + case X25519_TYPE: + case X448_TYPE: + ret = wd_ecc_init(&g_ctx_cfg, g_sched); + break; + default: + ret = -EINVAL; + } + if (ret) { + HPRE_TST_PRT("failed to get hpre ctx!\n"); + goto out; + } + + wd_free_list_accels(list); + + return 0; +out: + free(g_ctx_cfg.ctxs); + wd_sched_rr_release(g_sched); + + return ret; +} + +static void uninit_hpre_ctx_config(int subtype) +{ + int i; + + /* uninit */ + switch(subtype) { + case RSA_TYPE: + wd_rsa_uninit(); + break; + case DH_TYPE: + wd_dh_uninit(); + break; + case ECDH_TYPE: + case ECDSA_TYPE: + case SM2_TYPE: + case X25519_TYPE: + case X448_TYPE: + wd_ecc_uninit(); + break; + default: + HPRE_TST_PRT("failed to parse alg subtype on uninit!\n"); + return; + } + + for (i = 0; i < g_ctx_cfg.ctx_num; i++) + wd_release_ctx(g_ctx_cfg.ctxs[i].ctx); + free(g_ctx_cfg.ctxs); + wd_sched_rr_release(g_sched); +} + +/*-------------------------------uadk benchmark main code-------------------------------------*/ + +void *hpre_uadk_poll(void *data) +{ + typedef int (*poll_ctx)(__u32 idx, __u32 expt, __u32 *count); + poll_ctx uadk_poll_ctx = NULL; + thread_data *pdata = (thread_data *)data; + u32 expt = ACC_QUEUE_SIZE * g_thread_num; + u32 id = pdata->td_id; + u32 last_time = 2; // poll need one more recv time + u32 count = 0; + u32 recv = 0; + int ret; + + if (id > g_ctxnum) + return NULL; + + switch(pdata->subtype) { + case RSA_TYPE: + uadk_poll_ctx = wd_rsa_poll_ctx; + break; + case DH_TYPE: + uadk_poll_ctx = wd_dh_poll_ctx; + break; + case ECDH_TYPE: + case ECDSA_TYPE: + case SM2_TYPE: + case X25519_TYPE: + case X448_TYPE: + uadk_poll_ctx = wd_ecc_poll_ctx; + break; + default: + HPRE_TST_PRT("<<<<<keybits >> 3); + + return NULL; +} + +static int get_rsa_key_from_sample(handle_t sess, char *privkey_file, + char *crt_privkey_file, u32 key_bits, u32 is_crt) +{ + struct wd_dtb wd_e, wd_d, wd_n, wd_dq, wd_dp, wd_qinv, wd_q, wd_p; + int e_bytes, d_bytes, n_bytes, q_bytes, p_bytes, qinv_bytes; + u8 *p, *q, *n, *e, *d, *dmp1, *dmq1, *iqmp; + int dq_bytes, dp_bytes, bits, wd_lenth; + u32 key_size = key_bits >> 3; + char *wd_mem; + int ret = 0; + + memset(&wd_e, 0, sizeof(wd_e)); + memset(&wd_d, 0, sizeof(wd_d)); + memset(&wd_n, 0, sizeof(wd_n)); + memset(&wd_dq, 0, sizeof(wd_dq)); + memset(&wd_dp, 0, sizeof(wd_dp)); + memset(&wd_qinv, 0, sizeof(wd_qinv)); + memset(&wd_q, 0, sizeof(wd_q)); + memset(&wd_p, 0, sizeof(wd_p)); + + bits = wd_rsa_get_key_bits(sess); + switch (bits) { + case 1024: + e = rsa_e_1024; + n = rsa_n_1024; + p = rsa_p_1024; + q = rsa_q_1024; + dmp1 = rsa_dp_1024; + dmq1 = rsa_dq_1024; + iqmp = rsa_qinv_1024; + d = rsa_d_1024; + e_bytes = ARRAY_SIZE(rsa_e_1024); + n_bytes = ARRAY_SIZE(rsa_n_1024); + q_bytes = ARRAY_SIZE(rsa_q_1024); + p_bytes = ARRAY_SIZE(rsa_p_1024); + dq_bytes = ARRAY_SIZE(rsa_dq_1024); + dp_bytes = ARRAY_SIZE(rsa_dp_1024); + qinv_bytes = ARRAY_SIZE(rsa_qinv_1024); + d_bytes = ARRAY_SIZE(rsa_d_1024); + break; + case 2048: + e = rsa_e_2048; + n = rsa_n_2048; + p = rsa_p_2048; + q = rsa_q_2048; + dmp1 = rsa_dp_2048; + dmq1 = rsa_dq_2048; + iqmp = rsa_qinv_2048; + d = rsa_d_2048; + e_bytes = ARRAY_SIZE(rsa_e_2048); + n_bytes = ARRAY_SIZE(rsa_n_2048); + q_bytes = ARRAY_SIZE(rsa_q_2048); + p_bytes = ARRAY_SIZE(rsa_p_2048); + dq_bytes = ARRAY_SIZE(rsa_dq_2048); + dp_bytes = ARRAY_SIZE(rsa_dp_2048); + qinv_bytes = ARRAY_SIZE(rsa_qinv_2048); + d_bytes = ARRAY_SIZE(rsa_d_2048); + break; + case 3072: + e = rsa_e_3072; + n = rsa_n_3072; + p = rsa_p_3072; + q = rsa_q_3072; + dmp1 = rsa_dp_3072; + dmq1 = rsa_dq_3072; + iqmp = rsa_qinv_3072; + d = rsa_d_3072; + e_bytes = ARRAY_SIZE(rsa_e_3072); + n_bytes = ARRAY_SIZE(rsa_n_3072); + q_bytes = ARRAY_SIZE(rsa_q_3072); + p_bytes = ARRAY_SIZE(rsa_p_3072); + dq_bytes = ARRAY_SIZE(rsa_dq_3072); + dp_bytes = ARRAY_SIZE(rsa_dp_3072); + qinv_bytes = ARRAY_SIZE(rsa_qinv_3072); + d_bytes = ARRAY_SIZE(rsa_d_3072); + break; + case 4096: + e = rsa_e_4096; + n = rsa_n_4096; + p = rsa_p_4096; + q = rsa_q_4096; + dmp1 = rsa_dp_4096; + dmq1 = rsa_dq_4096; + iqmp = rsa_qinv_4096; + d = rsa_d_4096; + e_bytes = ARRAY_SIZE(rsa_e_4096); + n_bytes = ARRAY_SIZE(rsa_n_4096); + q_bytes = ARRAY_SIZE(rsa_q_4096); + p_bytes = ARRAY_SIZE(rsa_p_4096); + dq_bytes = ARRAY_SIZE(rsa_dq_4096); + dp_bytes = ARRAY_SIZE(rsa_dp_4096); + qinv_bytes = ARRAY_SIZE(rsa_qinv_4096); + d_bytes = ARRAY_SIZE(rsa_d_4096); + break; + default: + HPRE_TST_PRT("invalid key bits = %d!\n", bits); + return -EINVAL; + } + + wd_lenth = e_bytes + n_bytes + q_bytes + p_bytes + dq_bytes + + dp_bytes + qinv_bytes + d_bytes; + wd_mem = malloc(wd_lenth); + if (!wd_mem) { + HPRE_TST_PRT("failed to alloc rsa key memory!\n"); + return -EINVAL; + } + + wd_e.data = wd_mem; + wd_n.data = wd_e.data + e_bytes; + + memcpy(wd_e.data, e, e_bytes); + wd_e.dsize = e_bytes; + memcpy(wd_n.data, n, n_bytes); + wd_n.dsize = n_bytes; + if (wd_rsa_set_pubkey_params(sess, &wd_e, &wd_n)) { + HPRE_TST_PRT("failed to set rsa pubkey!\n"); + ret = -EINVAL; + goto gen_fail; + } + + if (rsa_key_in) { + memcpy(rsa_key_in->e, e, e_bytes); + memcpy(rsa_key_in->p, p, p_bytes); + memcpy(rsa_key_in->q, q, q_bytes); + rsa_key_in->e_size = e_bytes; + rsa_key_in->p_size = p_bytes; + rsa_key_in->q_size = q_bytes; + } + + if (is_crt) { + wd_q.data = wd_n.data + n_bytes; + wd_p.data = wd_q.data + q_bytes; + wd_dq.data = wd_p.data + p_bytes; + wd_dp.data = wd_dq.data + dq_bytes; + wd_qinv.data = wd_dp.data + dp_bytes; + + /* CRT mode private key */ + wd_dq.dsize = dq_bytes; + memcpy(wd_dq.data, dmq1, dq_bytes); + + wd_dp.dsize = dp_bytes; + memcpy(wd_dp.data, dmp1, dp_bytes); + + wd_q.dsize = q_bytes; + memcpy(wd_q.data, q, q_bytes); + + wd_p.dsize = p_bytes; + memcpy(wd_p.data, p, p_bytes); + + wd_qinv.dsize = qinv_bytes; + memcpy(wd_qinv.data, iqmp, qinv_bytes); + + if (wd_rsa_set_crt_prikey_params(sess, &wd_dq, + &wd_dp, &wd_qinv, + &wd_q, &wd_p)) { + HPRE_TST_PRT("failed to set rsa crt prikey!\n"); + ret = -EINVAL; + goto gen_fail; + } + + if (crt_privkey_file) { + memcpy(crt_privkey_file, wd_dq.data, (key_bits >> 4) * 5); + memcpy(crt_privkey_file + (key_bits >> 4) * 5, + wd_e.data, (key_bits >> 2)); + } + + } else { + //wd_rsa_get_prikey_params(prikey, &wd_d, &wd_n); + wd_d.data = wd_mem + (wd_lenth - d_bytes); + + /* common mode private key */ + wd_d.dsize = d_bytes; + memcpy(wd_d.data, d, d_bytes); + + if (wd_rsa_set_prikey_params(sess, &wd_d, &wd_n)) { + HPRE_TST_PRT("failed to set rsa prikey!\n"); + ret = -EINVAL; + goto gen_fail; + } + + + if (privkey_file) { + memcpy(privkey_file, wd_d.data, key_size); + memcpy(privkey_file + key_size, wd_n.data, key_size); + memcpy(privkey_file + 2 * key_size, wd_e.data, key_size); + memcpy(privkey_file + 3 * key_size, wd_n.data, key_size); + } + } + +gen_fail: + free(wd_mem); + + return ret; +} + +static int get_hpre_keygen_opdata(handle_t sess, struct wd_rsa_req *req) +{ + struct wd_rsa_pubkey *pubkey; + struct wd_rsa_prikey *prikey; + struct wd_dtb t_e, t_p, t_q; + struct wd_dtb *e, *p, *q; + + wd_rsa_get_pubkey(sess, &pubkey); + wd_rsa_get_pubkey_params(pubkey, &e, NULL); + wd_rsa_get_prikey(sess, &prikey); + + if (wd_rsa_is_crt(sess)) { + wd_rsa_get_crt_prikey_params(prikey, NULL , NULL, NULL, &q, &p); + } else { + e = &t_e; + p = &t_p; + q = &t_q; + e->data = rsa_key_in->e; + e->dsize = rsa_key_in->e_size; + p->data = rsa_key_in->p; + p->dsize = rsa_key_in->p_size; + q->data = rsa_key_in->q; + q->dsize = rsa_key_in->q_size; + } + + req->src = wd_rsa_new_kg_in(sess, e, p, q); + if (!req->src) { + HPRE_TST_PRT("failed to create rsa kgen in!\n"); + return -ENOMEM; + } + req->dst = wd_rsa_new_kg_out(sess); + if (!req->dst) { + HPRE_TST_PRT("failed to create rsa kgen out!\n"); + wd_rsa_del_kg_in(sess, req->src); + return -ENOMEM; + } + + return 0; +} + +static int get_ecc_curve(struct hpre_ecc_setup *setup, u32 cid) +{ + switch (cid) { + case 0: // secp128R1 + setup->nid = 706; + setup->curve_id = WD_SECP128R1; + break; + case 1: // secp192K1 + setup->nid = 711; + setup->curve_id = WD_SECP192K1; + break; + case 2: // secp224R1 + setup->nid = 712; + setup->curve_id = WD_SECP224R1; + break; + case 3: // secp256K1 + setup->nid = 714; + setup->curve_id = WD_SECP256K1; + break; + case 4: // brainpoolP320R1 + setup->nid = 929; + setup->curve_id = WD_BRAINPOOLP320R1; + break; + case 5: // secp384R1 + setup->nid = 715; + setup->curve_id = WD_SECP384R1; + break; + case 6: // secp521R1 + setup->nid = 716; + setup->curve_id = WD_SECP521R1; + break; + default: + HPRE_TST_PRT("failed to get ecc curve id!\n"); + return -EINVAL; + } + + return 0; +} + +static int get_ecc_key_param(struct wd_ecc_curve *param, u32 key_bits) +{ + u32 key_size = (key_bits + 7) / 8; + + switch (key_bits) { + case 128: + param->a.data = ecdh_a_secp128r1; + param->b.data = ecdh_b_secp128r1; + param->p.data = ecdh_p_secp128r1; + param->n.data = ecdh_n_secp128r1; + param->g.x.data = ecdh_g_secp128r1; + param->g.y.data = ecdh_g_secp128r1 + key_size; + case 192: + param->a.data = ecdh_a_secp192k1; + param->b.data = ecdh_b_secp192k1; + param->p.data = ecdh_p_secp192k1; + param->n.data = ecdh_n_secp192k1; + param->g.x.data = ecdh_g_secp192k1; + param->g.y.data = ecdh_g_secp192k1 + key_size; + case 224: + param->a.data = ecdh_a_secp224r1; + param->b.data = ecdh_b_secp224r1; + param->p.data = ecdh_p_secp224r1; + param->n.data = ecdh_n_secp224r1; + param->g.x.data = ecdh_g_secp224r1; + param->g.y.data = ecdh_g_secp224r1 + key_size; + case 256: + param->a.data = ecdh_a_secp256k1; + param->b.data = ecdh_b_secp256k1; + param->p.data = ecdh_p_secp256k1; + param->n.data = ecdh_n_secp256k1; + param->g.x.data = ecdh_g_secp256k1; + param->g.y.data = ecdh_g_secp256k1 + key_size; + case 320: + param->a.data = ecdh_a_secp320k1; + param->b.data = ecdh_b_secp320k1; + param->p.data = ecdh_p_secp320k1; + param->n.data = ecdh_n_secp320k1; + param->g.x.data = ecdh_g_secp320k1; + param->g.y.data = ecdh_g_secp320k1 + key_size; + case 384: + param->a.data = ecdh_a_secp384r1; + param->b.data = ecdh_b_secp384r1; + param->p.data = ecdh_p_secp384r1; + param->n.data = ecdh_n_secp384r1; + param->g.x.data = ecdh_g_secp384r1; + param->g.y.data = ecdh_g_secp384r1 + key_size; + case 521: + param->a.data = ecdh_a_secp521r1; + param->b.data = ecdh_b_secp521r1; + param->p.data = ecdh_p_secp521r1; + param->n.data = ecdh_n_secp521r1; + param->g.x.data = ecdh_g_secp521r1; + param->g.y.data = ecdh_g_secp521r1 + key_size; + default: + HPRE_TST_PRT("key_bits %d not find\n", key_bits); + return -EINVAL; + } + + param->a.bsize = key_size; + param->a.dsize = key_size; + param->b.bsize = key_size; + param->b.dsize = key_size; + param->p.bsize = key_size; + param->p.dsize = key_size; + param->n.bsize = key_size; + param->n.dsize = key_size; + param->g.x.bsize = key_size; + param->g.x.dsize = key_size; + param->g.y.bsize = key_size; + param->g.y.dsize = key_size; + + return 0; +} + +static int ecc_get_rand(char *out, size_t out_len, void *usr) +{ + //int ret; + + get_rand_data((u8 *)out, out_len); + //ret = RAND_priv_bytes((void *)out, out_len); + //if (ret != 1) { + // HPRE_TST_PRT("failed to get ecc rand data:%d\n", ret); + // return -EINVAL; + //} + + return 0; +} + +static int get_ecc_param_from_sample(struct hpre_ecc_setup *setup, + u32 subtype, u32 key_bits) +{ + int key_size = (key_bits + 7) / 8; + u32 len; + + setup->key_bits = key_bits; + + if (setup->nid == 714 || key_bits == 256) { // NID_secp256k1 + /* sm2 */ + if (subtype == SM2_TYPE) { + setup->priv_key = sm2_priv; + setup->priv_key_size = sizeof(sm2_priv); + setup->pub_key = sm2_pubkey; + setup->pub_key_size = sizeof(sm2_pubkey); + + len = SM2_DG_SZ; + setup->msg = malloc(len); + if (!setup->msg) + return -1; + memset(setup->msg, 0xFF, len); + + if (true) { // for msg_sigest mode + memcpy(setup->msg, sm2_digest, sizeof(sm2_digest)); + setup->msg_size = sizeof(sm2_digest); + } else { + memcpy(setup->msg, sm2_plaintext, sizeof(sm2_plaintext)); + setup->msg_size = sizeof(sm2_plaintext); + } + + if (setup->msg_size > 512) { + setup->ciphertext = sm2_ciphertext_l; + setup->ciphertext_size = sizeof(sm2_ciphertext_l); + setup->plaintext = sm2_plaintext_l; + setup->plaintext_size = sizeof(sm2_plaintext_l); + } else { + setup->ciphertext = sm2_ciphertext; + setup->ciphertext_size = sizeof(sm2_ciphertext); + setup->plaintext = sm2_plaintext; + setup->plaintext_size = sizeof(sm2_plaintext); + } + + setup->k = sm2_k; + setup->k_size = sizeof(sm2_k); + setup->userid = sm2_id; + setup->userid_size = sizeof(sm2_id); + setup->sign = sm2_sign_data; + setup->sign_size = sizeof(sm2_sign_data); + + } else { + setup->priv_key = ecdh_da_secp256k1; + setup->except_pub_key = ecdh_except_b_pubkey_secp256k1; + setup->pub_key = ecdh_cp_pubkey_secp256k1; + setup->share_key = ecdh_cp_sharekey_secp256k1; + setup->priv_key_size = sizeof(ecdh_da_secp256k1); + setup->except_pub_key_size = sizeof(ecdh_except_b_pubkey_secp256k1); + setup->pub_key_size = sizeof(ecdh_cp_pubkey_secp256k1); + setup->share_key_size = sizeof(ecdh_cp_sharekey_secp256k1); + + /* ecc sign */ + setup->msg = ecc_except_e_secp256k1; + setup->msg_size = sizeof(ecc_except_e_secp256k1); + setup->k = ecc_except_kinv_secp256k1; + setup->k_size = sizeof(ecc_except_kinv_secp256k1); + setup->rp = ecdh_cp_pubkey_secp256k1 + 1; + setup->rp_size = key_size; + + /* ecc verf */ + setup->sign = ecc_cp_sign_secp256k1; + setup->sign_size = sizeof(ecc_cp_sign_secp256k1); + } + } else if (setup->nid == 706 || key_bits == 128) { + setup->priv_key = ecdh_da_secp128r1; + setup->except_pub_key = ecdh_except_b_pubkey_secp128r1; + setup->pub_key = ecdh_cp_pubkey_secp128r1; + setup->share_key = ecdh_cp_sharekey_secp128r1; + setup->priv_key_size = sizeof(ecdh_da_secp128r1); + setup->except_pub_key_size = sizeof(ecdh_except_b_pubkey_secp128r1); + setup->pub_key_size = sizeof(ecdh_cp_pubkey_secp128r1); + setup->share_key_size = sizeof(ecdh_cp_sharekey_secp128r1); + + /* ecc sign */ + setup->msg = ecc_except_e_secp128r1; + setup->msg_size = sizeof(ecc_except_e_secp128r1); + setup->k = ecc_except_kinv_secp128r1; + setup->k_size = sizeof(ecc_except_kinv_secp128r1); + setup->rp = ecdh_cp_pubkey_secp128r1 + 1; + setup->rp_size = key_size; + + /* ecc verf */ + setup->sign = ecc_cp_sign_secp128r1; + setup->sign_size = sizeof(ecc_cp_sign_secp128r1); + + } else if (setup->nid == 711 || key_bits == 192) { + setup->priv_key = ecdh_da_secp192k1; + setup->except_pub_key = ecdh_except_b_pubkey_secp192k1; + setup->pub_key = ecdh_cp_pubkey_secp192k1; + setup->share_key = ecdh_cp_sharekey_secp192k1; + setup->priv_key_size = sizeof(ecdh_da_secp192k1); + setup->except_pub_key_size = sizeof(ecdh_except_b_pubkey_secp192k1); + setup->pub_key_size = sizeof(ecdh_cp_pubkey_secp192k1); + setup->share_key_size = sizeof(ecdh_cp_sharekey_secp192k1); + + /* ecc sign */ + setup->msg = ecc_except_e_secp192k1; + setup->msg_size = sizeof(ecc_except_e_secp192k1); + setup->k = ecc_except_kinv_secp192k1; + setup->k_size = sizeof(ecc_except_kinv_secp192k1); + setup->rp = ecdh_cp_pubkey_secp192k1 + 1; + setup->rp_size = key_size; + + /* ecc verf */ + setup->sign = ecc_cp_sign_secp256k1; + setup->sign_size = sizeof(ecc_cp_sign_secp256k1); + } else if (setup->nid == 712 || key_bits == 224) { + setup->priv_key = ecdh_da_secp224r1; + setup->except_pub_key = ecdh_except_b_pubkey_secp224r1; + setup->pub_key = ecdh_cp_pubkey_secp224r1; + setup->share_key = ecdh_cp_sharekey_secp224r1; + setup->priv_key_size = sizeof(ecdh_da_secp224r1); + setup->except_pub_key_size = sizeof(ecdh_except_b_pubkey_secp224r1); + setup->pub_key_size = sizeof(ecdh_cp_pubkey_secp224r1); + setup->share_key_size = sizeof(ecdh_cp_sharekey_secp224r1); + } else if (setup->nid == 929 || key_bits == 320) { + setup->priv_key = ecdh_da_secp320k1; + setup->except_pub_key = ecdh_except_b_pubkey_secp320k1; + setup->pub_key = ecdh_cp_pubkey_secp320k1; + setup->share_key = ecdh_cp_sharekey_secp320k1; + setup->priv_key_size = sizeof(ecdh_da_secp320k1); + setup->except_pub_key_size = sizeof(ecdh_except_b_pubkey_secp320k1); + setup->pub_key_size = sizeof(ecdh_cp_pubkey_secp320k1); + setup->share_key_size = sizeof(ecdh_cp_sharekey_secp320k1); + + /* ecc sign */ + setup->msg = ecc_except_e_secp320k1; + setup->msg_size = sizeof(ecc_except_e_secp320k1); + setup->k = ecc_except_kinv_secp320k1; + setup->k_size = sizeof(ecc_except_kinv_secp320k1); + setup->rp = ecdh_cp_pubkey_secp192k1 + 1; + setup->rp_size = key_size; + + /* ecc verf */ + setup->sign = ecc_cp_sign_secp256k1; + setup->sign_size = sizeof(ecc_cp_sign_secp256k1); + + } else if (setup->nid == 931 || key_bits == 384) { + setup->priv_key = ecdh_da_secp384r1; + setup->except_pub_key = ecdh_except_b_pubkey_secp384r1; + setup->pub_key = ecdh_cp_pubkey_secp384r1; + setup->share_key = ecdh_cp_sharekey_secp384r1; + setup->priv_key_size = sizeof(ecdh_da_secp384r1); + setup->except_pub_key_size = sizeof(ecdh_except_b_pubkey_secp384r1); + setup->pub_key_size = sizeof(ecdh_cp_pubkey_secp384r1); + setup->share_key_size = sizeof(ecdh_cp_sharekey_secp384r1); + + /* ecc sign */ + setup->msg = ecc_except_e_secp384r1; + setup->msg_size = sizeof(ecc_except_e_secp384r1); + setup->k = ecc_except_kinv_secp384r1; + setup->k_size = sizeof(ecc_except_kinv_secp384r1); + setup->rp = ecdh_cp_pubkey_secp384r1 + 1; + setup->rp_size = key_size; + + /* ecc verf */ + setup->sign = ecc_cp_sign_secp256k1; + setup->sign_size = sizeof(ecc_cp_sign_secp256k1); + } else if (setup->nid == 716 || key_bits == 521) { + setup->priv_key = ecdh_da_secp521r1; + setup->except_pub_key = ecdh_except_b_pubkey_secp521r1; + setup->pub_key = ecdh_cp_pubkey_secp521r1; + setup->share_key = ecdh_cp_sharekey_secp521r1; + setup->priv_key_size = sizeof(ecdh_da_secp521r1); + setup->except_pub_key_size = sizeof(ecdh_except_b_pubkey_secp521r1); + setup->pub_key_size = sizeof(ecdh_cp_pubkey_secp521r1); + setup->share_key_size = sizeof(ecdh_cp_sharekey_secp521r1); + + /* ecc sign */ + setup->msg = ecc_except_e_secp521r1; + setup->msg_size = sizeof(ecc_except_e_secp521r1); + setup->k = ecc_except_kinv_secp521r1; + setup->k_size = sizeof(ecc_except_kinv_secp521r1); + setup->rp = ecdh_cp_pubkey_secp521r1 + 1; + setup->rp_size = key_size; + + /* ecc verf */ + setup->sign = ecc_cp_sign_secp256k1; + setup->sign_size = sizeof(ecc_cp_sign_secp256k1); + + } else { + HPRE_TST_PRT("init test sess setup not find this bits %d or nid %d\n", + key_bits, setup->nid); + return -EINVAL; + } + + return 0; +} + +static void *rsa_uadk_sync_run(void *arg) +{ + thread_data *pdata = (thread_data *)arg; + int key_size = pdata->keybits >> 3; + struct wd_rsa_sess_setup setup; + struct wd_rsa_req req; + void *key_info = NULL; + handle_t h_sess; + u32 count = 0; + int ret; + + memset(&setup, 0, sizeof(setup)); + memset(&req, 0, sizeof(req)); + setup.key_bits = pdata->keybits; + setup.is_crt = pdata->kmode; + + h_sess = wd_rsa_alloc_sess(&setup); + if (!h_sess) + return NULL; + + key_info = malloc(key_size * 16); + if (!key_info) { + HPRE_TST_PRT("failed to alloc RSA key info!\n"); + return NULL; + } + memset(key_info, 0, key_size * 16); + + rsa_key_in = malloc(2 * key_size + sizeof(struct hpre_rsa_key_in)); + if (!rsa_key_in) { + HPRE_TST_PRT("failed to alloc RSA key input param!\n"); + goto key_release; + } + rsa_key_in->e = rsa_key_in + 1; + rsa_key_in->p = rsa_key_in->e + key_size; + rsa_key_in->q = rsa_key_in->p + (key_size >> 1); + + ret = get_rsa_key_from_sample(h_sess, key_info, key_info, + pdata->keybits, pdata->kmode); + if (ret) { + HPRE_TST_PRT("failed to get sample key data!\n"); + goto sample_release; + } + + req.src_bytes = key_size; + req.dst_bytes = key_size; + req.op_type = pdata->optype; + if (req.op_type == WD_RSA_GENKEY) { + ret = get_hpre_keygen_opdata(h_sess, &req); + if (ret){ + HPRE_TST_PRT("failed to fill rsa key gen req!\n"); + goto sample_release; + } + } else { + req.src = malloc(key_size); + if (!req.src) { + HPRE_TST_PRT("failed to alloc rsa in buffer!\n"); + goto sample_release; + } + memset(req.src, 0, req.src_bytes); + memcpy(req.src + key_size - sizeof(rsa_m), rsa_m, sizeof(rsa_m)); + req.dst = malloc(key_size); + if (!req.dst) { + HPRE_TST_PRT("failed to alloc rsa out buffer!\n"); + goto src_release; + } + } + + do { + ret = wd_do_rsa_sync(h_sess, &req); + if (ret || req.status) { + HPRE_TST_PRT("failed to do rsa task, status: %d\n", req.status); + goto dst_release; + } + + count++; + if (get_run_state() == 0) + break; + } while(true); + + /* clean output buffer remainings in the last time operation */ + if (req.op_type == WD_RSA_GENKEY) { + char *data; + int len; + + len = wd_rsa_kg_out_data((void *)req.dst, &data); + if (len < 0) { + HPRE_TST_PRT("failed to wd rsa get key gen out data!\n"); + goto sample_release; + } + memset(data, 0, len); + + wd_rsa_del_kg_in(h_sess, req.src); + req.src = NULL; + wd_rsa_del_kg_out(h_sess, req.dst); + req.dst = NULL; + } + +dst_release: + if (req.dst) + free(req.dst); +src_release: + if (req.src) + free(req.src); +sample_release: + free(rsa_key_in); +key_release: + free(key_info); + + wd_rsa_free_sess(h_sess); + add_recv_data(count, key_size); + + return NULL; +} + +static void rsa_async_cb(void *req_t) +{ + //struct wd_rsa_req *req = req_t; + //struct rsa_async_tag *tag = req->cb_param; + //enum wd_rsa_op_type op_type = req->op_type; + //handle_t h_sess = tag->sess; + + return; +} + +static void *rsa_uadk_async_run(void *arg) +{ + thread_data *pdata = (thread_data *)arg; + int key_size = pdata->keybits >> 3; + struct rsa_async_tag *tag; + struct wd_rsa_sess_setup setup; + struct wd_rsa_req req; + void *key_info = NULL; + int try_cnt = 0; + handle_t h_sess; + u32 count = 0; + int i, ret; + + memset(&setup, 0, sizeof(setup)); + memset(&req, 0, sizeof(req)); + setup.key_bits = pdata->keybits; + setup.is_crt = pdata->kmode; + + h_sess = wd_rsa_alloc_sess(&setup); + if (!h_sess) + return NULL; + + key_info = malloc(key_size * 16); + if (!key_info) { + HPRE_TST_PRT("failed to alloc RSA key info!\n"); + return NULL; + } + memset(key_info, 0, key_size * 16); + + rsa_key_in = malloc(2 * key_size + sizeof(struct hpre_rsa_key_in)); + if (!rsa_key_in) { + HPRE_TST_PRT("failed to alloc RSA key input param!\n"); + goto key_release; + } + rsa_key_in->e = rsa_key_in + 1; + rsa_key_in->p = rsa_key_in->e + key_size; + rsa_key_in->q = rsa_key_in->p + (key_size >> 1); + + ret = get_rsa_key_from_sample(h_sess, key_info, key_info, + pdata->keybits, pdata->kmode); + if (ret) { + HPRE_TST_PRT("failed to get sample key data!\n"); + goto sample_release; + } + + req.src_bytes = key_size; + req.dst_bytes = key_size; + req.op_type = pdata->optype; + if (req.op_type == WD_RSA_GENKEY) { + ret = get_hpre_keygen_opdata(h_sess, &req); + if (ret){ + HPRE_TST_PRT("failed to fill rsa key gen req!\n"); + goto sample_release; + } + } else { + req.src = malloc(key_size); + if (!req.src) { + HPRE_TST_PRT("failed to alloc rsa in buffer!\n"); + goto sample_release; + } + memset(req.src, 0, req.src_bytes); + memcpy(req.src + key_size - sizeof(rsa_m), rsa_m, sizeof(rsa_m)); + req.dst = malloc(key_size); + if (!req.dst) { + HPRE_TST_PRT("failed to alloc rsa out buffer!\n"); + goto src_release; + } + } + + tag = malloc(sizeof(*tag) * MAX_POOL_LENTH); + if (!tag) { + HPRE_TST_PRT("failed to malloc rsa tag!\n"); + goto dst_release; + } + req.cb = rsa_async_cb; + + do { + if (get_run_state() == 0) + break; + + try_cnt = 0; + i = count % MAX_POOL_LENTH; + tag[i].sess = h_sess; + req.cb_param = &tag[i]; + + ret = wd_do_rsa_async(h_sess, &req); + if (ret == -WD_EBUSY) { + usleep(SEND_USLEEP * try_cnt); + try_cnt++; + if (try_cnt > MAX_TRY_CNT) { + HPRE_TST_PRT("Test RSA send fail %d times!\n", MAX_TRY_CNT); + try_cnt = 0; + } + continue; + } else if (ret) { + HPRE_TST_PRT("failed to do rsa async task!\n"); + goto tag_release; + } + count++; + } while(true); + + /* clean output buffer remainings in the last time operation */ + if (req.op_type == WD_RSA_GENKEY) { + char *data; + int len; + + len = wd_rsa_kg_out_data((void *)req.dst, &data); + if (len < 0) { + HPRE_TST_PRT("failed to wd rsa get key gen out data!\n"); + goto tag_release; + } + memset(data, 0, len); + + wd_rsa_del_kg_in(h_sess, req.src); + req.src = NULL; + wd_rsa_del_kg_out(h_sess, req.dst); + req.dst = NULL; + } + +tag_release: + free(tag); +dst_release: + if (req.dst) + free(req.dst); +src_release: + if (req.src) + free(req.src); +sample_release: + free(rsa_key_in); +key_release: + free(key_info); + + wd_rsa_free_sess(h_sess); + add_send_complete(); + + return NULL; +} + +static int get_dh_param_from_sample(struct hpre_dh_param *setup, + u32 key_bits, u8 is_g2) +{ + setup->key_bits = key_bits; + + switch (key_bits) { + case 768: + setup->x = dh_xa_768; + setup->p = dh_p_768; + setup->except_pub_key = dh_except_b_pubkey_768; + setup->pub_key = dh_except_a_pubkey_768; + setup->share_key = dh_share_key_768; + setup->x_size = sizeof(dh_xa_768); + setup->p_size = sizeof(dh_p_768); + setup->except_pub_key_size = sizeof(dh_except_b_pubkey_768); + setup->pub_key_size = sizeof(dh_except_a_pubkey_768); + setup->share_key_size = sizeof(dh_share_key_768); + break; + case 1024: + setup->x = dh_xa_1024; + setup->p = dh_p_1024; + setup->except_pub_key = dh_except_b_pubkey_1024; + setup->pub_key = dh_except_a_pubkey_1024; + setup->share_key = dh_share_key_1024; + setup->x_size = sizeof(dh_xa_1024); + setup->p_size = sizeof(dh_p_1024); + setup->except_pub_key_size = sizeof(dh_except_b_pubkey_1024); + setup->pub_key_size = sizeof(dh_except_a_pubkey_1024); + setup->share_key_size = sizeof(dh_share_key_1024); + break; + case 1536: + setup->x = dh_xa_1536; + setup->p = dh_p_1536; + setup->except_pub_key = dh_except_b_pubkey_1536; + setup->pub_key = dh_except_a_pubkey_1536; + setup->share_key = dh_share_key_1536; + setup->x_size = sizeof(dh_xa_1536); + setup->p_size = sizeof(dh_p_1536); + setup->except_pub_key_size = sizeof(dh_except_b_pubkey_1536); + setup->pub_key_size = sizeof(dh_except_a_pubkey_1536); + setup->share_key_size = sizeof(dh_share_key_1536); + break; + case 2048: + setup->x = dh_xa_2048; + setup->p = dh_p_2048; + setup->except_pub_key = dh_except_b_pubkey_2048; + setup->pub_key = dh_except_a_pubkey_2048; + setup->share_key = dh_share_key_2048; + setup->x_size = sizeof(dh_xa_2048); + setup->p_size = sizeof(dh_p_2048); + setup->except_pub_key_size = sizeof(dh_except_b_pubkey_2048); + setup->pub_key_size = sizeof(dh_except_a_pubkey_2048); + setup->share_key_size = sizeof(dh_share_key_2048); + break; + case 3072: + setup->x = dh_xa_3072; + setup->p = dh_p_3072; + setup->except_pub_key = dh_except_b_pubkey_3072; + setup->pub_key = dh_except_a_pubkey_3072; + setup->share_key = dh_share_key_3072; + setup->x_size = sizeof(dh_xa_3072); + setup->p_size = sizeof(dh_p_3072); + setup->except_pub_key_size = sizeof(dh_except_b_pubkey_3072); + setup->pub_key_size = sizeof(dh_except_a_pubkey_3072); + setup->share_key_size = sizeof(dh_share_key_3072); + break; + case 4096: + setup->x = dh_xa_4096; + setup->p = dh_p_4096; + setup->except_pub_key = dh_except_b_pubkey_4096; + setup->pub_key = dh_except_a_pubkey_4096; + setup->share_key = dh_share_key_4096; + setup->x_size = sizeof(dh_xa_4096); + setup->p_size = sizeof(dh_p_4096); + setup->except_pub_key_size = sizeof(dh_except_b_pubkey_4096); + setup->pub_key_size = sizeof(dh_except_a_pubkey_4096); + setup->share_key_size = sizeof(dh_share_key_4096); + break; + default: + HPRE_TST_PRT("failed to find dh keybits %u\n", key_bits); + return -EINVAL; + } + + if (is_g2) { + setup->g = dh_g_2; + } else { + setup->g = dh_g_5; + } + setup->g_size = 1; + + return 0; +} + +static int get_dh_opdata_param(handle_t h_sess, struct wd_dh_req *req, + struct hpre_dh_param *setup, int key_size) +{ + unsigned char *ag_bin = NULL; + struct wd_dtb ctx_g; + int ret; + + ag_bin = malloc(2 * key_size); + if (!ag_bin) + return -ENOMEM; + + memset(ag_bin, 0, 2 * key_size); + req->pv = ag_bin; + + req->x_p = malloc(2 * key_size); + if (!req->x_p) + goto ag_error; + + memset(req->x_p, 0, 2 * key_size); + + req->pri = malloc(2 * key_size); + if (!req->pri) + goto xp_error; + + memset(req->pri, 0, 2 * key_size); + req->pri_bytes = 2 * key_size; + + ctx_g.data = malloc(key_size); + if (!ctx_g.data) + goto ctx_release; + + if (setup->optype == WD_DH_PHASE1) { // GEN1 + memcpy(req->x_p, setup->x, setup->x_size); + memcpy(req->x_p + key_size, setup->p, setup->p_size); + memcpy(ctx_g.data, setup->g, setup->g_size); + req->pbytes = setup->p_size; + req->xbytes = setup->x_size; + ctx_g.dsize = setup->g_size; + ctx_g.bsize = key_size; + + ret = wd_dh_set_g(h_sess, &ctx_g); + if (ret) + HPRE_TST_PRT("wd_dh_set_g run failed\n"); + } else { // GEN1 + memcpy(req->x_p, setup->x, setup->x_size); + memcpy(req->x_p + key_size, setup->p, setup->p_size); + memcpy(req->pv, setup->except_pub_key, setup->except_pub_key_size); + req->pbytes = setup->p_size; + req->xbytes = setup->x_size; + req->pvbytes = setup->except_pub_key_size; + } + + free(ctx_g.data); + + return 0; + +ctx_release: + free(req->pri); +xp_error: + free(req->x_p); +ag_error: + free(req->pv); + + return -ENOMEM; +} + +static void dh_async_cb(void *req_t) +{ + //struct wd_dh_req *req = req_t; + //struct rsa_async_tag *tag = req->cb_param; + //enum wd_rsa_op_type op_type = req->op_type; + //handle_t h_sess = tag->sess; + + return; +} + +static void *dh_uadk_async_run(void *arg) +{ + thread_data *pdata = (thread_data *)arg; + int key_size = pdata->keybits >> 3; + struct wd_dh_sess_setup dh_setup; + struct rsa_async_tag *tag; + struct hpre_dh_param param; + struct wd_dh_req req; + handle_t h_sess; + int try_cnt = 0; + u32 count = 0; + int i, ret; + + memset(&dh_setup, 0, sizeof(dh_setup)); + memset(&req, 0, sizeof(req)); + dh_setup.key_bits = pdata->keybits; + if (pdata->optype == WD_DH_PHASE2) + dh_setup.is_g2 = true; // G1 is 0; G2 is 1; + + h_sess = wd_dh_alloc_sess(&dh_setup); + if (!h_sess) + return NULL; + + ret = get_dh_param_from_sample(¶m, pdata->keybits, pdata->kmode); + if (ret) + goto sess_release; + + param.optype = pdata->optype; + req.op_type = pdata->optype; + ret = get_dh_opdata_param(h_sess, &req, ¶m, key_size); + if (ret){ + HPRE_TST_PRT("failed to fill dh key gen req!\n"); + goto param_release; + } + + tag = malloc(sizeof(*tag) * MAX_POOL_LENTH); + if (!tag) { + HPRE_TST_PRT("failed to malloc rsa tag!\n"); + goto param_release; + } + req.cb = dh_async_cb; + + do { + if (get_run_state() == 0) + break; + + try_cnt = 0; + i = count % MAX_POOL_LENTH; + tag[i].sess = h_sess; + req.cb_param = &tag[i]; + + ret = wd_do_dh_async(h_sess, &req); + if (ret == -WD_EBUSY) { + usleep(SEND_USLEEP * try_cnt); + try_cnt++; + if (try_cnt > MAX_TRY_CNT) { + HPRE_TST_PRT("Test DH send fail %d times!\n", MAX_TRY_CNT); + try_cnt = 0; + } + continue; + } else if (ret) { + HPRE_TST_PRT("failed to do DH async task!\n"); + goto tag_release; + } + count++; + } while(true); + +tag_release: + free(tag); +param_release: + free(req.x_p); + free(req.pv); + free(req.pri); +sess_release: + wd_dh_free_sess(h_sess); + add_send_complete(); + + return NULL; +} + +static void *dh_uadk_sync_run(void *arg) +{ + thread_data *pdata = (thread_data *)arg; + int key_size = pdata->keybits >> 3; + struct wd_dh_sess_setup dh_setup; + struct hpre_dh_param setup; + struct wd_dh_req req; + handle_t h_sess; + u32 count = 0; + int ret; + + memset(&dh_setup, 0, sizeof(dh_setup)); + memset(&req, 0, sizeof(req)); + dh_setup.key_bits = pdata->keybits; + if (pdata->optype == WD_DH_PHASE2) + dh_setup.is_g2 = true; // G1 is 0; G2 is 1; + + h_sess = wd_dh_alloc_sess(&dh_setup); + if (!h_sess) + return NULL; + + ret = get_dh_param_from_sample(&setup, pdata->keybits, pdata->kmode); + if (ret) + goto sess_release; + + setup.optype = pdata->optype; + req.op_type = pdata->optype; + ret = get_dh_opdata_param(h_sess, &req, &setup, key_size); + if (ret){ + HPRE_TST_PRT("failed to fill dh key gen req!\n"); + goto param_release; + } + + do { + ret = wd_do_dh_sync(h_sess, &req); + if (ret || req.status) { + HPRE_TST_PRT("failed to do dh task, status: %d\n", req.status); + goto param_release; + } + + count++; + if (get_run_state() == 0) + break; + } while(true); + +param_release: + free(req.x_p); + free(req.pv); + free(req.pri); +sess_release: + wd_dh_free_sess(h_sess); + add_recv_data(count, key_size); + + return NULL; +} + +static int hpre_compute_hash(const char *in, size_t in_len, + char *out, size_t out_len, void *usr) +{ + /* perf test for none hash check */ + return 0; +} + +static int ecdsa_param_fill(handle_t h_sess, struct wd_ecc_req *req, + struct wd_ecc_key *ecc_key, struct hpre_ecc_setup *setup, + thread_data *pdata) +{ + int key_insize = (pdata->keybits + 7) / 8; + u32 optype = pdata->optype; + struct wd_ecc_out *ecc_out = NULL; + struct wd_ecc_in *ecc_in = NULL; + struct wd_ecc_point pub; + struct wd_dtb d, e, k; + int ret = 0; + + if (optype == WD_ECDSA_SIGN) {// Sign + ecc_out = wd_ecdsa_new_sign_out(h_sess); + if (!ecc_out) { + HPRE_TST_PRT("failed to get ecdsa out!\n"); + return -ENOMEM; + } + + d.data = (void *)setup->priv_key; + d.dsize = setup->priv_key_size; + d.bsize = setup->priv_key_size; + ret = wd_ecc_set_prikey(ecc_key, &d); + if (ret) { + HPRE_TST_PRT("failed to set ecdsa prikey!\n"); + goto del_ecc_out; + } + + pub.x.data = (void *)setup->pub_key + 1; + pub.x.dsize = key_insize; + pub.x.bsize = key_insize; + pub.y.data = pub.x.data + key_insize; + pub.y.dsize = key_insize; + pub.y.bsize = key_insize; + ret = wd_ecc_set_pubkey(ecc_key, &pub); + if (ret) { + HPRE_TST_PRT("failed to set ecdsa pubkey!\n"); + goto del_ecc_out; + } + + e.data = (void *)setup->msg; + e.dsize = setup->msg_size; + e.bsize = key_insize; + + k.data = (void *)setup->k; + k.dsize = setup->k_size; + k.bsize = key_insize; + ecc_in = wd_ecdsa_new_sign_in(h_sess, &e, &k); + if (!ecc_in) { + HPRE_TST_PRT("failed to get ecdsa sign in!\n"); + ret = -ENOMEM; + goto del_ecc_out; + } + + req->src = ecc_in; + req->dst = ecc_out; + } else { // Verf + pub.x.data = (void *)setup->pub_key + 1; + pub.x.dsize = key_insize; + pub.x.bsize = key_insize; + pub.y.data = pub.x.data + key_insize; + pub.y.dsize = key_insize; + pub.y.bsize = key_insize; + ret = wd_ecc_set_pubkey(ecc_key, &pub); + if (ret) { + HPRE_TST_PRT("failed to set ecdsa pubkey!\n"); + return -ENOMEM; + } + + e.data = (void *)setup->msg; + e.dsize = setup->msg_size; + e.bsize = key_insize; + + d.data = (void *)setup->sign; + d.dsize = key_insize; + d.bsize = key_insize; + k.data = d.data + key_insize; + k.dsize = key_insize; + k.bsize = key_insize; + ecc_in = wd_ecdsa_new_verf_in(h_sess, &e, &d, &k); + if (!ecc_in) { + HPRE_TST_PRT("failed to get ecdsa verf ecc in!\n"); + return -ENOMEM; + } + + req->src = ecc_in; + } + + return 0; +del_ecc_out: + if (ecc_out) + (void)wd_ecc_del_out(h_sess, ecc_out); + return ret; +} + +static int sm2_param_fill(handle_t h_sess, struct wd_ecc_req *req, + struct hpre_ecc_setup *setup, thread_data *pdata) +{ + int key_insize = (pdata->keybits + 7) / 8; + u32 optype = pdata->optype; + struct wd_ecc_out *ecc_out = NULL; + struct wd_ecc_in *ecc_in = NULL; + struct wd_ecc_point tmp; + struct wd_dtb d, e, k; + + switch (optype) { + case WD_SM2_SIGN:// Sign + ecc_out = wd_sm2_new_sign_out(h_sess); + if (!ecc_out) { + HPRE_TST_PRT("failed to alloc sm2 ecc out!\n"); + return -ENOMEM; + } + + e.data = (void *)setup->msg; + e.dsize = setup->msg_size; + e.bsize = setup->msg_size; + k.data = (void *)setup->k; + k.dsize = setup->k_size; + k.bsize = key_insize; + ecc_in = wd_sm2_new_sign_in(h_sess, &e, &k, NULL, 1); + if (!ecc_in) { + HPRE_TST_PRT("failed to alloc sm2 ecc in!\n"); + goto del_ecc_out; + } + req->src = ecc_in; + req->dst = ecc_out; + break; + case WD_SM2_VERIFY: // Verf + ecc_out = wd_sm2_new_sign_out(h_sess); + if (!ecc_out) { + HPRE_TST_PRT("failed to alloc sm2 ecc out!\n"); + return -ENOMEM; + } + + e.data = (void *)setup->msg; + e.dsize = setup->msg_size; + e.bsize = key_insize; + d.data = (void *)setup->sign; + d.dsize = key_insize; + d.bsize = key_insize; + k.data = d.data + key_insize; + k.dsize = key_insize; + k.bsize = key_insize; + ecc_in = wd_sm2_new_verf_in(h_sess, &e, &d, &k, NULL, 1); + if (!ecc_in) { + HPRE_TST_PRT("failed to alloc sm2 ecc in!\n"); + goto del_ecc_out; + } + + req->src = ecc_in; + req->dst = ecc_out; + break; + case WD_SM2_ENCRYPT: // Enc + ecc_out = wd_sm2_new_enc_out(h_sess, setup->msg_size); + if (!ecc_out) { + HPRE_TST_PRT("failed to alloc sm2 ecc out!\n"); + return -ENOMEM; + } + + e.data = (void *)setup->plaintext; + e.dsize = setup->plaintext_size; + e.bsize = setup->plaintext_size; + k.data = (void *)setup->k; + k.dsize = setup->k_size; + k.bsize = key_insize; + ecc_in = wd_sm2_new_enc_in(h_sess, &e, &k); + if (!ecc_in) { + HPRE_TST_PRT("failed to alloc sm2 ecc in!\n"); + goto del_ecc_out; + } + req->src = ecc_in; + req->dst = ecc_out; + break; + case WD_SM2_DECRYPT: // Dec + tmp.x.data = (void *)setup->ciphertext; + tmp.x.dsize = 32; + tmp.y.data = tmp.x.data + 32; + tmp.y.dsize = 32; + e.data = tmp.y.data + 32; + e.dsize = 32; + d.data = e.data + 32; + d.dsize = setup->ciphertext_size - 32 * 3; + ecc_in = wd_sm2_new_dec_in(h_sess, &tmp, &d, &e); + if (!ecc_in) { + HPRE_TST_PRT("failed to alloc sm2 ecc in!\n"); + return -ENOMEM; + } + + ecc_out = wd_sm2_new_dec_out(h_sess, d.dsize); + if (!ecc_out) { + HPRE_TST_PRT("failed to alloc sm2 ecc out!\n"); + goto del_ecc_in; + } + + req->src = ecc_in; + req->dst = ecc_out; + break; + case WD_SM2_KG: // KG + ecc_out = wd_sm2_new_kg_out(h_sess); + if (!ecc_out) { + HPRE_TST_PRT("failed to alloc sm2 ecc out!\n"); + return -ENOMEM; + } + + req->dst = ecc_out; + break; + default: + HPRE_TST_PRT("failed to match sm2 optype!\n"); + return -ENOMEM; + } + + return 0; + +del_ecc_in: + if (ecc_in) + (void)wd_ecc_del_in(h_sess, ecc_in); +del_ecc_out: + if (ecc_out) + (void)wd_ecc_del_out(h_sess, ecc_out); + + return -ENOMEM; +} + +static int ecc_param_fill(handle_t h_sess, struct wd_ecc_req *req, + struct wd_ecc_key *ecc_key, struct hpre_ecc_setup *setup, + thread_data *pdata) +{ + int key_insize = (pdata->keybits + 7) / 8; + u32 subtype = pdata->subtype; + u32 optype = pdata->optype; + struct wd_ecc_out *ecc_out = NULL; + struct wd_ecc_in *ecc_in = NULL; + struct wd_ecc_point tmp; + struct wd_dtb d; + int ret = 0; + + ecc_out = wd_ecxdh_new_out(h_sess); + if (!ecc_out) { + HPRE_TST_PRT("failed to alloc ecc out!\n"); + return -ENOMEM; + } + if (optype == WD_ECXDH_GEN_KEY) { // gen + d.data = (void *)setup->priv_key; + d.dsize = setup->priv_key_size; + d.bsize = setup->priv_key_size; + ret = wd_ecc_set_prikey(ecc_key, &d); + if (ret) { + HPRE_TST_PRT("failed to set ecxdh prikey!\n"); + goto del_ecc_out; + } + + req->dst = ecc_out; + } else { // compute + if (subtype == ECDH_TYPE) + tmp.x.data = setup->except_pub_key; + else + tmp.x.data = setup->except_pub_key + 1; + tmp.x.bsize = key_insize; + tmp.x.dsize = key_insize; + tmp.y.data = tmp.x.data + key_insize; + tmp.y.bsize = key_insize; + tmp.y.dsize = key_insize; + ecc_in = wd_ecxdh_new_in(h_sess, &tmp); + if (!ecc_in) { + HPRE_TST_PRT("failed to get ecxdh sign in!\n"); + goto del_ecc_out; + } + + d.data = (void *)setup->priv_key; + d.dsize = setup->priv_key_size; + d.bsize = setup->priv_key_size; + ret = wd_ecc_set_prikey(ecc_key, &d); + if (ret) { + HPRE_TST_PRT("failed to set ecc prikey!\n"); + goto del_ecc_out; + } + + req->src = ecc_in; + req->dst = ecc_out; + } + + return 0; + +del_ecc_out: + if (ecc_out) + (void)wd_ecc_del_out(h_sess, ecc_out); + + return ret; +} + +static void *ecc_uadk_sync_run(void *arg) +{ + thread_data *pdata = (thread_data *)arg; + int key_size = pdata->keybits >> 3; + u32 subtype = pdata->subtype; + struct wd_ecc_sess_setup sess_setup; + struct hpre_ecc_setup setup; + struct wd_ecc_curve param; + struct wd_ecc_key *ecc_key; + struct wd_ecc_point pbk; + struct wd_dtb prk; + struct wd_ecc_req req; + u32 cid = ECC_CURVE_ID; + handle_t h_sess; + u32 count = 0; + int ret; + + memset(&sess_setup, 0, sizeof(sess_setup)); + memset(¶m, 0, sizeof(param)); + memset(&req, 0, sizeof(req)); + + memset(&setup, 0, sizeof(setup)); + if (subtype != X448_TYPE || subtype != X25519_TYPE) { + ret = get_ecc_curve(&setup, cid); + if (ret) + return NULL; + } + + sess_setup.key_bits = pdata->keybits; + if (subtype == ECDH_TYPE || subtype == ECDSA_TYPE) { + if (cid > ECC_CURVE_ID) { + sess_setup.cv.type = WD_CV_CFG_PARAM; + get_ecc_key_param(¶m, pdata->keybits); + sess_setup.cv.cfg.pparam = ¶m; + } else { + sess_setup.cv.type = WD_CV_CFG_ID; + sess_setup.cv.cfg.id = setup.curve_id; + } + } + + sess_setup.rand.cb = ecc_get_rand; + switch (subtype) { + case SM2_TYPE: + sess_setup.alg = "sm2"; + break; + case ECDH_TYPE: + sess_setup.alg = "ecdh"; + break; + case ECDSA_TYPE: + sess_setup.alg = "ecdsa"; + break; + } + + // set def setting; + sess_setup.hash.cb = hpre_compute_hash; + sess_setup.hash.type = WD_HASH_SHA256; + + ret = get_ecc_param_from_sample(&setup, subtype, pdata->keybits); + if (ret) + return NULL; + + h_sess = wd_ecc_alloc_sess(&sess_setup); + if (!h_sess) + goto msg_release; + + prk.data = (void *)setup.priv_key; + prk.dsize = setup.priv_key_size; + prk.bsize = setup.priv_key_size; + pbk.x.data = (char *)setup.pub_key + 1; + pbk.x.dsize = key_size; + pbk.x.bsize = key_size; + pbk.y.data = pbk.x.data + key_size; + pbk.y.dsize = key_size; + pbk.y.bsize = key_size; + + ecc_key = wd_ecc_get_key(h_sess); + ret = wd_ecc_set_prikey(ecc_key, &prk); + if (ret) { + HPRE_TST_PRT("failed to pre set ecc prikey!\n"); + goto sess_release; + } + + ret = wd_ecc_set_pubkey(ecc_key, &pbk); + if (ret) { + HPRE_TST_PRT("failed to pre set ecc pubkey!\n"); + goto sess_release; + } + + req.op_type = pdata->optype; + switch (subtype) { + case ECDSA_TYPE: // ECC alg + ret = ecdsa_param_fill(h_sess, &req, ecc_key, &setup, pdata); + if (ret) + goto src_release; + break; + case SM2_TYPE: // SM2 alg + ret = sm2_param_fill(h_sess, &req, &setup, pdata); + if (ret) + goto src_release; + break; + default: // ECDH, X25519, X448 alg + ret = ecc_param_fill(h_sess, &req, ecc_key, &setup, pdata); + if (ret) + goto src_release; + break; + } + + do { + ret = wd_do_ecc_sync(h_sess, &req); + if (ret || req.status) { + HPRE_TST_PRT("failed to do ecc task, status: %d\n", req.status); + goto src_release; + } + + count++; + if (get_run_state() == 0) + break; + } while(true); + +src_release: + if (req.src) + (void)wd_ecc_del_in(h_sess, req.src); + if (req.dst) + (void)wd_ecc_del_out(h_sess, req.dst); +sess_release: + wd_ecc_free_sess(h_sess); +msg_release: + if (subtype == SM2_TYPE) + free(setup.msg); + + add_recv_data(count, key_size); + + return NULL; +} + +static void ecc_async_cb(void *req_t) +{ + //struct wd_ecc_req *req = req_t; + //struct rsa_async_tag *tag = req->cb_param; + //enum wd_rsa_op_type op_type = req->op_type; + //handle_t h_sess = tag->sess; + + return; +} + +static void *ecc_uadk_async_run(void *arg) +{ + thread_data *pdata = (thread_data *)arg; + int key_size = pdata->keybits >> 3; + u32 subtype = pdata->subtype; + struct wd_ecc_sess_setup sess_setup; + struct rsa_async_tag *tag; + struct hpre_ecc_setup setup; + struct wd_ecc_curve param; + struct wd_ecc_key *ecc_key; + struct wd_ecc_point pbk; + struct wd_ecc_req req; + struct wd_dtb prk; + u32 cid = ECC_CURVE_ID; + handle_t h_sess; + int try_cnt = 0; + u32 count = 0; + int i, ret; + + memset(&sess_setup, 0, sizeof(sess_setup)); + memset(¶m, 0, sizeof(param)); + memset(&req, 0, sizeof(req)); + + memset(&setup, 0, sizeof(setup)); + if (subtype != X448_TYPE || subtype != X25519_TYPE) { + ret = get_ecc_curve(&setup, cid); + if (ret) + return NULL; + } + + sess_setup.key_bits = pdata->keybits; + if (subtype == ECDH_TYPE || subtype == ECDSA_TYPE) { + if (cid > ECC_CURVE_ID) { + sess_setup.cv.type = WD_CV_CFG_PARAM; + get_ecc_key_param(¶m, pdata->keybits); + sess_setup.cv.cfg.pparam = ¶m; + } else { + sess_setup.cv.type = WD_CV_CFG_ID; + sess_setup.cv.cfg.id = setup.curve_id; + } + } + + sess_setup.rand.cb = ecc_get_rand; + switch (subtype) { + case SM2_TYPE: + sess_setup.alg = "sm2"; + break; + case ECDH_TYPE: + sess_setup.alg = "ecdh"; + break; + case ECDSA_TYPE: + sess_setup.alg = "ecdsa"; + break; + } + + // set def setting; + sess_setup.hash.cb = hpre_compute_hash; + sess_setup.hash.type = WD_HASH_SHA256; + + ret = get_ecc_param_from_sample(&setup, subtype, pdata->keybits); + if (ret) + return NULL; + + h_sess = wd_ecc_alloc_sess(&sess_setup); + if (!h_sess) + goto msg_release; + + prk.data = (void *)setup.priv_key; + prk.dsize = setup.priv_key_size; + prk.bsize = setup.priv_key_size; + pbk.x.data = (char *)setup.pub_key + 1; + pbk.x.dsize = key_size; + pbk.x.bsize = key_size; + pbk.y.data = pbk.x.data + key_size; + pbk.y.dsize = key_size; + pbk.y.bsize = key_size; + + ecc_key = wd_ecc_get_key(h_sess); + ret = wd_ecc_set_prikey(ecc_key, &prk); + if (ret) { + HPRE_TST_PRT("failed to pre set ecc prikey!\n"); + goto sess_release; + } + + ret = wd_ecc_set_pubkey(ecc_key, &pbk); + if (ret) { + HPRE_TST_PRT("failed to pre set ecc pubkey!\n"); + goto sess_release; + } + + req.op_type = pdata->optype; + switch (subtype) { + case ECDSA_TYPE: // ECC alg + ret = ecdsa_param_fill(h_sess, &req, ecc_key, &setup, pdata); + if (ret) + goto src_release; + break; + case SM2_TYPE: // SM2 alg + ret = sm2_param_fill(h_sess, &req, &setup, pdata); + if (ret) + goto src_release; + break; + default: // ECDH, X25519, X448 alg + ret = ecc_param_fill(h_sess, &req, ecc_key, &setup, pdata); + if (ret) + goto src_release; + break; + } + + tag = malloc(sizeof(*tag) * MAX_POOL_LENTH); + if (!tag) { + HPRE_TST_PRT("failed to malloc rsa tag!\n"); + goto src_release; + } + req.cb = ecc_async_cb; + + do { + if (get_run_state() == 0) + break; + + try_cnt = 0; + i = count % MAX_POOL_LENTH; + tag[i].sess = h_sess; + req.cb_param = &tag[i]; + + ret = wd_do_ecc_sync(h_sess, &req); + if (ret == -WD_EBUSY) { + usleep(SEND_USLEEP * try_cnt); + try_cnt++; + if (try_cnt > MAX_TRY_CNT) { + HPRE_TST_PRT("Test ECC send fail %d times!\n", MAX_TRY_CNT); + try_cnt = 0; + } + continue; + } else if (ret) { + HPRE_TST_PRT("failed to do ECC async task!\n"); + goto tag_release; + } + count++; + } while(true); + +tag_release: + free(tag); +src_release: + if (req.src) + (void)wd_ecc_del_in(h_sess, req.src); + if (req.dst) + (void)wd_ecc_del_out(h_sess, req.dst); +sess_release: + wd_ecc_free_sess(h_sess); +msg_release: + if (subtype == SM2_TYPE) + free(setup.msg); + + add_send_complete(); + + return NULL; +} + +static int hpre_uadk_sync_threads(struct acc_option *options) +{ + typedef void *(*hpre_sync_run)(void *arg); + hpre_sync_run uadk_hpre_sync_run = NULL; + thread_data threads_args[THREADS_NUM]; + thread_data threads_option; + pthread_t tdid[THREADS_NUM]; + int i, ret; + + /* alg param parse and set to thread data */ + threads_option.subtype = options->subtype; + threads_option.td_id = 0; + ret = hpre_uadk_param_parse(&threads_option, options); + if (ret) + return ret; + + switch (options->subtype) { + case RSA_TYPE: + uadk_hpre_sync_run = rsa_uadk_sync_run; + break; + case DH_TYPE: + uadk_hpre_sync_run = dh_uadk_sync_run; + break; + case ECDH_TYPE: + case ECDSA_TYPE: + case SM2_TYPE: + case X25519_TYPE: + case X448_TYPE: + uadk_hpre_sync_run = ecc_uadk_sync_run; + break; + default: + HPRE_TST_PRT("failed to parse alg subtype on uninit!\n"); + return -EINVAL; + } + + for (i = 0; i < g_thread_num; i++) { + threads_args[i].subtype = threads_option.subtype; + threads_args[i].kmode = threads_option.kmode; + threads_args[i].keybits = threads_option.keybits; + threads_args[i].optype = threads_option.optype; + threads_args[i].td_id = i; + ret = pthread_create(&tdid[i], NULL, uadk_hpre_sync_run, &threads_args[i]); + if (ret) { + HPRE_TST_PRT("Create sync thread fail!\n"); + goto sync_error; + } + } + + /* join thread */ + for (i = 0; i < g_thread_num; i++) { + ret = pthread_join(tdid[i], NULL); + if (ret) { + HPRE_TST_PRT("Join sync thread fail!\n"); + goto sync_error; + } + } + +sync_error: + return ret; +} + +static int hpre_uadk_async_threads(struct acc_option *options) +{ + typedef void *(*hpre_async_run)(void *arg); + hpre_async_run uadk_hpre_async_run = NULL; + thread_data threads_args[THREADS_NUM]; + thread_data threads_option; + pthread_t tdid[THREADS_NUM]; + pthread_t pollid[THREADS_NUM]; + int i, ret; + + /* alg param parse and set to thread data */ + threads_option.subtype = options->subtype; + threads_option.td_id = 0; + ret = hpre_uadk_param_parse(&threads_option, options); + if (ret) + return ret; + + switch (options->subtype) { + case RSA_TYPE: + uadk_hpre_async_run = rsa_uadk_async_run; + break; + case DH_TYPE: + uadk_hpre_async_run = dh_uadk_async_run; + break; + case ECDH_TYPE: + case ECDSA_TYPE: + case SM2_TYPE: + case X25519_TYPE: + case X448_TYPE: + uadk_hpre_async_run = ecc_uadk_async_run; + break; + default: + HPRE_TST_PRT("failed to parse alg subtype on uninit!\n"); + return -EINVAL; + } + + for (i = 0; i < g_ctxnum; i++) { + threads_args[i].subtype = threads_option.subtype; + threads_args[i].td_id = i; + /* poll thread */ + ret = pthread_create(&pollid[i], NULL, hpre_uadk_poll, &threads_args[i]); + if (ret) { + HPRE_TST_PRT("Create poll thread fail!\n"); + goto async_error; + } + } + + for (i = 0; i < g_thread_num; i++) { + threads_args[i].subtype = threads_option.subtype; + threads_args[i].kmode = threads_option.kmode; + threads_args[i].keybits = threads_option.keybits; + threads_args[i].optype = threads_option.optype; + threads_args[i].td_id = i; + ret = pthread_create(&tdid[i], NULL, uadk_hpre_async_run, &threads_args[i]); + if (ret) { + HPRE_TST_PRT("Create async thread fail!\n"); + goto async_error; + } + } + + /* join thread */ + for (i = 0; i < g_thread_num; i++) { + ret = pthread_join(tdid[i], NULL); + if (ret) { + HPRE_TST_PRT("Join async thread fail!\n"); + goto async_error; + } + } + + for (i = 0; i < g_ctxnum; i++) { + ret = pthread_join(pollid[i], NULL); + if (ret) { + HPRE_TST_PRT("Join poll thread fail!\n"); + goto async_error; + } + } + +async_error: + return ret; +} + +int hpre_uadk_benchmark(struct acc_option *options) +{ + u32 ptime; + int ret; + + g_thread_num = options->threads; + g_ctxnum = options->ctxnums; + + if (options->optype >= (WD_EC_OP_MAX - WD_ECDSA_VERIFY)) { + HPRE_TST_PRT("HPRE optype error: %u\n", options->optype); + return -EINVAL; + } + + ret = init_hpre_ctx_config(options->algclass, options->subtype, + options->syncmode); + if (ret) + return ret; + + get_pid_cpu_time(&ptime); + time_start(options->times); + if (options->syncmode) + ret = hpre_uadk_async_threads(options); + else + ret = hpre_uadk_sync_threads(options); + cal_perfermance_data(options, ptime); + if (ret) + return ret; + + uninit_hpre_ctx_config(options->subtype); + + return 0; +} diff --git a/uadk/uadk_tool/benchmark/hpre_uadk_benchmark.h b/uadk/uadk_tool/benchmark/hpre_uadk_benchmark.h new file mode 100644 index 0000000..7e3966d --- /dev/null +++ b/uadk/uadk_tool/benchmark/hpre_uadk_benchmark.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +#ifndef HPRE_UADK_BENCHMARK_H +#define HPRE_UADK_BENCHMARK_H + +extern int hpre_uadk_benchmark(struct acc_option *options); +#endif /* HPRE_UADK_BENCHMARK_H */ diff --git a/uadk/uadk_tool/benchmark/hpre_wd_benchmark.c b/uadk/uadk_tool/benchmark/hpre_wd_benchmark.c new file mode 100644 index 0000000..354e0e1 --- /dev/null +++ b/uadk/uadk_tool/benchmark/hpre_wd_benchmark.c @@ -0,0 +1,2553 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include "uadk_benchmark.h" + +#include "hpre_wd_benchmark.h" +#include "hpre_protocol_data.h" +#include "v1/wd.h" +#include "v1/wd_ecc.h" +#include "v1/wd_rsa.h" +#include "v1/wd_dh.h" +#include "v1/wd_bmm.h" +#include "v1/wd_util.h" + +#define ECC_CURVE_ID 0x3 /* def set secp256k1 */ +#define HPRE_TST_PRT printf +#define ERR_OPTYPE 0xFF +#define SM2_DG_SZ 1024 +#define SEND_USLEEP 100 +#define ALIGN_SIZE 128 + +static char rsa_m[8] = {0x54, 0x85, 0x9b, 0x34, 0x2c, 0x49, 0xea, 0x2a}; + +struct hpre_rsa_key_in { + void *e; + void *p; + void *q; + u32 e_size; + u32 p_size; + u32 q_size; + void *data[]; +}; +static __thread struct hpre_rsa_key_in *rsa_key_in = NULL; + +struct rsa_async_tag { + void *ctx; + int cnt; + int optype; +}; + +//----------------------------------RSA param--------------------------------------// +struct hpre_dh_param { + const void *x; + const void *p; + const void *g; + const void *except_pub_key; + const void *pub_key; + const void *share_key; + void *pool; + u32 x_size; + u32 p_size; + u32 g_size; + u32 pub_key_size; + u32 share_key_size; + u32 except_pub_key_size; + u32 key_bits; + u32 optype; +}; + +//----------------------------------DH param-------------------------------------// +struct hpre_ecc_setup { + void *except_pub_key; // use in ecdh phase 2 + const void *pub_key; // use in ecdh phase 1 + const void *share_key; // use in ecdh phase 2 + const void *degist; //ecdsa sign in + const void *k; //ecdsa sign in + const void *rp; //ecdsa sign in + const void *sign; // ecdsa sign out or verf in + const void *priv_key; // use in ecdsa sign + void *msg; // sm2 plaintext,ciphertext or digest input + const void *userid; // sm2 user id + const void *ciphertext; // sm2 ciphertext + const void *plaintext; // sm2 plaintext + u32 key_size; + u32 share_key_size; + u32 except_pub_key_size; + u32 degist_size; + u32 k_size; + u32 rp_size; + u32 sign_size; + u32 priv_key_size; + u32 pub_key_size; + u32 msg_size; + u32 userid_size; + u32 ciphertext_size; + u32 plaintext_size; + u32 op_type; + u32 key_bits; + u32 nid; + u32 curve_id; // WD ecc curve_id +}; + +//----------------------------------ECC param-------------------------------------// +struct thread_bd_res { + struct wd_queue *queue; + void *pool; +}; + +struct thread_queue_res { + struct thread_bd_res *bd_res; +}; + +typedef struct uadk_thread_res { + u32 subtype; + u32 keybits; + u32 kmode; + u32 optype; + u32 td_id; +} thread_data; + +static unsigned int g_thread_num; +static struct thread_queue_res g_thread_queue; + +static const char* const alg_operations[] = { + "GenKey", "ShareKey", "Encrypt", "Decrypt", "Sign", "Verify", +}; + +static void get_rsa_param(u32 algtype, u32 *keysize, u32 *mode) +{ + switch(algtype) { + case RSA_1024: + *keysize = 1024; + *mode = 0; + break; + case RSA_2048: + *keysize = 2048; + *mode = 0; + break; + case RSA_3072: + *keysize = 3072; + *mode = 0; + break; + case RSA_4096: + *keysize = 4096; + *mode = 0; + break; + case RSA_1024_CRT: + *keysize = 1024; + *mode = 1; + break; + case RSA_2048_CRT: + *keysize = 2048; + *mode = 1; + break; + case RSA_3072_CRT: + *keysize = 3072; + *mode = 1; + break; + case RSA_4096_CRT: + *keysize = 4096; + *mode = 1; + break; + } +} + +static u32 get_rsa_optype(u32 optype) +{ + u32 op_type = 0; + + switch(optype) { + case 0: //GENKEY1 + op_type = WCRYPTO_RSA_GENKEY; + break; + case 4: //Sign + op_type = WCRYPTO_RSA_SIGN; + break; + case 5: //Verf + op_type = WCRYPTO_RSA_VERIFY; + break; + default: + HPRE_TST_PRT("failed to set rsa op_type\n"); + HPRE_TST_PRT("RSA Gen: 0\n"); + HPRE_TST_PRT("RSA Sign: 4\n"); + HPRE_TST_PRT("RSA Verf: 5\n"); + return ERR_OPTYPE; + } + + return op_type; +} + +static void get_dh_param(u32 algtype, u32 *keysize) +{ + switch(algtype) { + case DH_768: + *keysize = 768; + break; + case DH_1024: + *keysize = 1024; + break; + case DH_1536: + *keysize = 1536; + break; + case DH_2048: + *keysize = 2048; + break; + case DH_3072: + *keysize = 3072; + break; + case DH_4096: + *keysize = 4096; + break; + } +} + +static u32 get_dh_optype(u32 optype) +{ + u32 op_type = 0; + + switch(optype) { + case 0: //GENKEY1 + op_type = WCRYPTO_DH_PHASE1; + break; + case 1: //GENKEY12 + op_type = WCRYPTO_DH_PHASE2; + break; + default: + HPRE_TST_PRT("failed to set dh op_type\n"); + HPRE_TST_PRT("DH Gen1: 0\n"); + HPRE_TST_PRT("DH Gen2: 1\n"); + return ERR_OPTYPE; + } + + return op_type; +} + +static void get_ecc_param(u32 algtype, u32 *keysize) +{ + switch(algtype) { + case ECDH_256: + *keysize = 256; + break; + case ECDH_384: + *keysize = 384; + break; + case ECDH_521: + *keysize = 521; + break; + case ECDSA_256: + *keysize = 256; + break; + case ECDSA_384: + *keysize = 384; + break; + case ECDSA_521: + *keysize = 521; + break; + case SM2_ALG: + *keysize = 256; + break; + case X25519_ALG: + *keysize = 256; + break; + case X448_ALG: + *keysize = 448; + break; + } +} + +static u32 get_ecc_optype(u32 subtype, u32 optype) +{ + u32 op_type = 0; + + if (subtype == SM2_TYPE) { + switch (optype) { + case 0: + op_type = WCRYPTO_SM2_KG; + break; + case 2: + op_type = WCRYPTO_SM2_ENCRYPT; + break; + case 3: + op_type = WCRYPTO_SM2_DECRYPT; + break; + case 4: + op_type = WCRYPTO_SM2_SIGN; + break; + case 5: + op_type = WCRYPTO_SM2_VERIFY; + break; + default: + HPRE_TST_PRT("failed to set SM2 op_type\n"); + HPRE_TST_PRT("SM2 KeyGen: 0\n"); + HPRE_TST_PRT("SM2 Encrypt: 2\n"); + HPRE_TST_PRT("SM2 Decrypt: 3\n"); + HPRE_TST_PRT("SM2 Sign: 4\n"); + HPRE_TST_PRT("SM2 Verify: 5\n"); + return ERR_OPTYPE; + } + } else if (subtype == ECDH_TYPE || + subtype == X25519_TYPE || subtype == X448_TYPE) { + switch(optype) { + case 0: //GENKEY + op_type = WCRYPTO_ECXDH_GEN_KEY; + break; + case 1: //COMPUTEKEY + op_type = WCRYPTO_ECXDH_COMPUTE_KEY; + break; + default: + HPRE_TST_PRT("failed to set ECDH op_type\n"); + HPRE_TST_PRT("ECDH GenKey: 0\n"); + HPRE_TST_PRT("ECDH ShareKey: 1\n"); + return ERR_OPTYPE; + } + } else if (subtype == ECDSA_TYPE) { + switch(optype) { + case 4: //Sign + op_type = WCRYPTO_ECDSA_SIGN; + break; + case 5: //Verf + op_type = WCRYPTO_ECDSA_VERIFY; + break; + default: + HPRE_TST_PRT("failed to set ECDSA op_type\n"); + HPRE_TST_PRT("ECDSA Sign: 4\n"); + HPRE_TST_PRT("ECDSA Verf: 5\n"); + return ERR_OPTYPE; + } + } + + return op_type; +} + +static int hpre_wd_param_parse(thread_data *tddata, struct acc_option *options) +{ + u32 algtype = options->algtype; + u32 optype = 0; + u32 keysize = 0; + u32 mode = 0; + + if (algtype >= RSA_1024 && algtype <= RSA_4096_CRT) { + get_rsa_param(algtype, &keysize, &mode); + optype = get_rsa_optype(options->optype); + } else if (algtype <= DH_4096) { + get_dh_param(algtype, &keysize); + optype = get_dh_optype(options->optype); + } else if (algtype <= X448_ALG) { + get_ecc_param(algtype, &keysize); + optype = get_ecc_optype(options->subtype, options->optype); + } else { + HPRE_TST_PRT("failed to set hpre alg!\n"); + return -EINVAL; + } + + if (optype == ERR_OPTYPE) + return -EINVAL; + + /* HPRE package length is keybits */ + options->pktlen = keysize >> 3; + tddata->keybits = keysize; + tddata->kmode = mode; + tddata->optype = optype; + + HPRE_TST_PRT("%s to run %s task!\n", options->algclass, + alg_operations[options->optype]); + + return 0; +} + +static int hpre_wd_get_block(u32 algtype) +{ + int block_size = 512; + + switch(algtype) { + case RSA_1024: + block_size = 1280; + break; + case RSA_2048: + block_size = 2560; + break; + case RSA_3072: + block_size = 3840; + break; + case RSA_4096: + block_size = 5120; + break; + case RSA_1024_CRT: + block_size = 1280; + break; + case RSA_2048_CRT: + block_size = 2560; + break; + case RSA_3072_CRT: + block_size = 3840; + break; + case RSA_4096_CRT: + block_size = 5120; + break; + case DH_768: + block_size = 1536; + break; + case DH_1024: + block_size = 2048; + break; + case DH_1536: + block_size = 3072; + break; + case DH_2048: + block_size = 4096; + break; + case DH_3072: + block_size = 6144; + break; + case DH_4096: + block_size = 8192; + break; + case ECDH_256: + block_size = 256; + break; + case ECDH_384: + block_size = 384; + break; + case ECDH_521: + block_size = 576; + break; + case ECDSA_256: + block_size = 256; + break; + case ECDSA_384: + block_size = 384; + break; + case ECDSA_521: + block_size = 576; + break; + case SM2_ALG: + block_size = 4352; + break; + case X25519_ALG: + block_size = 256; + break; + case X448_ALG: + block_size = 384; + break; + } + + return block_size; +} + +static int init_hpre_wd_queue(struct acc_option *options) +{ + u32 blocksize = hpre_wd_get_block(options->algtype); + struct wd_blkpool_setup blksetup; + int i, j, ret; + + g_thread_queue.bd_res = malloc(g_thread_num * sizeof(struct thread_bd_res)); + if (!g_thread_queue.bd_res) { + HPRE_TST_PRT("malloc thread res memory fail!\n"); + return -ENOMEM; + } + + for (i = 0; i < g_thread_num; i++) { + g_thread_queue.bd_res[i].queue = malloc(sizeof(struct wd_queue)); + g_thread_queue.bd_res[i].queue->capa.alg = options->algclass; + // 0 is ENC, 1 is DEC + g_thread_queue.bd_res[i].queue->capa.priv.direction = options->optype; + /* nodemask need to be clean */ + g_thread_queue.bd_res[i].queue->node_mask = 0x0; + memset(g_thread_queue.bd_res[i].queue->dev_path, 0x0, PATH_STR_SIZE); + + ret = wd_request_queue(g_thread_queue.bd_res[i].queue); + if (ret) { + HPRE_TST_PRT("request queue %d fail!\n", i); + goto queue_out; + } + } + + // use no-sva pbuffer, MAX_BLOCK_NM at least 4 times of thread inside alloc + memset(&blksetup, 0, sizeof(blksetup)); + blksetup.block_size = blocksize; + blksetup.block_num = MAX_BLOCK_NM; + blksetup.align_size = ALIGN_SIZE; + // HPRE_TST_PRT("create pool memory: %d KB\n", (MAX_BLOCK_NM * blksetup.block_size) >> 10); + + for (j = 0; j < g_thread_num; j++) { + g_thread_queue.bd_res[j].pool = wd_blkpool_create(g_thread_queue.bd_res[j].queue, &blksetup); + if (!g_thread_queue.bd_res[j].pool) { + HPRE_TST_PRT("create %dth pool fail!\n", j); + ret = -ENOMEM; + goto pool_err; + } + } + + return 0; + +pool_err: + for (j--; j >= 0; j--) + wd_blkpool_destroy(g_thread_queue.bd_res[j].pool); +queue_out: + for (i--; i >= 0; i--) { + wd_release_queue(g_thread_queue.bd_res[i].queue); + free(g_thread_queue.bd_res[i].queue); + } + free(g_thread_queue.bd_res); + return ret; +} + +static void uninit_hpre_wd_queue(void) +{ + int j; + + for (j = 0; j < g_thread_num; j++) { + wd_blkpool_destroy(g_thread_queue.bd_res[j].pool); + wd_release_queue(g_thread_queue.bd_res[j].queue); + } + + free(g_thread_queue.bd_res); +} + +/*-------------------------------uadk benchmark main code-------------------------------------*/ + +void *hpre_wd_poll(void *data) +{ + typedef int (*poll_ctx)(struct wd_queue *q, unsigned int num); + thread_data *pdata = (thread_data *)data; + u32 expt = ACC_QUEUE_SIZE * g_thread_num; + poll_ctx wd_poll_ctx = NULL; + struct wd_queue *queue; + u32 id = pdata->td_id; + u32 last_time = 2; // poll need one more recv time + u32 count = 0; + int recv = 0; + + if (id > g_thread_num) + return NULL; + + queue = g_thread_queue.bd_res[id].queue; + switch(pdata->subtype) { + case RSA_TYPE: + wd_poll_ctx = wcrypto_rsa_poll; + break; + case DH_TYPE: + wd_poll_ctx = wcrypto_dh_poll; + break; + case ECDH_TYPE: + case X25519_TYPE: + case X448_TYPE: + wd_poll_ctx = wcrypto_ecxdh_poll; + break; + case ECDSA_TYPE: + wd_poll_ctx = wcrypto_ecdsa_poll; + break; + case SM2_TYPE: + wd_poll_ctx = wcrypto_sm2_poll; + break; + default: + HPRE_TST_PRT("wd async poll interface is NULL!\n"); + return NULL; + } + + while (last_time) { + recv = wd_poll_ctx(queue, expt); + /* + * async mode poll easy to 100% with small package. + * SEC_TST_PRT("poll %d recv: %u!\n", i, recv); + */ + + if (unlikely(recv < 0)) { + HPRE_TST_PRT("poll ret: %u!\n", recv); + goto recv_error; + } + count += recv; + recv = 0; + + if (get_run_state() == 0) + last_time--; + } + +recv_error: + add_recv_data(count, pdata->keybits >> 3); + + return NULL; +} + +static int get_rsa_key_from_sample(void *ctx, char *privkey_file, + char *crt_privkey_file, u32 key_bits, u32 is_crt) +{ + struct wd_dtb wd_e, wd_d, wd_n, wd_dq, wd_dp, wd_qinv, wd_q, wd_p; + int e_bytes, d_bytes, n_bytes, q_bytes, p_bytes, qinv_bytes; + u8 *p, *q, *n, *e, *d, *dmp1, *dmq1, *iqmp; + int dq_bytes, dp_bytes, bits, wd_lenth; + u32 key_size = key_bits >> 3; + char *wd_mem; + int ret = 0; + + memset(&wd_e, 0, sizeof(wd_e)); + memset(&wd_d, 0, sizeof(wd_d)); + memset(&wd_n, 0, sizeof(wd_n)); + memset(&wd_dq, 0, sizeof(wd_dq)); + memset(&wd_dp, 0, sizeof(wd_dp)); + memset(&wd_qinv, 0, sizeof(wd_qinv)); + memset(&wd_q, 0, sizeof(wd_q)); + memset(&wd_p, 0, sizeof(wd_p)); + + bits = wcrypto_rsa_key_bits(ctx); + switch (bits) { + case 1024: + e = rsa_e_1024; + n = rsa_n_1024; + p = rsa_p_1024; + q = rsa_q_1024; + dmp1 = rsa_dp_1024; + dmq1 = rsa_dq_1024; + iqmp = rsa_qinv_1024; + d = rsa_d_1024; + e_bytes = ARRAY_SIZE(rsa_e_1024); + n_bytes = ARRAY_SIZE(rsa_n_1024); + q_bytes = ARRAY_SIZE(rsa_q_1024); + p_bytes = ARRAY_SIZE(rsa_p_1024); + dq_bytes = ARRAY_SIZE(rsa_dq_1024); + dp_bytes = ARRAY_SIZE(rsa_dp_1024); + qinv_bytes = ARRAY_SIZE(rsa_qinv_1024); + d_bytes = ARRAY_SIZE(rsa_d_1024); + break; + case 2048: + e = rsa_e_2048; + n = rsa_n_2048; + p = rsa_p_2048; + q = rsa_q_2048; + dmp1 = rsa_dp_2048; + dmq1 = rsa_dq_2048; + iqmp = rsa_qinv_2048; + d = rsa_d_2048; + e_bytes = ARRAY_SIZE(rsa_e_2048); + n_bytes = ARRAY_SIZE(rsa_n_2048); + q_bytes = ARRAY_SIZE(rsa_q_2048); + p_bytes = ARRAY_SIZE(rsa_p_2048); + dq_bytes = ARRAY_SIZE(rsa_dq_2048); + dp_bytes = ARRAY_SIZE(rsa_dp_2048); + qinv_bytes = ARRAY_SIZE(rsa_qinv_2048); + d_bytes = ARRAY_SIZE(rsa_d_2048); + break; + case 3072: + e = rsa_e_3072; + n = rsa_n_3072; + p = rsa_p_3072; + q = rsa_q_3072; + dmp1 = rsa_dp_3072; + dmq1 = rsa_dq_3072; + iqmp = rsa_qinv_3072; + d = rsa_d_3072; + e_bytes = ARRAY_SIZE(rsa_e_3072); + n_bytes = ARRAY_SIZE(rsa_n_3072); + q_bytes = ARRAY_SIZE(rsa_q_3072); + p_bytes = ARRAY_SIZE(rsa_p_3072); + dq_bytes = ARRAY_SIZE(rsa_dq_3072); + dp_bytes = ARRAY_SIZE(rsa_dp_3072); + qinv_bytes = ARRAY_SIZE(rsa_qinv_3072); + d_bytes = ARRAY_SIZE(rsa_d_3072); + break; + case 4096: + e = rsa_e_4096; + n = rsa_n_4096; + p = rsa_p_4096; + q = rsa_q_4096; + dmp1 = rsa_dp_4096; + dmq1 = rsa_dq_4096; + iqmp = rsa_qinv_4096; + d = rsa_d_4096; + e_bytes = ARRAY_SIZE(rsa_e_4096); + n_bytes = ARRAY_SIZE(rsa_n_4096); + q_bytes = ARRAY_SIZE(rsa_q_4096); + p_bytes = ARRAY_SIZE(rsa_p_4096); + dq_bytes = ARRAY_SIZE(rsa_dq_4096); + dp_bytes = ARRAY_SIZE(rsa_dp_4096); + qinv_bytes = ARRAY_SIZE(rsa_qinv_4096); + d_bytes = ARRAY_SIZE(rsa_d_4096); + break; + default: + HPRE_TST_PRT("invalid key bits = %d!\n", bits); + return -EINVAL; + } + + wd_lenth = e_bytes + n_bytes + q_bytes + p_bytes + dq_bytes + + dp_bytes + qinv_bytes + d_bytes; + wd_mem = malloc(wd_lenth); + if (!wd_mem) { + HPRE_TST_PRT("failed to alloc rsa key memory!\n"); + return -EINVAL; + } + + wd_e.data = wd_mem; + wd_n.data = wd_e.data + e_bytes; + + memcpy(wd_e.data, e, e_bytes); + wd_e.dsize = e_bytes; + memcpy(wd_n.data, n, n_bytes); + wd_n.dsize = n_bytes; + if (wcrypto_set_rsa_pubkey_params(ctx, &wd_e, &wd_n)) { + HPRE_TST_PRT("failed to set rsa pubkey!\n"); + ret = -EINVAL; + goto gen_fail; + } + + if (rsa_key_in) { + memcpy(rsa_key_in->e, e, e_bytes); + memcpy(rsa_key_in->p, p, p_bytes); + memcpy(rsa_key_in->q, q, q_bytes); + rsa_key_in->e_size = e_bytes; + rsa_key_in->p_size = p_bytes; + rsa_key_in->q_size = q_bytes; + } + + if (is_crt) { + wd_q.data = wd_n.data + n_bytes; + wd_p.data = wd_q.data + q_bytes; + wd_dq.data = wd_p.data + p_bytes; + wd_dp.data = wd_dq.data + dq_bytes; + wd_qinv.data = wd_dp.data + dp_bytes; + + /* CRT mode private key */ + wd_dq.dsize = dq_bytes; + memcpy(wd_dq.data, dmq1, dq_bytes); + + wd_dp.dsize = dp_bytes; + memcpy(wd_dp.data, dmp1, dp_bytes); + + wd_q.dsize = q_bytes; + memcpy(wd_q.data, q, q_bytes); + + wd_p.dsize = p_bytes; + memcpy(wd_p.data, p, p_bytes); + + wd_qinv.dsize = qinv_bytes; + memcpy(wd_qinv.data, iqmp, qinv_bytes); + + if (wcrypto_set_rsa_crt_prikey_params(ctx, &wd_dq, + &wd_dp, &wd_qinv, + &wd_q, &wd_p)) { + HPRE_TST_PRT("failed to set rsa crt prikey!\n"); + ret = -EINVAL; + goto gen_fail; + } + + + if (crt_privkey_file) { + memcpy(crt_privkey_file, wd_dq.data, (key_bits >> 4) * 5); + memcpy(crt_privkey_file + (key_bits >> 4) * 5, + wd_e.data, (key_bits >> 2)); + } + + } else { + //wd_rsa_get_prikey_params(prikey, &wd_d, &wd_n); + wd_d.data = wd_mem + (wd_lenth - d_bytes); + + /* common mode private key */ + wd_d.dsize = d_bytes; + memcpy(wd_d.data, d, d_bytes); + + if (wcrypto_set_rsa_prikey_params(ctx, &wd_d, &wd_n)) { + HPRE_TST_PRT("failed to set rsa prikey!\n"); + ret = -EINVAL; + goto gen_fail; + } + + if (privkey_file) { + memcpy(privkey_file, wd_d.data, key_size); + memcpy(privkey_file + key_size, wd_n.data, key_size); + memcpy(privkey_file + 2 * key_size, wd_e.data, key_size); + memcpy(privkey_file + 3 * key_size, wd_n.data, key_size); + } + } + +gen_fail: + free(wd_mem); + + return ret; +} + +static int get_hpre_keygen_opdata(void *ctx, + struct wcrypto_rsa_op_data *opdata) +{ + struct wcrypto_rsa_pubkey *pubkey; + struct wcrypto_rsa_prikey *prikey; + struct wd_dtb t_e, t_p, t_q; + struct wd_dtb *e, *p, *q; + + wcrypto_get_rsa_pubkey(ctx, &pubkey); + wcrypto_get_rsa_pubkey_params(pubkey, &e, NULL); + wcrypto_get_rsa_prikey(ctx, &prikey); + + if (wcrypto_rsa_is_crt(ctx)) { + wcrypto_get_rsa_crt_prikey_params(prikey, NULL , NULL, NULL, &q, &p); + } else { + e = &t_e; + p = &t_p; + q = &t_q; + e->data = rsa_key_in->e; + e->dsize = rsa_key_in->e_size; + p->data = rsa_key_in->p; + p->dsize = rsa_key_in->p_size; + q->data = rsa_key_in->q; + q->dsize = rsa_key_in->q_size; + } + + opdata->in = wcrypto_new_kg_in(ctx, e, p, q); + if (!opdata->in) { + HPRE_TST_PRT("failed to create rsa kgen in!\n"); + return -ENOMEM; + } + opdata->out = wcrypto_new_kg_out(ctx); + if (!opdata->out) { + HPRE_TST_PRT("failed to create rsa kgen out!\n"); + wcrypto_del_kg_in(ctx, opdata->in); + return -ENOMEM; + } + + return 0; +} + +static void *rsa_wd_sync_run(void *arg) +{ + thread_data *pdata = (thread_data *)arg; + int key_size = pdata->keybits >> 3; + struct wcrypto_rsa_ctx_setup setup; + struct wcrypto_rsa_op_data opdata; + struct wd_queue *queue; + void *key_info = NULL; + void *ctx = NULL; + void *tag = NULL; + void *pool; + u32 count = 0; + int ret; + + memset(&setup, 0, sizeof(setup)); + memset(&opdata, 0, sizeof(opdata)); + pool = g_thread_queue.bd_res[pdata->td_id].pool; + queue = g_thread_queue.bd_res[pdata->td_id].queue; + + setup.br.alloc = (void *)wd_alloc_blk; + setup.br.free = (void *)wd_free_blk; + setup.br.iova_map = (void *)wd_blk_iova_map; + setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + setup.br.get_bufsize = (void *)wd_blksize; + setup.br.usr = pool; + setup.key_bits = pdata->keybits; + setup.is_crt = pdata->kmode; + + ctx = wcrypto_create_rsa_ctx(queue, &setup); + if (!ctx) + return NULL; + + key_info = malloc(key_size * 16); + if (!key_info) { + HPRE_TST_PRT("failed to alloc RSA key info!\n"); + return NULL; + } + memset(key_info, 0, key_size * 16); + + rsa_key_in = malloc(2 * key_size + sizeof(struct hpre_rsa_key_in)); + if (!rsa_key_in) { + HPRE_TST_PRT("failed to alloc RSA key input param!\n"); + goto key_release; + } + rsa_key_in->e = rsa_key_in + 1; + rsa_key_in->p = rsa_key_in->e + key_size; + rsa_key_in->q = rsa_key_in->p + (key_size >> 1); + + ret = get_rsa_key_from_sample(ctx, key_info, key_info, + pdata->keybits, pdata->kmode); + if (ret) { + HPRE_TST_PRT("failed to get sample key data!\n"); + goto sample_release; + } + + opdata.in_bytes = key_size; + opdata.out_bytes = key_size; + opdata.op_type = pdata->optype; + if (opdata.op_type == WCRYPTO_RSA_GENKEY) { + ret = get_hpre_keygen_opdata(ctx, &opdata); + if (ret){ + HPRE_TST_PRT("failed to fill rsa key gen req!\n"); + goto sample_release; + } + } else { + opdata.in = wd_alloc_blk(pool); + if (!opdata.in) { + HPRE_TST_PRT("failed to alloc rsa in buffer!\n"); + goto sample_release; + } + memset(opdata.in, 0, opdata.in_bytes); + memcpy(opdata.in + key_size - sizeof(rsa_m), rsa_m, sizeof(rsa_m)); + + opdata.out = wd_alloc_blk(pool); + if (!opdata.out) { + HPRE_TST_PRT("failed to alloc rsa out buffer!\n"); + goto in_release; + } + } + + do { + ret = wcrypto_do_rsa(ctx, &opdata, tag); + if (ret || opdata.status) { + HPRE_TST_PRT("failed to do rsa task, status: %d\n", opdata.status); + goto out_release; + } + + count++; + if (get_run_state() == 0) + break; + } while(true); + + /* clean output buffer remainings in the last time operation */ + if (opdata.op_type == WCRYPTO_RSA_GENKEY) { + char *data; + int len; + + len = wcrypto_rsa_kg_out_data((void *)opdata.out, &data); + if (len < 0) { + HPRE_TST_PRT("failed to wd rsa get key gen out data!\n"); + goto out_release; + } + memset(data, 0, len); + + wcrypto_del_kg_in(ctx, opdata.in); + opdata.in = NULL; + wcrypto_del_kg_out(ctx, opdata.out); + opdata.out = NULL; + } + +out_release: + if (opdata.out) + wd_free_blk(pool, opdata.out); +in_release: + if (opdata.in) + wd_free_blk(pool, opdata.in); +sample_release: + free(rsa_key_in); +key_release: + free(key_info); + + wcrypto_del_rsa_ctx(ctx); + add_recv_data(count, key_size); + + return NULL; +} + +static void rsa_async_cb(const void *msg, void *tag) +{ + //struct wcrypto_rsa_msg *massage = msg; + //struct rsa_async_tag *ptag = tag; + //u32 op_type = tag->op_type; + //void *ctx = tag->ctx; + + return; +} + +static void *rsa_wd_async_run(void *arg) +{ + thread_data *pdata = (thread_data *)arg; + int key_size = pdata->keybits >> 3; + struct wcrypto_rsa_ctx_setup setup; + struct wcrypto_rsa_op_data opdata; + struct rsa_async_tag *tag = NULL; + struct wd_queue *queue; + void *key_info = NULL; + void *ctx = NULL; + int try_cnt = 0; + void *pool; + u32 count = 0; + int i, ret; + + memset(&setup, 0, sizeof(setup)); + memset(&opdata, 0, sizeof(opdata)); + pool = g_thread_queue.bd_res[pdata->td_id].pool; + queue = g_thread_queue.bd_res[pdata->td_id].queue; + + setup.cb = (void *)rsa_async_cb; + setup.br.alloc = (void *)wd_alloc_blk; + setup.br.free = (void *)wd_free_blk; + setup.br.iova_map = (void *)wd_blk_iova_map; + setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + setup.br.get_bufsize = (void *)wd_blksize; + setup.br.usr = pool; + setup.key_bits = pdata->keybits; + setup.is_crt = pdata->kmode; + + ctx = wcrypto_create_rsa_ctx(queue, &setup); + if (!ctx) + return NULL; + + key_info = malloc(key_size * 16); + if (!key_info) { + HPRE_TST_PRT("failed to alloc RSA key info!\n"); + return NULL; + } + memset(key_info, 0, key_size * 16); + + rsa_key_in = malloc(2 * key_size + sizeof(struct hpre_rsa_key_in)); + if (!rsa_key_in) { + HPRE_TST_PRT("failed to alloc RSA key input param!\n"); + goto key_release; + } + rsa_key_in->e = rsa_key_in + 1; + rsa_key_in->p = rsa_key_in->e + key_size; + rsa_key_in->q = rsa_key_in->p + (key_size >> 1); + + ret = get_rsa_key_from_sample(ctx, key_info, key_info, + pdata->keybits, pdata->kmode); + if (ret) { + HPRE_TST_PRT("failed to get sample key data!\n"); + goto sample_release; + } + + opdata.in_bytes = key_size; + opdata.out_bytes = key_size; + opdata.op_type = pdata->optype; + if (opdata.op_type == WCRYPTO_RSA_GENKEY) { + ret = get_hpre_keygen_opdata(ctx, &opdata); + if (ret){ + HPRE_TST_PRT("failed to fill rsa key gen req!\n"); + goto sample_release; + } + } else { + opdata.in = wd_alloc_blk(pool); + if (!opdata.in) { + HPRE_TST_PRT("failed to alloc rsa in buffer!\n"); + goto sample_release; + } + memset(opdata.in, 0, opdata.in_bytes); + memcpy(opdata.in + key_size - sizeof(rsa_m), rsa_m, sizeof(rsa_m)); + + opdata.out = wd_alloc_blk(pool); + if (!opdata.out) { + HPRE_TST_PRT("failed to alloc rsa out buffer!\n"); + goto in_release; + } + } + + tag = malloc(sizeof(*tag) * MAX_POOL_LENTH); + if (!tag) { + HPRE_TST_PRT("failed to malloc rsa tag!\n"); + goto out_release; + } + + do { + if (get_run_state() == 0) + break; + + try_cnt = 0; + i = count % MAX_POOL_LENTH; + tag[i].ctx = ctx; + tag[i].cnt = i; + tag[i].optype = opdata.op_type; + + ret = wcrypto_do_rsa(ctx, &opdata, &tag[i]); + if (ret == -WD_EBUSY) { + usleep(SEND_USLEEP * try_cnt); + try_cnt++; + if (try_cnt > MAX_TRY_CNT) { + HPRE_TST_PRT("Test RSA send fail %d times!\n", MAX_TRY_CNT); + try_cnt = 0; + } + continue; + } else if (ret) { + HPRE_TST_PRT("failed to do rsa async task!\n"); + goto tag_release; + } + count++; + } while(true); + + /* clean output buffer remainings in the last time operation */ + if (opdata.op_type == WCRYPTO_RSA_GENKEY) { + char *data; + int len; + + len = wcrypto_rsa_kg_out_data((void *)opdata.out, &data); + if (len < 0) { + HPRE_TST_PRT("failed to wd rsa get key gen out data!\n"); + goto out_release; + } + memset(data, 0, len); + + wcrypto_del_kg_in(ctx, opdata.in); + opdata.in = NULL; + wcrypto_del_kg_out(ctx, opdata.out); + opdata.out = NULL; + } + +tag_release: + free(tag); +out_release: + if (opdata.out) + wd_free_blk(pool, opdata.out); +in_release: + if (opdata.in) + wd_free_blk(pool, opdata.in); +sample_release: + free(rsa_key_in); +key_release: + free(key_info); + + while (1) { + if (get_recv_time() > 0) // wait Async mode finish recv + break; + usleep(SEND_USLEEP); + } + wcrypto_del_rsa_ctx(ctx); + + add_send_complete(); + + return NULL; +} + +static int get_dh_param_from_sample(struct hpre_dh_param *setup, + u32 key_bits, u8 is_g2) +{ + setup->key_bits = key_bits; + + switch (key_bits) { + case 768: + setup->x = dh_xa_768; + setup->p = dh_p_768; + setup->except_pub_key = dh_except_b_pubkey_768; + setup->pub_key = dh_except_a_pubkey_768; + setup->share_key = dh_share_key_768; + setup->x_size = sizeof(dh_xa_768); + setup->p_size = sizeof(dh_p_768); + setup->except_pub_key_size = sizeof(dh_except_b_pubkey_768); + setup->pub_key_size = sizeof(dh_except_a_pubkey_768); + setup->share_key_size = sizeof(dh_share_key_768); + break; + case 1024: + setup->x = dh_xa_1024; + setup->p = dh_p_1024; + setup->except_pub_key = dh_except_b_pubkey_1024; + setup->pub_key = dh_except_a_pubkey_1024; + setup->share_key = dh_share_key_1024; + setup->x_size = sizeof(dh_xa_1024); + setup->p_size = sizeof(dh_p_1024); + setup->except_pub_key_size = sizeof(dh_except_b_pubkey_1024); + setup->pub_key_size = sizeof(dh_except_a_pubkey_1024); + setup->share_key_size = sizeof(dh_share_key_1024); + break; + case 1536: + setup->x = dh_xa_1536; + setup->p = dh_p_1536; + setup->except_pub_key = dh_except_b_pubkey_1536; + setup->pub_key = dh_except_a_pubkey_1536; + setup->share_key = dh_share_key_1536; + setup->x_size = sizeof(dh_xa_1536); + setup->p_size = sizeof(dh_p_1536); + setup->except_pub_key_size = sizeof(dh_except_b_pubkey_1536); + setup->pub_key_size = sizeof(dh_except_a_pubkey_1536); + setup->share_key_size = sizeof(dh_share_key_1536); + break; + case 2048: + setup->x = dh_xa_2048; + setup->p = dh_p_2048; + setup->except_pub_key = dh_except_b_pubkey_2048; + setup->pub_key = dh_except_a_pubkey_2048; + setup->share_key = dh_share_key_2048; + setup->x_size = sizeof(dh_xa_2048); + setup->p_size = sizeof(dh_p_2048); + setup->except_pub_key_size = sizeof(dh_except_b_pubkey_2048); + setup->pub_key_size = sizeof(dh_except_a_pubkey_2048); + setup->share_key_size = sizeof(dh_share_key_2048); + break; + case 3072: + setup->x = dh_xa_3072; + setup->p = dh_p_3072; + setup->except_pub_key = dh_except_b_pubkey_3072; + setup->pub_key = dh_except_a_pubkey_3072; + setup->share_key = dh_share_key_3072; + setup->x_size = sizeof(dh_xa_3072); + setup->p_size = sizeof(dh_p_3072); + setup->except_pub_key_size = sizeof(dh_except_b_pubkey_3072); + setup->pub_key_size = sizeof(dh_except_a_pubkey_3072); + setup->share_key_size = sizeof(dh_share_key_3072); + break; + case 4096: + setup->x = dh_xa_4096; + setup->p = dh_p_4096; + setup->except_pub_key = dh_except_b_pubkey_4096; + setup->pub_key = dh_except_a_pubkey_4096; + setup->share_key = dh_share_key_4096; + setup->x_size = sizeof(dh_xa_4096); + setup->p_size = sizeof(dh_p_4096); + setup->except_pub_key_size = sizeof(dh_except_b_pubkey_4096); + setup->pub_key_size = sizeof(dh_except_a_pubkey_4096); + setup->share_key_size = sizeof(dh_share_key_4096); + break; + default: + HPRE_TST_PRT("failed to find dh keybits %u\n", key_bits); + return -EINVAL; + } + + if (is_g2) { + setup->g = dh_g_2; + } else { + setup->g = dh_g_5; + } + setup->g_size = 1; + + return 0; +} + +static int get_dh_opdata_param(void *ctx, struct wcrypto_dh_op_data *opdata, + struct hpre_dh_param *setup, int key_size) +{ + unsigned char *ag_bin = NULL; + void *pool = setup->pool; + struct wd_dtb ctx_g; + int ret; + + ag_bin = wd_alloc_blk(pool); + if (!ag_bin) + return -ENOMEM; + + memset(ag_bin, 0, 2 * key_size); + opdata->pv = ag_bin; + + opdata->x_p = wd_alloc_blk(pool); + if (!opdata->x_p) + goto ag_error; + + memset(opdata->x_p, 0, 2 * key_size); + + opdata->pri = wd_alloc_blk(pool); + if (!opdata->pri) + goto xp_error; + + memset(opdata->pri, 0, 2 * key_size); + opdata->pri_bytes = 2 * key_size; + + ctx_g.data = malloc(key_size); + if (!ctx_g.data) + goto ctx_release; + + if (setup->optype == WCRYPTO_DH_PHASE1) { // GEN1 + memcpy(opdata->x_p, setup->x, setup->x_size); + memcpy(opdata->x_p + key_size, setup->p, setup->p_size); + memcpy(ctx_g.data, setup->g, setup->g_size); + opdata->pbytes = setup->p_size; + opdata->xbytes = setup->x_size; + ctx_g.dsize = setup->g_size; + ctx_g.bsize = key_size; + + ret = wcrypto_set_dh_g(ctx, &ctx_g); + if (ret) + HPRE_TST_PRT("wd_dh_set_g run failed\n"); + } else { // GEN1 + memcpy(opdata->x_p, setup->x, setup->x_size); + memcpy(opdata->x_p + key_size, setup->p, setup->p_size); + memcpy(opdata->pv, setup->except_pub_key, setup->except_pub_key_size); + opdata->pbytes = setup->p_size; + opdata->xbytes = setup->x_size; + opdata->pvbytes = setup->except_pub_key_size; + } + + free(ctx_g.data); + + return 0; + +ctx_release: + wd_free_blk(pool, opdata->pri); +xp_error: + wd_free_blk(pool, opdata->x_p); +ag_error: + wd_free_blk(pool, opdata->pv); + + return -ENOMEM; +} + +static void *dh_wd_sync_run(void *arg) +{ + thread_data *pdata = (thread_data *)arg; + int key_size = pdata->keybits >> 3; + struct wcrypto_dh_ctx_setup dh_setup; + struct wcrypto_dh_op_data opdata; + struct hpre_dh_param setup; + struct wd_queue *queue; + void *ctx = NULL; + void *tag = NULL; + void *pool; + u32 count = 0; + int ret; + + memset(&dh_setup, 0, sizeof(dh_setup)); + memset(&opdata, 0, sizeof(opdata)); + + pool = g_thread_queue.bd_res[pdata->td_id].pool; + queue = g_thread_queue.bd_res[pdata->td_id].queue; + dh_setup.key_bits = pdata->keybits; + dh_setup.br.alloc = (void *)wd_alloc_blk; + dh_setup.br.free = (void *)wd_free_blk; + dh_setup.br.iova_map = (void *)wd_blk_iova_map; + dh_setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + dh_setup.br.get_bufsize = (void *)wd_blksize; + dh_setup.br.usr = pool; + if (pdata->optype == WCRYPTO_DH_PHASE2) + dh_setup.is_g2 = true; // G1 is 0; G2 is 1; + + ctx = wcrypto_create_dh_ctx(queue, &dh_setup); + if (!ctx) + return NULL; + + ret = get_dh_param_from_sample(&setup, pdata->keybits, pdata->kmode); + if (ret) + goto ctx_release; + + setup.optype = pdata->optype; + setup.pool = pool; + opdata.op_type = pdata->optype; + ret = get_dh_opdata_param(ctx, &opdata, &setup, key_size); + if (ret){ + HPRE_TST_PRT("failed to fill dh key gen req!\n"); + goto param_release; + } + + do { + ret = wcrypto_do_dh(ctx, &opdata, tag); + if (ret || opdata.status) { + HPRE_TST_PRT("failed to do dh task, status: %d\n", opdata.status); + goto param_release; + } + + count++; + if (get_run_state() == 0) + break; + } while(true); + +param_release: + wd_free_blk(pool, opdata.x_p); + wd_free_blk(pool, opdata.pv); + wd_free_blk(pool, opdata.pri); +ctx_release: + wcrypto_del_dh_ctx(ctx); + add_recv_data(count, key_size); + + return NULL; +} + +static void dh_async_cb(const void *msg, void *tag) +{ + //struct wcrypto_dh_msg *massage = msg; + //struct rsa_async_tag *ptag = tag; + //u32 op_type = tag->op_type; + //void *ctx = tag->ctx; + + return; +} + +static void *dh_wd_async_run(void *arg) +{ + thread_data *pdata = (thread_data *)arg; + int key_size = pdata->keybits >> 3; + struct wcrypto_dh_ctx_setup dh_setup; + struct wcrypto_dh_op_data opdata; + struct rsa_async_tag *tag = NULL; + struct hpre_dh_param setup; + struct wd_queue *queue; + void *ctx = NULL; + int try_cnt = 0; + void *pool; + u32 count = 0; + int i, ret; + + memset(&dh_setup, 0, sizeof(dh_setup)); + memset(&opdata, 0, sizeof(opdata)); + + pool = g_thread_queue.bd_res[pdata->td_id].pool; + queue = g_thread_queue.bd_res[pdata->td_id].queue; + dh_setup.key_bits = pdata->keybits; + dh_setup.br.alloc = (void *)wd_alloc_blk; + dh_setup.br.free = (void *)wd_free_blk; + dh_setup.br.iova_map = (void *)wd_blk_iova_map; + dh_setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + dh_setup.br.get_bufsize = (void *)wd_blksize; + dh_setup.cb = (void *)dh_async_cb; + dh_setup.br.usr = pool; + if (pdata->optype == WCRYPTO_DH_PHASE2) + dh_setup.is_g2 = true; // G1 is 0; G2 is 1; + + ctx = wcrypto_create_dh_ctx(queue, &dh_setup); + if (!ctx) + return NULL; + + ret = get_dh_param_from_sample(&setup, pdata->keybits, pdata->kmode); + if (ret) + goto ctx_release; + + setup.optype = pdata->optype; + setup.pool = pool; + opdata.op_type = pdata->optype; + ret = get_dh_opdata_param(ctx, &opdata, &setup, key_size); + if (ret){ + HPRE_TST_PRT("failed to fill dh key gen req!\n"); + goto param_release; + } + + tag = malloc(sizeof(*tag) * MAX_POOL_LENTH); + if (!tag) { + HPRE_TST_PRT("failed to malloc dh tag!\n"); + goto param_release; + } + + do { + if (get_run_state() == 0) + break; + + try_cnt = 0; + i = count % MAX_POOL_LENTH; + tag[i].ctx = ctx; + tag[i].cnt = i; + tag[i].optype = opdata.op_type; + + ret = wcrypto_do_dh(ctx, &opdata, &tag[i]); + if (ret == -WD_EBUSY) { + usleep(SEND_USLEEP * try_cnt); + try_cnt++; + if (try_cnt > MAX_TRY_CNT) { + HPRE_TST_PRT("Test DH send fail %d times!\n", MAX_TRY_CNT); + try_cnt = 0; + } + continue; + } else if (ret) { + HPRE_TST_PRT("failed to do rsa async task!\n"); + goto tag_release; + } + + count++; + } while(true); + +tag_release: + free(tag); +param_release: + wd_free_blk(pool, opdata.x_p); + wd_free_blk(pool, opdata.pv); + wd_free_blk(pool, opdata.pri); +ctx_release: + while (1) { + if (get_recv_time() > 0) // wait Async mode finish recv + break; + usleep(SEND_USLEEP); + } + + wcrypto_del_dh_ctx(ctx); + add_send_complete(); + + return NULL; +} + +static int get_ecc_curve(struct hpre_ecc_setup *setup, u32 cid) +{ + switch (cid) { + case 0: // secp128R1 + setup->nid = 706; + setup->curve_id = WCRYPTO_SECP128R1; + break; + case 1: // secp192K1 + setup->nid = 711; + setup->curve_id = WCRYPTO_SECP192K1; + break; + case 2: // secp256K1 + setup->nid = 714; + setup->curve_id = WCRYPTO_SECP256K1; + break; + case 3: // brainpoolP320R1 + setup->nid = 929; + setup->curve_id = WCRYPTO_BRAINPOOLP320R1; + break; + case 4: // brainpoolP384R1 + setup->nid = 931; + setup->curve_id = WCRYPTO_BRAINPOOLP384R1; + break; + case 5: // secp521R1 + setup->nid = 716; + setup->curve_id = WCRYPTO_SECP521R1; + break; + default: + HPRE_TST_PRT("failed to get ecc curve id!\n"); + return -EINVAL; + } + + return 0; +} + +static int get_ecc_key_param(struct wcrypto_ecc_curve *param, u32 key_bits) +{ + u32 key_size = (key_bits + 7) / 8; + + switch (key_bits) { + case 128: + param->a.data = ecdh_a_secp128r1; + param->b.data = ecdh_b_secp128r1; + param->p.data = ecdh_p_secp128r1; + param->n.data = ecdh_n_secp128r1; + param->g.x.data = ecdh_g_secp128r1; + param->g.y.data = ecdh_g_secp128r1 + key_size; + case 192: + param->a.data = ecdh_a_secp192k1; + param->b.data = ecdh_b_secp192k1; + param->p.data = ecdh_p_secp192k1; + param->n.data = ecdh_n_secp192k1; + param->g.x.data = ecdh_g_secp192k1; + param->g.y.data = ecdh_g_secp192k1 + key_size; + case 224: + param->a.data = ecdh_a_secp224r1; + param->b.data = ecdh_b_secp224r1; + param->p.data = ecdh_p_secp224r1; + param->n.data = ecdh_n_secp224r1; + param->g.x.data = ecdh_g_secp224r1; + param->g.y.data = ecdh_g_secp224r1 + key_size; + case 256: + param->a.data = ecdh_a_secp256k1; + param->b.data = ecdh_b_secp256k1; + param->p.data = ecdh_p_secp256k1; + param->n.data = ecdh_n_secp256k1; + param->g.x.data = ecdh_g_secp256k1; + param->g.y.data = ecdh_g_secp256k1 + key_size; + case 320: + param->a.data = ecdh_a_secp320k1; + param->b.data = ecdh_b_secp320k1; + param->p.data = ecdh_p_secp320k1; + param->n.data = ecdh_n_secp320k1; + param->g.x.data = ecdh_g_secp320k1; + param->g.y.data = ecdh_g_secp320k1 + key_size; + case 384: + param->a.data = ecdh_a_secp384r1; + param->b.data = ecdh_b_secp384r1; + param->p.data = ecdh_p_secp384r1; + param->n.data = ecdh_n_secp384r1; + param->g.x.data = ecdh_g_secp384r1; + param->g.y.data = ecdh_g_secp384r1 + key_size; + case 521: + param->a.data = ecdh_a_secp521r1; + param->b.data = ecdh_b_secp521r1; + param->p.data = ecdh_p_secp521r1; + param->n.data = ecdh_n_secp521r1; + param->g.x.data = ecdh_g_secp521r1; + param->g.y.data = ecdh_g_secp521r1 + key_size; + default: + HPRE_TST_PRT("key_bits %d not find\n", key_bits); + return -EINVAL; + } + + param->a.bsize = key_size; + param->a.dsize = key_size; + param->b.bsize = key_size; + param->b.dsize = key_size; + param->p.bsize = key_size; + param->p.dsize = key_size; + param->n.bsize = key_size; + param->n.dsize = key_size; + param->g.x.bsize = key_size; + param->g.x.dsize = key_size; + param->g.y.bsize = key_size; + param->g.y.dsize = key_size; + + return 0; +} + +static int ecc_get_rand(char *out, size_t out_len, void *usr) +{ + //int ret; + + get_rand_data((u8 *)out, out_len); + //ret = RAND_priv_bytes((void *)out, out_len); + //if (ret != 1) { + // HPRE_TST_PRT("failed to get ecc rand data:%d\n", ret); + // return -EINVAL; + //} + + return 0; +} + +static int ecc_compute_hash(const char *in, size_t in_len, + char *out, size_t out_len, void *usr) +{ + /* perf test for none hash check */ + return 0; +} + +static int get_ecc_param_from_sample(struct hpre_ecc_setup *setup, + u32 subtype, u32 key_bits) +{ + int key_size = (key_bits + 7) / 8; + u32 len; + + setup->key_bits = key_bits; + + if (setup->nid == 714 || key_bits == 256) { // NID_secp256k1 + /* sm2 */ + if (subtype == SM2_TYPE) { + setup->priv_key = sm2_priv; + setup->priv_key_size = sizeof(sm2_priv); + setup->pub_key = sm2_pubkey; + setup->pub_key_size = sizeof(sm2_pubkey); + + len = SM2_DG_SZ; + setup->msg = malloc(len); + if (!setup->msg) + return -1; + memset(setup->msg, 0xFF, len); + + if (true) { // for msg_sigest mode + memcpy(setup->msg, sm2_digest, sizeof(sm2_digest)); + setup->msg_size = sizeof(sm2_digest); + } else { + memcpy(setup->msg, sm2_plaintext, sizeof(sm2_plaintext)); + setup->msg_size = sizeof(sm2_plaintext); + } + + if (setup->msg_size > 512) { + setup->ciphertext = sm2_ciphertext_l; + setup->ciphertext_size = sizeof(sm2_ciphertext_l); + setup->plaintext = sm2_plaintext_l; + setup->plaintext_size = sizeof(sm2_plaintext_l); + } else { + setup->ciphertext = sm2_ciphertext; + setup->ciphertext_size = sizeof(sm2_ciphertext); + setup->plaintext = sm2_plaintext; + setup->plaintext_size = sizeof(sm2_plaintext); + } + + setup->k = sm2_k; + setup->k_size = sizeof(sm2_k); + setup->userid = sm2_id; + setup->userid_size = sizeof(sm2_id); + setup->sign = sm2_sign_data; + setup->sign_size = sizeof(sm2_sign_data); + + } else { + setup->priv_key = ecdh_da_secp256k1; + setup->except_pub_key = ecdh_except_b_pubkey_secp256k1; + setup->pub_key = ecdh_cp_pubkey_secp256k1; + setup->share_key = ecdh_cp_sharekey_secp256k1; + setup->priv_key_size = sizeof(ecdh_da_secp256k1); + setup->except_pub_key_size = sizeof(ecdh_except_b_pubkey_secp256k1); + setup->pub_key_size = sizeof(ecdh_cp_pubkey_secp256k1); + setup->share_key_size = sizeof(ecdh_cp_sharekey_secp256k1); + + /* ecc sign */ + setup->msg = ecc_except_e_secp256k1; + setup->msg_size = sizeof(ecc_except_e_secp256k1); + setup->k = ecc_except_kinv_secp256k1; + setup->k_size = sizeof(ecc_except_kinv_secp256k1); + setup->rp = ecdh_cp_pubkey_secp256k1 + 1; + setup->rp_size = key_size; + + /* ecc verf */ + setup->sign = ecc_cp_sign_secp256k1; + setup->sign_size = sizeof(ecc_cp_sign_secp256k1); + } + } else if (setup->nid == 706 || key_bits == 128) { + setup->priv_key = ecdh_da_secp128r1; + setup->except_pub_key = ecdh_except_b_pubkey_secp128r1; + setup->pub_key = ecdh_cp_pubkey_secp128r1; + setup->share_key = ecdh_cp_sharekey_secp128r1; + setup->priv_key_size = sizeof(ecdh_da_secp128r1); + setup->except_pub_key_size = sizeof(ecdh_except_b_pubkey_secp128r1); + setup->pub_key_size = sizeof(ecdh_cp_pubkey_secp128r1); + setup->share_key_size = sizeof(ecdh_cp_sharekey_secp128r1); + + /* ecc sign */ + setup->msg = ecc_except_e_secp128r1; + setup->msg_size = sizeof(ecc_except_e_secp128r1); + setup->k = ecc_except_kinv_secp128r1; + setup->k_size = sizeof(ecc_except_kinv_secp128r1); + setup->rp = ecdh_cp_pubkey_secp128r1 + 1; + setup->rp_size = key_size; + + /* ecc verf */ + setup->sign = ecc_cp_sign_secp128r1; + setup->sign_size = sizeof(ecc_cp_sign_secp128r1); + + } else if (setup->nid == 711 || key_bits == 192) { + setup->priv_key = ecdh_da_secp192k1; + setup->except_pub_key = ecdh_except_b_pubkey_secp192k1; + setup->pub_key = ecdh_cp_pubkey_secp192k1; + setup->share_key = ecdh_cp_sharekey_secp192k1; + setup->priv_key_size = sizeof(ecdh_da_secp192k1); + setup->except_pub_key_size = sizeof(ecdh_except_b_pubkey_secp192k1); + setup->pub_key_size = sizeof(ecdh_cp_pubkey_secp192k1); + setup->share_key_size = sizeof(ecdh_cp_sharekey_secp192k1); + + /* ecc sign */ + setup->msg = ecc_except_e_secp192k1; + setup->msg_size = sizeof(ecc_except_e_secp192k1); + setup->k = ecc_except_kinv_secp192k1; + setup->k_size = sizeof(ecc_except_kinv_secp192k1); + setup->rp = ecdh_cp_pubkey_secp192k1 + 1; + setup->rp_size = key_size; + + /* ecc verf */ + setup->sign = ecc_cp_sign_secp256k1; + setup->sign_size = sizeof(ecc_cp_sign_secp256k1); + } else if (setup->nid == 712 || key_bits == 224) { + setup->priv_key = ecdh_da_secp224r1; + setup->except_pub_key = ecdh_except_b_pubkey_secp224r1; + setup->pub_key = ecdh_cp_pubkey_secp224r1; + setup->share_key = ecdh_cp_sharekey_secp224r1; + setup->priv_key_size = sizeof(ecdh_da_secp224r1); + setup->except_pub_key_size = sizeof(ecdh_except_b_pubkey_secp224r1); + setup->pub_key_size = sizeof(ecdh_cp_pubkey_secp224r1); + setup->share_key_size = sizeof(ecdh_cp_sharekey_secp224r1); + } else if (setup->nid == 929 || key_bits == 320) { + setup->priv_key = ecdh_da_secp320k1; + setup->except_pub_key = ecdh_except_b_pubkey_secp320k1; + setup->pub_key = ecdh_cp_pubkey_secp320k1; + setup->share_key = ecdh_cp_sharekey_secp320k1; + setup->priv_key_size = sizeof(ecdh_da_secp320k1); + setup->except_pub_key_size = sizeof(ecdh_except_b_pubkey_secp320k1); + setup->pub_key_size = sizeof(ecdh_cp_pubkey_secp320k1); + setup->share_key_size = sizeof(ecdh_cp_sharekey_secp320k1); + + /* ecc sign */ + setup->msg = ecc_except_e_secp320k1; + setup->msg_size = sizeof(ecc_except_e_secp320k1); + setup->k = ecc_except_kinv_secp320k1; + setup->k_size = sizeof(ecc_except_kinv_secp320k1); + setup->rp = ecdh_cp_pubkey_secp192k1 + 1; + setup->rp_size = key_size; + + /* ecc verf */ + setup->sign = ecc_cp_sign_secp256k1; + setup->sign_size = sizeof(ecc_cp_sign_secp256k1); + + } else if (setup->nid == 931 || key_bits == 384) { + setup->priv_key = ecdh_da_secp384r1; + setup->except_pub_key = ecdh_except_b_pubkey_secp384r1; + setup->pub_key = ecdh_cp_pubkey_secp384r1; + setup->share_key = ecdh_cp_sharekey_secp384r1; + setup->priv_key_size = sizeof(ecdh_da_secp384r1); + setup->except_pub_key_size = sizeof(ecdh_except_b_pubkey_secp384r1); + setup->pub_key_size = sizeof(ecdh_cp_pubkey_secp384r1); + setup->share_key_size = sizeof(ecdh_cp_sharekey_secp384r1); + + /* ecc sign */ + setup->msg = ecc_except_e_secp384r1; + setup->msg_size = sizeof(ecc_except_e_secp384r1); + setup->k = ecc_except_kinv_secp384r1; + setup->k_size = sizeof(ecc_except_kinv_secp384r1); + setup->rp = ecdh_cp_pubkey_secp384r1 + 1; + setup->rp_size = key_size; + + /* ecc verf */ + setup->sign = ecc_cp_sign_secp256k1; + setup->sign_size = sizeof(ecc_cp_sign_secp256k1); + } else if (setup->nid == 716 || key_bits == 521) { + setup->priv_key = ecdh_da_secp521r1; + setup->except_pub_key = ecdh_except_b_pubkey_secp521r1; + setup->pub_key = ecdh_cp_pubkey_secp521r1; + setup->share_key = ecdh_cp_sharekey_secp521r1; + setup->priv_key_size = sizeof(ecdh_da_secp521r1); + setup->except_pub_key_size = sizeof(ecdh_except_b_pubkey_secp521r1); + setup->pub_key_size = sizeof(ecdh_cp_pubkey_secp521r1); + setup->share_key_size = sizeof(ecdh_cp_sharekey_secp521r1); + + /* ecc sign */ + setup->msg = ecc_except_e_secp521r1; + setup->msg_size = sizeof(ecc_except_e_secp521r1); + setup->k = ecc_except_kinv_secp521r1; + setup->k_size = sizeof(ecc_except_kinv_secp521r1); + setup->rp = ecdh_cp_pubkey_secp521r1 + 1; + setup->rp_size = key_size; + + /* ecc verf */ + setup->sign = ecc_cp_sign_secp256k1; + setup->sign_size = sizeof(ecc_cp_sign_secp256k1); + + } else { + HPRE_TST_PRT("init test sess setup not find this bits %d or nid %d\n", + key_bits, setup->nid); + return -EINVAL; + } + + return 0; +} + +static int ecdsa_param_fill(void *ctx, struct wcrypto_ecc_op_data *opdata, + struct wcrypto_ecc_key *ecc_key, struct hpre_ecc_setup *setup, + thread_data *pdata) +{ + int key_insize = (pdata->keybits + 7) / 8; + u32 optype = pdata->optype; + struct wcrypto_ecc_out *ecc_out = NULL; + struct wcrypto_ecc_in *ecc_in = NULL; + struct wcrypto_ecc_point pub; + struct wd_dtb d, e, k; + int ret = 0; + + if (optype == WCRYPTO_ECDSA_SIGN) {// Sign + ecc_out = wcrypto_new_ecdsa_sign_out(ctx); + if (!ecc_out) { + HPRE_TST_PRT("failed to get ecdsa out!\n"); + return -ENOMEM; + } + + d.data = (void *)setup->priv_key; + d.dsize = setup->priv_key_size; + d.bsize = setup->priv_key_size; + ret = wcrypto_set_ecc_prikey(ecc_key, &d); + if (ret) { + HPRE_TST_PRT("failed to set ecdsa prikey!\n"); + goto del_ecc_out; + } + + pub.x.data = (void *)setup->pub_key + 1; + pub.x.dsize = key_insize; + pub.x.bsize = key_insize; + pub.y.data = pub.x.data + key_insize; + pub.y.dsize = key_insize; + pub.y.bsize = key_insize; + ret = wcrypto_set_ecc_pubkey(ecc_key, &pub); + if (ret) { + HPRE_TST_PRT("failed to set ecdsa pubkey!\n"); + goto del_ecc_out; + } + + e.data = (void *)setup->msg; + e.dsize = setup->msg_size; + e.bsize = key_insize; + + k.data = (void *)setup->k; + k.dsize = setup->k_size; + k.bsize = key_insize; + ecc_in = wcrypto_new_ecdsa_sign_in(ctx, &e, &k); + if (!ecc_in) { + HPRE_TST_PRT("failed to get ecdsa sign in!\n"); + ret = -ENOMEM; + goto del_ecc_out; + } + + opdata->in = ecc_in; + opdata->out = ecc_out; + } else { // Verf + pub.x.data = (void *)setup->pub_key + 1; + pub.x.dsize = key_insize; + pub.x.bsize = key_insize; + pub.y.data = pub.x.data + key_insize; + pub.y.dsize = key_insize; + pub.y.bsize = key_insize; + ret = wcrypto_set_ecc_pubkey(ecc_key, &pub); + if (ret) { + HPRE_TST_PRT("failed to set ecdsa pubkey!\n"); + return -ENOMEM; + } + + e.data = (void *)setup->msg; + e.dsize = setup->msg_size; + e.bsize = key_insize; + + d.data = (void *)setup->sign; + d.dsize = key_insize; + d.bsize = key_insize; + k.data = d.data + key_insize; + k.dsize = key_insize; + k.bsize = key_insize; + ecc_in = wcrypto_new_ecdsa_verf_in(ctx, &e, &d, &k); + if (!ecc_in) { + HPRE_TST_PRT("failed to get ecdsa verf ecc in!\n"); + return -ENOMEM; + } + + opdata->in = ecc_in; + } + + return 0; +del_ecc_out: + if (ecc_out) + (void)wcrypto_del_ecc_out(ctx, ecc_out); + return ret; +} + +static int sm2_param_fill(void *ctx, struct wcrypto_ecc_op_data *opdata, + struct hpre_ecc_setup *setup, thread_data *pdata) +{ + int key_insize = (pdata->keybits + 7) / 8; + u32 optype = pdata->optype; + struct wcrypto_ecc_out *ecc_out = NULL; + struct wcrypto_ecc_in *ecc_in = NULL; + struct wcrypto_ecc_point tmp; + struct wd_dtb d, e, k; + + switch (optype) { + case WCRYPTO_SM2_SIGN:// Sign + ecc_out = wcrypto_new_sm2_sign_out(ctx); + if (!ecc_out) { + HPRE_TST_PRT("failed to alloc sm2 ecc out!\n"); + return -ENOMEM; + } + + e.data = (void *)setup->msg; + e.dsize = setup->msg_size; + e.bsize = setup->msg_size; + k.data = (void *)setup->k; + k.dsize = setup->k_size; + k.bsize = key_insize; + ecc_in = wcrypto_new_sm2_sign_in(ctx, &e, &k, NULL, 1); + if (!ecc_in) { + HPRE_TST_PRT("failed to alloc sm2 ecc in!\n"); + goto del_ecc_out; + } + opdata->in = ecc_in; + opdata->out = ecc_out; + break; + case WCRYPTO_SM2_VERIFY: // Verf + ecc_out = wcrypto_new_sm2_sign_out(ctx); + if (!ecc_out) { + HPRE_TST_PRT("failed to alloc sm2 ecc out!\n"); + return -ENOMEM; + } + + e.data = (void *)setup->msg; + e.dsize = setup->msg_size; + e.bsize = key_insize; + d.data = (void *)setup->sign; + d.dsize = key_insize; + d.bsize = key_insize; + k.data = d.data + key_insize; + k.dsize = key_insize; + k.bsize = key_insize; + ecc_in = wcrypto_new_sm2_verf_in(ctx, &e, &d, &k, NULL, 1); + if (!ecc_in) { + HPRE_TST_PRT("failed to alloc sm2 ecc in!\n"); + goto del_ecc_out; + } + + opdata->in = ecc_in; + opdata->out = ecc_out; + break; + case WCRYPTO_SM2_ENCRYPT: // Enc + ecc_out = wcrypto_new_sm2_enc_out(ctx, setup->msg_size); + if (!ecc_out) { + HPRE_TST_PRT("failed to alloc sm2 ecc out!\n"); + return -ENOMEM; + } + + e.data = (void *)setup->plaintext; + e.dsize = setup->plaintext_size; + e.bsize = setup->plaintext_size; + k.data = (void *)setup->k; + k.dsize = setup->k_size; + k.bsize = key_insize; + ecc_in = wcrypto_new_sm2_enc_in(ctx, &e, &k); + if (!ecc_in) { + HPRE_TST_PRT("failed to alloc sm2 ecc in!\n"); + goto del_ecc_out; + } + opdata->in = ecc_in; + opdata->out = ecc_out; + break; + case WCRYPTO_SM2_DECRYPT: // Dec + tmp.x.data = (void *)setup->ciphertext; + tmp.x.dsize = 32; + tmp.y.data = tmp.x.data + 32; + tmp.y.dsize = 32; + e.data = tmp.y.data + 32; + e.dsize = 32; + d.data = e.data + 32; + d.dsize = setup->ciphertext_size - 32 * 3; + ecc_in = wcrypto_new_sm2_dec_in(ctx, &tmp, &d, &e); + if (!ecc_in) { + HPRE_TST_PRT("failed to alloc sm2 ecc in!\n"); + return -ENOMEM; + } + + ecc_out = wcrypto_new_sm2_dec_out(ctx, d.dsize); + if (!ecc_out) { + HPRE_TST_PRT("failed to alloc sm2 ecc out!\n"); + goto del_ecc_in; + } + + opdata->in = ecc_in; + opdata->out = ecc_out; + break; + case WCRYPTO_SM2_KG: // KG + ecc_out = wcrypto_new_sm2_kg_out(ctx); + if (!ecc_out) { + HPRE_TST_PRT("failed to alloc sm2 ecc out!\n"); + return -ENOMEM; + } + + opdata->out = ecc_out; + break; + default: + HPRE_TST_PRT("failed to match sm2 optype!\n"); + return -ENOMEM; + } + + return 0; + +del_ecc_in: + if (ecc_in) + (void)wcrypto_del_ecc_in(ctx, ecc_in); +del_ecc_out: + if (ecc_out) + (void)wcrypto_del_ecc_out(ctx, ecc_out); + + return -ENOMEM; +} + +static int ecc_param_fill(void *ctx, struct wcrypto_ecc_op_data *opdata, + struct wcrypto_ecc_key *ecc_key, struct hpre_ecc_setup *setup, + thread_data *pdata) +{ + int key_insize = (pdata->keybits + 7) / 8; + u32 subtype = pdata->subtype; + u32 optype = pdata->optype; + struct wcrypto_ecc_out *ecc_out = NULL; + struct wcrypto_ecc_in *ecc_in = NULL; + struct wcrypto_ecc_point tmp; + struct wd_dtb d; + int ret = 0; + + ecc_out = wcrypto_new_ecxdh_out(ctx); + if (!ecc_out) { + HPRE_TST_PRT("failed to alloc ecxdh out!\n"); + return -ENOMEM; + } + if (optype == WCRYPTO_ECXDH_GEN_KEY) { // gen + d.data = (void *)setup->priv_key; + d.dsize = setup->priv_key_size; + d.bsize = setup->priv_key_size; + ret = wcrypto_set_ecc_prikey(ecc_key, &d); + if (ret) { + HPRE_TST_PRT("failed to set ecc prikey!\n"); + goto del_ecc_out; + } + + opdata->out = ecc_out; + } else { // compute + if (subtype == ECDH_TYPE) + tmp.x.data = setup->except_pub_key; + else + tmp.x.data = setup->except_pub_key + 1; + tmp.x.bsize = key_insize; + tmp.x.dsize = key_insize; + tmp.y.data = tmp.x.data + key_insize; + tmp.y.bsize = key_insize; + tmp.y.dsize = key_insize; + ecc_in = wcrypto_new_ecxdh_in(ctx, &tmp); + if (!ecc_in) { + HPRE_TST_PRT("failed to get ecxdh sign in!\n"); + goto del_ecc_out; + } + + d.data = (void *)setup->priv_key; + d.dsize = setup->priv_key_size; + d.bsize = setup->priv_key_size; + ret = wcrypto_set_ecc_prikey(ecc_key, &d); + if (ret) { + HPRE_TST_PRT("failed to set ecc prikey!\n"); + goto del_ecc_out; + } + + opdata->in = ecc_in; + opdata->out = ecc_out; + } + + return 0; + +del_ecc_out: + if (ecc_out) + (void)wcrypto_del_ecc_out(ctx, ecc_out); + + return ret; +} + +static void *ecc_wd_sync_run(void *arg) +{ + typedef int (*wd_do)(void *ctx, struct wcrypto_ecc_op_data *opdata, + void *tag); + wd_do wcrypto_do_ecc = NULL; + thread_data *pdata = (thread_data *)arg; + int key_size = pdata->keybits >> 3; + u32 subtype = pdata->subtype; + struct wcrypto_ecc_ctx_setup ctx_setup; + struct wcrypto_ecc_op_data opdata; + struct wcrypto_ecc_curve param; + struct hpre_ecc_setup setup; + struct wcrypto_ecc_key *ecc_key; + struct wcrypto_ecc_point pbk; + struct wd_queue *queue; + struct wd_dtb prk; + void *ctx = NULL; + void *tag = NULL; + void *pool; + u32 cid = ECC_CURVE_ID; + u32 count = 0; + int ret; + + memset(&ctx_setup, 0, sizeof(ctx_setup)); + memset(¶m, 0, sizeof(param)); + memset(&opdata, 0, sizeof(opdata)); + + pool = g_thread_queue.bd_res[pdata->td_id].pool; + queue = g_thread_queue.bd_res[pdata->td_id].queue; + + memset(&setup, 0, sizeof(setup)); + if (subtype != X448_TYPE || subtype != X25519_TYPE) { + ret = get_ecc_curve(&setup, cid); + if (ret) + return NULL; + } + + ctx_setup.br.alloc = (void *)wd_alloc_blk; + ctx_setup.br.free = (void *)wd_free_blk; + ctx_setup.br.iova_map = (void *)wd_blk_iova_map; + ctx_setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + ctx_setup.br.get_bufsize = (void *)wd_blksize; + ctx_setup.br.usr = pool; + + ctx_setup.key_bits = pdata->keybits; + if (subtype == ECDH_TYPE || subtype == ECDSA_TYPE) { + if (cid > ECC_CURVE_ID) { + ctx_setup.cv.type = WCRYPTO_CV_CFG_PARAM; + get_ecc_key_param(¶m, pdata->keybits); + ctx_setup.cv.cfg.pparam = ¶m; + } else { + ctx_setup.cv.type = WCRYPTO_CV_CFG_ID; + ctx_setup.cv.cfg.id = setup.curve_id; + } + } + + ctx_setup.rand.cb = ecc_get_rand; + // set def setting; + ctx_setup.hash.cb = ecc_compute_hash; + ctx_setup.hash.type = WCRYPTO_HASH_SHA256; + + ret = get_ecc_param_from_sample(&setup, subtype, pdata->keybits); + if (ret) + return NULL; + + ctx = wcrypto_create_ecc_ctx(queue, &ctx_setup); + if (!ctx) + goto msg_release; + + prk.data = (void *)setup.priv_key; + prk.dsize = setup.priv_key_size; + prk.bsize = setup.priv_key_size; + pbk.x.data = (char *)setup.pub_key + 1; + pbk.x.dsize = key_size; + pbk.x.bsize = key_size; + pbk.y.data = pbk.x.data + key_size; + pbk.y.dsize = key_size; + pbk.y.bsize = key_size; + + ecc_key = wcrypto_get_ecc_key(ctx); + ret = wcrypto_set_ecc_prikey(ecc_key, &prk); + if (ret) { + HPRE_TST_PRT("failed to set ecc prikey!\n"); + goto sess_release; + } + + ret = wcrypto_set_ecc_pubkey(ecc_key, &pbk); + if (ret) { + HPRE_TST_PRT("failed to set ecc pubkey!\n"); + goto sess_release; + } + + opdata.op_type = pdata->optype; + switch (subtype) { + case ECDSA_TYPE: // ECC alg + ret = ecdsa_param_fill(ctx, &opdata, ecc_key, &setup, pdata); + if (ret) + goto src_release; + wcrypto_do_ecc = wcrypto_do_ecdsa; + break; + case SM2_TYPE: // SM2 alg + ret = sm2_param_fill(ctx, &opdata, &setup, pdata); + if (ret) + goto src_release; + wcrypto_do_ecc = wcrypto_do_sm2; + break; + default: // ECDH, X25519, X448 alg + ret = ecc_param_fill(ctx, &opdata, ecc_key, &setup, pdata); + if (ret) + goto src_release; + wcrypto_do_ecc = wcrypto_do_ecxdh; + break; + } + + do { + ret = wcrypto_do_ecc(ctx, &opdata, tag); + if (ret || opdata.status) { + HPRE_TST_PRT("failed to do ecc task, status: %d\n", opdata.status); + goto src_release; + } + + count++; + if (get_run_state() == 0) + break; + } while(true); + +src_release: + if (opdata.in) + (void)wcrypto_del_ecc_in(ctx, opdata.in); + if (opdata.out) + (void)wcrypto_del_ecc_out(ctx, opdata.out); +sess_release: + wcrypto_del_ecc_ctx(ctx); +msg_release: + if (subtype == SM2_TYPE) + free(setup.msg); + add_recv_data(count, key_size); + + return NULL; +} + +static void ecc_async_cb(const void *msg, void *tag) +{ + //struct wcrypto_ecc_msg *massage = msg; + //struct rsa_async_tag *ptag = tag; + //u32 op_type = tag->op_type; + //void *ctx = tag->ctx; + + return; +} + +static void *ecc_wd_async_run(void *arg) +{ + typedef int (*wd_do)(void *ctx, struct wcrypto_ecc_op_data *opdata, + void *tag); + wd_do wcrypto_do_ecc = NULL; + thread_data *pdata = (thread_data *)arg; + int key_size = pdata->keybits >> 3; + u32 subtype = pdata->subtype; + struct rsa_async_tag *tag = NULL; + struct wcrypto_ecc_ctx_setup ctx_setup; + struct wcrypto_ecc_op_data opdata; + struct wcrypto_ecc_curve param; + struct hpre_ecc_setup setup; + struct wcrypto_ecc_key *ecc_key; + struct wcrypto_ecc_point pbk; + struct wd_queue *queue; + struct wd_dtb prk; + void *ctx = NULL; + int try_cnt = 0; + void *pool; + u32 cid = ECC_CURVE_ID; + u32 count = 0; + int i, ret; + + memset(&ctx_setup, 0, sizeof(ctx_setup)); + memset(¶m, 0, sizeof(param)); + memset(&opdata, 0, sizeof(opdata)); + + pool = g_thread_queue.bd_res[pdata->td_id].pool; + queue = g_thread_queue.bd_res[pdata->td_id].queue; + + memset(&setup, 0, sizeof(setup)); + if (subtype != X448_TYPE || subtype != X25519_TYPE) { + ret = get_ecc_curve(&setup, cid); + if (ret) + return NULL; + } + + ctx_setup.cb = (void *)ecc_async_cb; + ctx_setup.br.alloc = (void *)wd_alloc_blk; + ctx_setup.br.free = (void *)wd_free_blk; + ctx_setup.br.iova_map = (void *)wd_blk_iova_map; + ctx_setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + ctx_setup.br.get_bufsize = (void *)wd_blksize; + ctx_setup.br.usr = pool; + + ctx_setup.key_bits = pdata->keybits; + if (subtype == ECDH_TYPE || subtype == ECDSA_TYPE) { + if (cid > ECC_CURVE_ID) { + ctx_setup.cv.type = WCRYPTO_CV_CFG_PARAM; + get_ecc_key_param(¶m, pdata->keybits); + ctx_setup.cv.cfg.pparam = ¶m; + } else { + ctx_setup.cv.type = WCRYPTO_CV_CFG_ID; + ctx_setup.cv.cfg.id = setup.curve_id; + } + } + + ctx_setup.rand.cb = ecc_get_rand; + // set def setting; + ctx_setup.hash.cb = ecc_compute_hash; + ctx_setup.hash.type = WCRYPTO_HASH_SHA256; + + ret = get_ecc_param_from_sample(&setup, subtype, pdata->keybits); + if (ret) + return NULL; + + ctx = wcrypto_create_ecc_ctx(queue, &ctx_setup); + if (!ctx) + goto msg_release; + + prk.data = (void *)setup.priv_key; + prk.dsize = setup.priv_key_size; + prk.bsize = setup.priv_key_size; + pbk.x.data = (char *)setup.pub_key + 1; + pbk.x.dsize = key_size; + pbk.x.bsize = key_size; + pbk.y.data = pbk.x.data + key_size; + pbk.y.dsize = key_size; + pbk.y.bsize = key_size; + + ecc_key = wcrypto_get_ecc_key(ctx); + ret = wcrypto_set_ecc_prikey(ecc_key, &prk); + if (ret) { + HPRE_TST_PRT("failed to set ecc prikey!\n"); + goto sess_release; + } + + ret = wcrypto_set_ecc_pubkey(ecc_key, &pbk); + if (ret) { + HPRE_TST_PRT("failed to set ecc pubkey!\n"); + goto sess_release; + } + + opdata.op_type = pdata->optype; + switch (subtype) { + case ECDSA_TYPE: // ECC alg + ret = ecdsa_param_fill(ctx, &opdata, ecc_key, &setup, pdata); + if (ret) + goto src_release; + wcrypto_do_ecc = wcrypto_do_ecdsa; + break; + case SM2_TYPE: // SM2 alg + ret = sm2_param_fill(ctx, &opdata, &setup, pdata); + if (ret) + goto src_release; + wcrypto_do_ecc = wcrypto_do_sm2; + break; + default: // ECDH, X25519, X448 alg + ret = ecc_param_fill(ctx, &opdata, ecc_key, &setup, pdata); + if (ret) + goto src_release; + wcrypto_do_ecc = wcrypto_do_ecxdh; + break; + } + + tag = malloc(sizeof(*tag) * MAX_POOL_LENTH); + if (!tag) { + HPRE_TST_PRT("failed to malloc ecc tag!\n"); + goto src_release; + } + + do { + if (get_run_state() == 0) + break; + + try_cnt = 0; + i = count % MAX_POOL_LENTH; + tag[i].ctx = ctx; + tag[i].cnt = i; + tag[i].optype = opdata.op_type; + + ret = wcrypto_do_ecc(ctx, &opdata, &tag[i]); + if (ret == -WD_EBUSY) { + usleep(SEND_USLEEP * try_cnt); + try_cnt++; + if (try_cnt > MAX_TRY_CNT) { + HPRE_TST_PRT("Test ECC send fail %d times!\n", MAX_TRY_CNT); + try_cnt = 0; + } + continue; + } else if (ret) { + HPRE_TST_PRT("failed to do rsa async task!\n"); + goto tag_release; + } + count++; + } while(true); + +tag_release: + free(tag); +src_release: + if (opdata.in) + (void)wcrypto_del_ecc_in(ctx, opdata.in); + if (opdata.out) + (void)wcrypto_del_ecc_out(ctx, opdata.out); +sess_release: + while (1) { + if (get_recv_time() > 0) // wait Async mode finish recv + break; + usleep(SEND_USLEEP); + } + + wcrypto_del_ecc_ctx(ctx); +msg_release: + if (subtype == SM2_TYPE) + free(setup.msg); + add_send_complete(); + + return NULL; +} + +static int hpre_wd_sync_threads(struct acc_option *options) +{ + typedef void *(*hpre_sync_run)(void *arg); + hpre_sync_run wd_hpre_sync_run = NULL; + thread_data threads_args[THREADS_NUM]; + thread_data threads_option; + pthread_t tdid[THREADS_NUM]; + int i, ret; + + /* alg param parse and set to thread data */ + threads_option.subtype = options->subtype; + threads_option.td_id = 0; + ret = hpre_wd_param_parse(&threads_option, options); + if (ret) + return ret; + + switch (options->subtype) { + case RSA_TYPE: + wd_hpre_sync_run = rsa_wd_sync_run; + break; + case DH_TYPE: + wd_hpre_sync_run = dh_wd_sync_run; + break; + case ECDH_TYPE: + case ECDSA_TYPE: + case SM2_TYPE: + case X25519_TYPE: + case X448_TYPE: + wd_hpre_sync_run = ecc_wd_sync_run; + break; + default: + HPRE_TST_PRT("failed to parse alg subtype on uninit!\n"); + return -EINVAL; + } + + for (i = 0; i < g_thread_num; i++) { + threads_args[i].subtype = threads_option.subtype; + threads_args[i].kmode = threads_option.kmode; + threads_args[i].keybits = threads_option.keybits; + threads_args[i].optype = threads_option.optype; + threads_args[i].td_id = i; + ret = pthread_create(&tdid[i], NULL, wd_hpre_sync_run, &threads_args[i]); + if (ret) { + HPRE_TST_PRT("Create sync thread fail!\n"); + goto sync_error; + } + } + + /* join thread */ + for (i = 0; i < g_thread_num; i++) { + ret = pthread_join(tdid[i], NULL); + if (ret) { + HPRE_TST_PRT("Join sync thread fail!\n"); + goto sync_error; + } + } + +sync_error: + return ret; +} + +static int hpre_wd_async_threads(struct acc_option *options) +{ + typedef void *(*hpre_async_run)(void *arg); + hpre_async_run wd_hpre_async_run = NULL; + thread_data threads_args[THREADS_NUM]; + thread_data threads_option; + pthread_t tdid[THREADS_NUM]; + pthread_t pollid[THREADS_NUM]; + int i, ret; + + /* alg param parse and set to thread data */ + threads_option.subtype = options->subtype; + threads_option.td_id = 0; + ret = hpre_wd_param_parse(&threads_option, options); + if (ret) + return ret; + + switch (options->subtype) { + case RSA_TYPE: + wd_hpre_async_run = rsa_wd_async_run; + break; + case DH_TYPE: + wd_hpre_async_run = dh_wd_async_run; + break; + case ECDH_TYPE: + case ECDSA_TYPE: + case SM2_TYPE: + case X25519_TYPE: + case X448_TYPE: + wd_hpre_async_run = ecc_wd_async_run; + break; + default: + HPRE_TST_PRT("failed to parse alg subtype on uninit!\n"); + return -EINVAL; + } + + for (i = 0; i < g_thread_num; i++) { + threads_args[i].subtype = threads_option.subtype; + threads_args[i].td_id = i; + /* poll thread */ + ret = pthread_create(&pollid[i], NULL, hpre_wd_poll, &threads_args[i]); + if (ret) { + HPRE_TST_PRT("Create poll thread fail!\n"); + goto async_error; + } + } + + for (i = 0; i < g_thread_num; i++) { + threads_args[i].subtype = threads_option.subtype; + threads_args[i].kmode = threads_option.kmode; + threads_args[i].keybits = threads_option.keybits; + threads_args[i].optype = threads_option.optype; + threads_args[i].td_id = i; + ret = pthread_create(&tdid[i], NULL, wd_hpre_async_run, &threads_args[i]); + if (ret) { + HPRE_TST_PRT("Create async thread fail!\n"); + goto async_error; + } + } + + /* join thread */ + for (i = 0; i < g_thread_num; i++) { + ret = pthread_join(tdid[i], NULL); + if (ret) { + HPRE_TST_PRT("Join async thread fail!\n"); + goto async_error; + } + } + + for (i = 0; i < g_thread_num; i++) { + ret = pthread_join(pollid[i], NULL); + if (ret) { + HPRE_TST_PRT("Join poll thread fail!\n"); + goto async_error; + } + } + +async_error: + return ret; +} + +int hpre_wd_benchmark(struct acc_option *options) +{ + u32 ptime; + int ret; + + g_thread_num = options->threads; + + if (options->optype >= (WCRYPTO_EC_OP_MAX - WCRYPTO_ECDSA_VERIFY)) { + HPRE_TST_PRT("HPRE optype error: %u\n", options->optype); + return -EINVAL; + } + + ret = init_hpre_wd_queue(options); + if (ret) + return ret; + + get_pid_cpu_time(&ptime); + time_start(options->times); + if (options->syncmode) + ret = hpre_wd_async_threads(options); + else + ret = hpre_wd_sync_threads(options); + cal_perfermance_data(options, ptime); + if (ret) + return ret; + + uninit_hpre_wd_queue(); + + return 0; +} diff --git a/uadk/uadk_tool/benchmark/hpre_wd_benchmark.h b/uadk/uadk_tool/benchmark/hpre_wd_benchmark.h new file mode 100644 index 0000000..0cc94a3 --- /dev/null +++ b/uadk/uadk_tool/benchmark/hpre_wd_benchmark.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +#ifndef HPRE_WD_BENCHMARK_H +#define HPRE_WD_BENCHMARK_H + +extern int hpre_wd_benchmark(struct acc_option *options); +#endif /* HPRE_WD_BENCHMARK_H */ diff --git a/uadk/uadk_tool/benchmark/include/fse.h b/uadk/uadk_tool/benchmark/include/fse.h new file mode 100644 index 0000000..73c3eda --- /dev/null +++ b/uadk/uadk_tool/benchmark/include/fse.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef ZSTD_LZ77_FSE_H +#define ZSTD_LZ77_FSE_H + +#include +#include + +typedef struct ZSTD_CCtx_s ZSTD_CCtx; + +typedef struct seqDef_s { + unsigned int offset; + unsigned short litLength; + unsigned short matchLength; +} seqDef; + +typedef struct COMP_4TUPLE_TAG_S { + char *litStart; /* literal start address */ + seqDef *sequencesStart; /* sequences start address */ + unsigned int litlen; /* literal effective data length */ + unsigned int seqnum; /* sequences array's elements numbers */ + unsigned int longLengthID; /* litlen overflow flag */ + unsigned int longLengthPos; /* litlen overflow index */ + char *additional_p; /* start address of additional data */ +} COMP_TUPLE_TAG; + +typedef struct ZSTD_inBuffer_s { + const void* src; /* < start of input buffer */ + size_t size; /* < size of input buffer */ + size_t pos; /* < position where reading stopped. Will be updated. Necessarily 0 <= pos <= size */ +} ZSTD_inBuffer; + +typedef struct ZSTD_outBuffer_s { + void* dst; /* < start of output buffer */ + size_t size; /* < size of output buffer */ + size_t pos; /* < position where writing stopped. Will be updated. Necessarily 0 <= pos <= size */ +} ZSTD_outBuffer; + +typedef enum { + ZSTD_e_continue = 0, /* collect more data, encoder decides when to output compressed result, for optimal compression ratio */ + ZSTD_e_flush = 1, /* flush any data provided so far */ + ZSTD_e_end = 2 /* flush any remaining data _and_ close current frame. */ +} ZSTD_EndDirective; + +/* the complete implementation code in libfse */ +#ifdef ZLIB_FSE +ZSTD_CCtx* zstd_soft_fse_init(unsigned int level); +int zstd_soft_fse(void *Ftuple, ZSTD_inBuffer *input, ZSTD_outBuffer *output, ZSTD_CCtx * cctx, ZSTD_EndDirective cmode); +#endif + +#endif diff --git a/uadk/uadk_tool/benchmark/sec_soft_benchmark.c b/uadk/uadk_tool/benchmark/sec_soft_benchmark.c new file mode 100644 index 0000000..a622329 --- /dev/null +++ b/uadk/uadk_tool/benchmark/sec_soft_benchmark.c @@ -0,0 +1,990 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include "sec_soft_benchmark.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "include/wd_cipher.h" +#include "include/wd_digest.h" + +#define SSL_TST_PRT printf + +struct soft_bd { + u8 *src; + u8 *dst; +}; + +struct bd_pool { + struct soft_bd *bds; +}; + +struct thread_pool { + struct bd_pool *pool; + u8 *iv; + u8 *key; +} g_soft_pool; + +typedef struct soft_thread_res { + const EVP_CIPHER *evp_cipher; + const EVP_MD *evp_md; + u32 subtype; + u32 mode; + u32 keysize; + u32 optype; + u32 td_id; + u32 engine_flag; +} soft_thread; + +typedef struct soft_jobs_res { + const EVP_CIPHER *evp_cipher; + const EVP_MD *evp_md; + u32 subtype; + u32 mode; + u32 keysize; + u32 optype; + u32 td_id; + u32 jobid; + u32 use_engine; +} jobs_data; + +#define MAX_IVK_LENTH 64 +#define DEF_IVK_DATA 0xAA + +static unsigned int g_thread_num; +static unsigned int g_ctxnum; +static unsigned int g_pktlen; + +static int init_soft_bd_pool(void) +{ + unsigned long step; + int fill_size; + int i, j; + + // make the block not align to 4K + step = sizeof(char) * g_pktlen * 2; + if (g_pktlen > MAX_IVK_LENTH) + fill_size = MAX_IVK_LENTH; + else + fill_size = g_pktlen; + + g_soft_pool.iv = malloc(g_thread_num * MAX_IVK_LENTH * sizeof(char)); + g_soft_pool.key = malloc(g_thread_num * MAX_IVK_LENTH * sizeof(char)); + + g_soft_pool.pool = malloc(g_thread_num * sizeof(struct bd_pool)); + if (!g_soft_pool.pool) { + SSL_TST_PRT("init openssl pool alloc thread failed!\n"); + return -ENOMEM; + } else { + for (i = 0; i < g_thread_num; i++) { + g_soft_pool.pool[i].bds = malloc(MAX_POOL_LENTH * + sizeof(struct soft_bd)); + if (!g_soft_pool.pool[i].bds) { + SSL_TST_PRT("init openssl bds alloc failed!\n"); + goto malloc_error1; + } + for (j = 0; j < MAX_POOL_LENTH; j++) { + g_soft_pool.pool[i].bds[j].src = malloc(step); + if (!g_soft_pool.pool[i].bds[j].src) + goto malloc_error2; + g_soft_pool.pool[i].bds[j].dst = malloc(step); + if (!g_soft_pool.pool[i].bds[j].dst) + goto malloc_error3; + + get_rand_data(g_soft_pool.pool[i].bds[j].src, fill_size); + //get_rand_data(g_soft_pool.pool[i].bds[j].dst, 16); + } + } + } + + return 0; + +malloc_error3: + free(g_soft_pool.pool[i].bds[j].src); +malloc_error2: + for (j--; j >= 0; j--) { + free(g_soft_pool.pool[i].bds[j].src); + free(g_soft_pool.pool[i].bds[j].dst); + } +malloc_error1: + for (i--; i >= 0; i--) { + for (j = 0; j < MAX_POOL_LENTH; j++) { + free(g_soft_pool.pool[i].bds[j].src); + free(g_soft_pool.pool[i].bds[j].dst); + } + free(g_soft_pool.pool[i].bds); + g_soft_pool.pool[i].bds = NULL; + } + free(g_soft_pool.pool); + g_soft_pool.pool = NULL; + + free(g_soft_pool.iv); + free(g_soft_pool.key); + + SSL_TST_PRT("init openssl bd pool alloc failed!\n"); + return -ENOMEM; +} + +static void free_soft_bd_pool(void) +{ + int i, j; + + for (i = 0; i < g_thread_num; i++) { + if (g_soft_pool.pool[i].bds) { + for (j = 0; j < MAX_POOL_LENTH; j++) { + free(g_soft_pool.pool[i].bds[j].src); + free(g_soft_pool.pool[i].bds[j].dst); + } + } + free(g_soft_pool.pool[i].bds); + g_soft_pool.pool[i].bds = NULL; + } + free(g_soft_pool.pool); + g_soft_pool.pool = NULL; + + free(g_soft_pool.iv); + free(g_soft_pool.key); +} + +/*-------------------------------openssl benchmark main code-------------------------------------*/ +static int sec_soft_param_parse(soft_thread *tddata, struct acc_option *options) +{ + u32 algtype = options->algtype; + u32 optype = options->optype; + u8 keysize = 0; + u8 mode; + + tddata->evp_cipher = NULL; + tddata->evp_md = NULL; + + switch(algtype) { + case AES_128_ECB: + keysize = 16; + mode = WD_CIPHER_ECB; + tddata->evp_cipher = EVP_aes_128_ecb(); + break; + case AES_192_ECB: + keysize = 24; + mode = WD_CIPHER_ECB; + tddata->evp_cipher = EVP_aes_192_ecb(); + break; + case AES_256_ECB: + keysize = 32; + mode = WD_CIPHER_ECB; + tddata->evp_cipher = EVP_aes_256_ecb(); + break; + case AES_128_CBC: + keysize = 16; + mode = WD_CIPHER_CBC; + tddata->evp_cipher = EVP_aes_128_cbc(); + break; + case AES_192_CBC: + keysize = 24; + mode = WD_CIPHER_CBC; + tddata->evp_cipher = EVP_aes_192_cbc(); + break; + case AES_256_CBC: + keysize = 32; + mode = WD_CIPHER_CBC; + tddata->evp_cipher = EVP_aes_256_cbc(); + break; + case AES_128_CTR: + keysize = 16; + mode = WD_CIPHER_CTR; + tddata->evp_cipher = EVP_aes_128_ctr(); + break; + case AES_192_CTR: + keysize = 24; + mode = WD_CIPHER_CTR; + tddata->evp_cipher = EVP_aes_192_ctr(); + break; + case AES_256_CTR: + keysize = 32; + mode = WD_CIPHER_CTR; + tddata->evp_cipher = EVP_aes_256_ctr(); + break; + case AES_128_OFB: + keysize = 16; + mode = WD_CIPHER_OFB; + tddata->evp_cipher = EVP_aes_128_ofb(); + break; + case AES_192_OFB: + keysize = 24; + mode = WD_CIPHER_OFB; + tddata->evp_cipher = EVP_aes_192_ofb(); + break; + case AES_256_OFB: + keysize = 32; + mode = WD_CIPHER_OFB; + tddata->evp_cipher = EVP_aes_256_ofb(); + break; + case AES_128_CFB: + keysize = 16; + mode = WD_CIPHER_CFB; + tddata->evp_cipher = EVP_aes_128_cfb(); + break; + case AES_192_CFB: + keysize = 24; + mode = WD_CIPHER_CFB; + tddata->evp_cipher = EVP_aes_192_cfb(); + break; + case AES_256_CFB: + keysize = 32; + mode = WD_CIPHER_CFB; + tddata->evp_cipher = EVP_aes_256_cfb(); + break; + case AES_256_XTS: + keysize = 32; + mode = WD_CIPHER_XTS; + tddata->evp_cipher = EVP_aes_128_xts(); + break; + case AES_512_XTS: + keysize = 64; + mode = WD_CIPHER_XTS; + tddata->evp_cipher = EVP_aes_256_xts(); + break; + case DES3_128_ECB: + keysize = 16; + mode = WD_CIPHER_ECB; + tddata->evp_cipher = EVP_des_ede_ecb(); + break; + case DES3_192_ECB: + keysize = 24; + mode = WD_CIPHER_ECB; + tddata->evp_cipher = EVP_des_ede3_ecb(); + break; + case DES3_128_CBC: + keysize = 16; + mode = WD_CIPHER_CBC; + tddata->evp_cipher = EVP_des_ede_cbc(); + break; + case DES3_192_CBC: + keysize = 24; + mode = WD_CIPHER_CBC; + tddata->evp_cipher = EVP_des_ede3_cbc(); + break; + case SM4_128_ECB: + keysize = 16; + mode = WD_CIPHER_ECB; + tddata->evp_cipher = EVP_sm4_ecb(); + break; + case SM4_128_CBC: + keysize = 16; + mode = WD_CIPHER_CBC; + tddata->evp_cipher = EVP_sm4_cbc(); + break; + case SM4_128_CTR: + keysize = 16; + mode = WD_CIPHER_CTR; + tddata->evp_cipher = EVP_sm4_ctr(); + break; + case SM4_128_OFB: + keysize = 16; + mode = WD_CIPHER_OFB; + tddata->evp_cipher = EVP_sm4_ofb(); + break; + case SM4_128_CFB: + keysize = 16; + mode = WD_CIPHER_CFB; + tddata->evp_cipher = EVP_sm4_cfb128(); + break; + case SM4_128_XTS: + keysize = 16; + mode = WD_CIPHER_XTS; + break; + case AES_128_CCM: + keysize = 16; + mode = WD_CIPHER_CCM; + tddata->evp_cipher = EVP_aes_128_ccm(); + break; + case AES_192_CCM: + keysize = 24; + mode = WD_CIPHER_CCM; + tddata->evp_cipher = EVP_aes_192_ccm(); + break; + case AES_256_CCM: + keysize = 32; + mode = WD_CIPHER_CCM; + tddata->evp_cipher = EVP_aes_256_ccm(); + break; + case AES_128_GCM: + keysize = 16; + mode = WD_CIPHER_GCM; + tddata->evp_cipher = EVP_aes_128_gcm(); + break; + case AES_192_GCM: + keysize = 24; + mode = WD_CIPHER_GCM; + tddata->evp_cipher = EVP_aes_192_gcm(); + break; + case AES_256_GCM: + keysize = 32; + mode = WD_CIPHER_GCM; + tddata->evp_cipher = EVP_aes_256_gcm(); + break; + case SM4_128_CCM: + keysize = 16; + mode = WD_CIPHER_CCM; + break; + case SM4_128_GCM: + keysize = 16; + mode = WD_CIPHER_GCM; + break; + case SM3_ALG: // digest mode is optype + keysize = 4; + mode = optype; + tddata->evp_md = EVP_sm3(); + break; + case MD5_ALG: + keysize = 4; + mode = optype; + tddata->evp_md = EVP_md5(); + break; + case SHA1_ALG: + keysize = 4; + mode = optype; + tddata->evp_md = EVP_sha1(); + break; + case SHA256_ALG: + keysize = 4; + mode = optype; + tddata->evp_md = EVP_sha256(); + break; + case SHA224_ALG: + keysize = 4; + mode = optype; + tddata->evp_md = EVP_sha224(); + break; + case SHA384_ALG: + keysize = 4; + mode = optype; + tddata->evp_md = EVP_sha384(); + break; + case SHA512_ALG: + keysize = 4; + mode = optype; + tddata->evp_md = EVP_sha512(); + break; + case SHA512_224: + keysize = 4; + mode = optype; + tddata->evp_md = EVP_sha512_224(); + break; + case SHA512_256: + keysize = 4; + mode = optype; + tddata->evp_md = EVP_sha512_256(); + break; + default: + SSL_TST_PRT("Fail to set sec alg\n"); + return -EINVAL; + } + + tddata->mode = mode; + tddata->keysize = keysize; + tddata->optype = options->optype; + tddata->subtype = options->subtype; + + return 0; +} + +static int sec_soft_jobfunc(void *args) +{ + jobs_data *jdata = (jobs_data *)args; + const EVP_CIPHER *evp_cipher = jdata->evp_cipher; + const EVP_MD *evp_md = jdata->evp_md; + u32 optype = jdata->optype; + u32 jid = jdata->jobid; + struct bd_pool *soft_pool; + u8 *priv_iv, *priv_key; + int ret, outl, i = 0; + EVP_CIPHER_CTX *ctx; + EVP_MD_CTX *md_ctx; + HMAC_CTX *hm_ctx; + ASYNC_JOB *currjob; + u8 faketag[16] = {0xcc}; + u8 aad[13] = {0xcc}; + u8 tag[12] = {0}; + u8 mac[EVP_MAX_MD_SIZE] = {0x00}; + u32 ssl_size = 0; + u8 *src, *dst; + + currjob = ASYNC_get_current_job(); + if (!currjob) { + SSL_TST_PRT("Error: not executing within a job\n"); + return 0; + } + + if (!evp_cipher && !evp_md) { + SSL_TST_PRT("Error: openssl not support!\n"); + return 0; + } + + if (jdata->td_id > g_thread_num) + return 0; + + soft_pool = &g_soft_pool.pool[jdata->td_id]; + priv_iv = &g_soft_pool.iv[jdata->td_id]; + priv_key = &g_soft_pool.key[jdata->td_id]; + + memset(priv_iv, DEF_IVK_DATA, MAX_IVK_LENTH); + memset(priv_key, DEF_IVK_DATA, MAX_IVK_LENTH); + + switch(jdata->subtype) { + case CIPHER_TYPE: + ctx = EVP_CIPHER_CTX_new(); + if (!ctx) + return 0; + + EVP_CIPHER_CTX_set_padding(ctx, 0); + + ret = EVP_CipherInit_ex(ctx, evp_cipher, NULL, priv_key, priv_iv, optype); + if (ret != 1) { + SSL_TST_PRT("Error: EVP_CipherInit_ex fail ret: %d\n", ret); + break; + } + + i = jid % MAX_POOL_LENTH; + src = soft_pool->bds[i].src; + dst = soft_pool->bds[i].dst; + if (optype) + ret = EVP_DecryptUpdate(ctx, dst, &outl, src, g_pktlen); + else + ret = EVP_EncryptUpdate(ctx, dst, &outl, src, g_pktlen); + if (ret != 1) + EVP_CipherInit_ex(ctx, NULL, NULL, NULL, priv_iv, -1); + + if (optype) + EVP_DecryptFinal_ex(ctx, dst, &outl); + else + EVP_EncryptFinal_ex(ctx, dst, &outl); + + EVP_CIPHER_CTX_free(ctx); + break; + case AEAD_TYPE: + ctx = EVP_CIPHER_CTX_new(); + if (!ctx) + return 0; + + EVP_CIPHER_CTX_set_padding(ctx, 0); + + ret = EVP_CipherInit_ex(ctx, evp_cipher, NULL, priv_key, priv_iv, optype); + if (ret != 1) { + SSL_TST_PRT("Error: AEAD EVP_CipherInit_ex fail ret: %d\n", ret); + break; + } + + if (jdata->mode == WD_CIPHER_CCM) { + i = jid % MAX_POOL_LENTH; + src = soft_pool->bds[i].src; + dst = soft_pool->bds[i].dst; + if (optype) { + EVP_CIPHER_CTX_ctrl(ctx, 0x11, sizeof(tag), tag); + /* reset iv */ + EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, priv_iv); + EVP_DecryptUpdate(ctx, dst, &outl, src, g_pktlen); + } else { + /* restore iv length field */ + EVP_EncryptUpdate(ctx, NULL, &outl, NULL, g_pktlen); + /* counter is reset on every update */ + EVP_EncryptUpdate(ctx, dst, &outl, src, g_pktlen); + } + + if (optype) + EVP_DecryptFinal_ex(ctx, dst, &outl); + else + EVP_EncryptFinal_ex(ctx, dst, &outl); + } else { + i = jid % MAX_POOL_LENTH; + src = soft_pool->bds[i].src; + dst = soft_pool->bds[i].dst; + if (optype) { + EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, priv_iv); + EVP_CIPHER_CTX_ctrl(ctx, 0x11, + sizeof(faketag), tag); + EVP_DecryptUpdate(ctx, NULL, &outl, aad, sizeof(aad)); + EVP_DecryptUpdate(ctx, dst, &outl, src, g_pktlen); + EVP_DecryptFinal_ex(ctx, dst + outl, &outl); + } else { + EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, priv_iv); + EVP_DecryptUpdate(ctx, NULL, &outl, aad, sizeof(aad)); + EVP_EncryptUpdate(ctx, NULL, &outl, NULL, g_pktlen); + EVP_DecryptFinal_ex(ctx, dst + outl, &outl); + } + } + EVP_CIPHER_CTX_free(ctx); + + break; + case DIGEST_TYPE: + if (!optype) { //normal mode + md_ctx = EVP_MD_CTX_new(); + if (!md_ctx) + return 0; + + i = jid % MAX_POOL_LENTH; + src = soft_pool->bds[i].src; + + EVP_DigestInit_ex(md_ctx, evp_md, NULL); + EVP_DigestUpdate(md_ctx, src, g_pktlen); + EVP_DigestFinal_ex(md_ctx, mac, &ssl_size); + // EVP_Digest(src, g_pktlen, mac, &ssl_size, evp_md, NULL); + + EVP_MD_CTX_free(md_ctx); + } else { //hmac mode + hm_ctx = HMAC_CTX_new(); + if (!hm_ctx) + return 0; + + i = jid % MAX_POOL_LENTH; + src = soft_pool->bds[i].src; + + HMAC_Init_ex(hm_ctx, priv_key, jdata->keysize, evp_md, NULL); + HMAC_Update(hm_ctx, src, g_pktlen); + HMAC_Final(hm_ctx, mac, &ssl_size); + // HMAC(evp_md, priv_key, jdata->keysize, src, g_pktlen, mac, &ssl_size); + + HMAC_CTX_free(hm_ctx); + } + break; + } + + return 0; +} + +static void *sec_soft_async_run(void *arg) +{ + soft_thread *pdata = (soft_thread *)arg; + ASYNC_WAIT_CTX *waitctx = NULL; + ASYNC_JOB *job = NULL; + int ret, jobret = 0; + jobs_data jobdata; + u32 count = 0; + + jobdata.evp_cipher = pdata->evp_cipher; + jobdata.evp_md = pdata->evp_md; + jobdata.keysize = pdata->keysize; + jobdata.mode = pdata->mode; + jobdata.optype = pdata->optype; + jobdata.subtype = pdata->subtype; + jobdata.td_id = pdata->td_id; + + waitctx = ASYNC_WAIT_CTX_new(); + if (!waitctx) { + SSL_TST_PRT("Error: create ASYNC_WAIT_CTX failed\n"); + return NULL; + } + + while (1) { + jobdata.jobid = count; + ret = ASYNC_start_job(&job, waitctx, &jobret, sec_soft_jobfunc, + (void *)&jobdata, sizeof(jobs_data)); + switch(ret) { + case ASYNC_ERR: + SSL_TST_PRT("Error: start soft async job err. \n"); + goto exit_pause; + case ASYNC_NO_JOBS: + SSL_TST_PRT("Error: can't get soft async job from job pool. \n"); + goto exit_pause; + case ASYNC_PAUSE: + SSL_TST_PRT("Info: job was paused \n"); + break; + case ASYNC_FINISH: + break; + default: + SSL_TST_PRT("Error: do soft async job err. \n"); + } + + count++; + if (get_run_state() == 0) + break; + } + +exit_pause: + ASYNC_WAIT_CTX_free(waitctx); + + add_recv_data(count, g_pktlen); + + return NULL; +} + +static void *sec_soft_sync_run(void *arg) +{ + soft_thread *pdata = (soft_thread *)arg; + const EVP_CIPHER *evp_cipher = pdata->evp_cipher; + const EVP_MD *evp_md = pdata->evp_md; + u32 optype = pdata->optype; + u8 mac[EVP_MAX_MD_SIZE] = {0x00}; + struct bd_pool *soft_pool; + u8 *priv_iv, *priv_key; + EVP_CIPHER_CTX *ctx = NULL; + EVP_MD_CTX *md_ctx = NULL; + HMAC_CTX *hm_ctx = NULL; + u8 faketag[16] = {0xcc}; + u8 aad[13] = {0xcc}; + u8 tag[12] = {0}; + u32 ssl_size = 0; + u32 count = 0; + u8 *src, *dst; + int ret, i = 0; + int outl = 0; + + if (!evp_cipher && !evp_md) { + SSL_TST_PRT("Error: openssl not support!\n"); + return NULL; + } + + if (pdata->td_id > g_thread_num) + return NULL; + + soft_pool = &g_soft_pool.pool[pdata->td_id]; + priv_iv = &g_soft_pool.iv[pdata->td_id]; + priv_key = &g_soft_pool.key[pdata->td_id]; + + memset(priv_iv, DEF_IVK_DATA, MAX_IVK_LENTH); + memset(priv_key, DEF_IVK_DATA, MAX_IVK_LENTH); + + switch(pdata->subtype) { + case CIPHER_TYPE: + ctx = EVP_CIPHER_CTX_new(); + if (!ctx) + return NULL; + + EVP_CIPHER_CTX_set_padding(ctx, 0); + + while (1) { + i = count % MAX_POOL_LENTH; + src = soft_pool->bds[i].src; + dst = soft_pool->bds[i].dst; + + (void)EVP_CipherInit_ex(ctx, evp_cipher, NULL, priv_key, priv_iv, optype); + + if (optype) + ret = EVP_DecryptUpdate(ctx, dst, &outl, src, g_pktlen); + else + ret = EVP_EncryptUpdate(ctx, dst, &outl, src, g_pktlen); + if (ret != 1) + EVP_CipherInit_ex(ctx, evp_cipher, NULL, priv_key, priv_iv, optype); + + if (optype) + EVP_DecryptFinal_ex(ctx, dst, &outl); + else + EVP_EncryptFinal_ex(ctx, dst, &outl); + + count++; + if (get_run_state() == 0) + break; + } + + EVP_CIPHER_CTX_free(ctx); + + break; + case AEAD_TYPE: + ctx = EVP_CIPHER_CTX_new(); + if (!ctx) + return NULL; + + EVP_CIPHER_CTX_set_padding(ctx, 0); + + if (pdata->mode == WD_CIPHER_CCM) { + while (1) { + i = count % MAX_POOL_LENTH; + src = soft_pool->bds[i].src; + dst = soft_pool->bds[i].dst; + + (void)EVP_CipherInit_ex(ctx, evp_cipher, NULL, priv_key, priv_iv, optype); + + if (optype) { + EVP_CIPHER_CTX_ctrl(ctx, 0x11, sizeof(tag), tag); + /* reset iv */ + EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, priv_iv); + ret = EVP_DecryptUpdate(ctx, dst, &outl, src, g_pktlen); + } else { + /* restore iv length field */ + EVP_EncryptUpdate(ctx, NULL, &outl, NULL, g_pktlen); + /* counter is reset on every update */ + ret = EVP_EncryptUpdate(ctx, dst, &outl, src, g_pktlen); + } + if (ret != 1) + EVP_CipherInit_ex(ctx, evp_cipher, NULL, priv_key, priv_iv, optype); + + if (optype) + EVP_DecryptFinal_ex(ctx, dst, &outl); + else + EVP_EncryptFinal_ex(ctx, dst, &outl); + + count++; + if (get_run_state() == 0) + break; + } + } else { + while (1) { + i = count % MAX_POOL_LENTH; + src = soft_pool->bds[i].src; + dst = soft_pool->bds[i].dst; + + (void)EVP_CipherInit_ex(ctx, evp_cipher, NULL, priv_key, priv_iv, optype); + + if (optype) { + EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, priv_iv); + EVP_CIPHER_CTX_ctrl(ctx, 0x11, + sizeof(faketag), tag); + EVP_DecryptUpdate(ctx, NULL, &outl, aad, sizeof(aad)); + EVP_DecryptUpdate(ctx, dst, &outl, src, g_pktlen); + ret = EVP_DecryptFinal_ex(ctx, dst + outl, &outl); + } else { + EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, priv_iv); + EVP_DecryptUpdate(ctx, NULL, &outl, aad, sizeof(aad)); + EVP_EncryptUpdate(ctx, NULL, &outl, NULL, g_pktlen); + ret = EVP_DecryptFinal_ex(ctx, dst + outl, &outl); + } + if (ret != 1) + EVP_CipherInit_ex(ctx, evp_cipher, NULL, priv_key, priv_iv, optype); + + count++; + if (get_run_state() == 0) + break; + } + } + EVP_CIPHER_CTX_free(ctx); + + break; + case DIGEST_TYPE: + if (!optype) { //normal mode + md_ctx = EVP_MD_CTX_new(); + if (!md_ctx) + return NULL; + + while (1) { + i = count % MAX_POOL_LENTH; + src = soft_pool->bds[i].src; + + EVP_DigestInit_ex(md_ctx, evp_md, NULL); + EVP_DigestUpdate(md_ctx, src, g_pktlen); + EVP_DigestFinal_ex(md_ctx, mac, &ssl_size); + // EVP_Digest(src, g_pktlen, mac, &ssl_size, evp_md, NULL); + + count++; + if (get_run_state() == 0) + break; + } + EVP_MD_CTX_free(md_ctx); + } else { //hmac mode + hm_ctx = HMAC_CTX_new(); + if (!hm_ctx) + return NULL; + + while (1) { + i = count % MAX_POOL_LENTH; + src = soft_pool->bds[i].src; + + HMAC_Init_ex(hm_ctx, priv_key, pdata->keysize, evp_md, NULL); + HMAC_Update(hm_ctx, src, g_pktlen); + HMAC_Final(hm_ctx, mac, &ssl_size); + // HMAC(evp_md, priv_key, pdata->keysize, src, g_pktlen, mac, &ssl_size); + + count++; + if (get_run_state() == 0) + break; + } + HMAC_CTX_free(hm_ctx); + } + break; + } + + add_recv_data(count, g_pktlen); + + return NULL; +} + +int sec_soft_sync_threads(struct acc_option *options) +{ + soft_thread threads_args[THREADS_NUM]; + soft_thread threads_option; + pthread_t tdid[THREADS_NUM]; + int i, ret; + + /* alg param parse and set to thread data */ + ret = sec_soft_param_parse(&threads_option, options); + if (ret) + return ret; + + for (i = 0; i < g_thread_num; i++) { + threads_args[i].evp_cipher = threads_option.evp_cipher; + threads_args[i].evp_md = threads_option.evp_md; + threads_args[i].subtype = threads_option.subtype; + threads_args[i].mode = threads_option.mode; + threads_args[i].keysize = threads_option.keysize; + threads_args[i].optype = threads_option.optype; + threads_args[i].td_id = i; + threads_args[i].engine_flag = options->engine_flag; + ret = pthread_create(&tdid[i], NULL, sec_soft_sync_run, &threads_args[i]); + if (ret) { + SSL_TST_PRT("Create sync thread fail!\n"); + goto sync_error; + } + } + + /* join thread */ + for (i = 0; i < g_thread_num; i++) { + ret = pthread_join(tdid[i], NULL); + if (ret) { + SSL_TST_PRT("Join sync thread fail!\n"); + goto sync_error; + } + } + +sync_error: + return ret; + +} + +int sec_soft_async_threads(struct acc_option *options) +{ + soft_thread threads_args[THREADS_NUM]; + soft_thread threads_option; + pthread_t tdid[THREADS_NUM]; + int i, ret; + + /* alg param parse and set to thread data */ + ret = sec_soft_param_parse(&threads_option, options); + if (ret) + return ret; + + for (i = 0; i < g_thread_num; i++) { + threads_args[i].evp_cipher = threads_option.evp_cipher; + threads_args[i].evp_md = threads_option.evp_md; + threads_args[i].subtype = threads_option.subtype; + threads_args[i].mode = threads_option.mode; + threads_args[i].keysize = threads_option.keysize; + threads_args[i].optype = threads_option.optype; + threads_args[i].td_id = i; + threads_args[i].engine_flag = options->engine_flag; + ret = pthread_create(&tdid[i], NULL, sec_soft_async_run, &threads_args[i]); + if (ret) { + SSL_TST_PRT("Create async thread fail!\n"); + goto async_error; + } + } + + /* join thread */ + for (i = 0; i < g_thread_num; i++) { + ret = pthread_join(tdid[i], NULL); + if (ret) { + SSL_TST_PRT("Join async thread fail!\n"); + goto async_error; + } + } + +async_error: + return ret; +} + +static int uadk_engine_register(struct acc_option *options) +{ + ENGINE *e = NULL; + + if (!options->engine_flag) + return 0; + + ERR_load_ENGINE_strings(); + OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_DYNAMIC, NULL); + + e = ENGINE_by_id(options->engine); + if (!e) { + SSL_TST_PRT("setup uadk engine failed!\n"); + return -EINVAL; + } + + ENGINE_init(e); + switch(options->subtype) { + case CIPHER_TYPE: + ENGINE_register_ciphers(e); + break; + case AEAD_TYPE: + SSL_TST_PRT("Openssl not support AEAD ALG!\n"); + return -EINVAL; + case DIGEST_TYPE: + ENGINE_register_digests(e); + break; + default: + return -EINVAL; + } + ENGINE_free(e); + + return 0; +} + +static void uadk_engine_unregister(struct acc_option *options) +{ + ENGINE *e = NULL; + + if (!options->engine_flag) + return; + + e = ENGINE_by_id(options->engine); + if (!e) { + SSL_TST_PRT("Error: not find uadk engine \n"); + return; + } + + ENGINE_init(e); + switch(options->subtype) { + case CIPHER_TYPE: + ENGINE_unregister_ciphers(e); + break; + case AEAD_TYPE: + // ENGINE_unregister_ciphers(e); //openssl not support aead + break; + case DIGEST_TYPE: + ENGINE_unregister_digests(e); + break; + default: + return; + } + ENGINE_free(e); +} + +int sec_soft_benchmark(struct acc_option *options) +{ + u32 ptime; + int ret; + + g_thread_num = options->threads; + g_pktlen = options->pktlen; + g_ctxnum = options->ctxnums; + if (options->optype > WD_CIPHER_DECRYPTION) { + SSL_TST_PRT("SEC optype error: %u\n", options->optype); + return -EINVAL; + } + + ret = init_soft_bd_pool(); + if (ret) + return ret; + + ret = uadk_engine_register(options); + if (ret) + return ret; + + get_pid_cpu_time(&ptime); + time_start(options->times); + if (options->syncmode) + ret = sec_soft_async_threads(options); + else + ret = sec_soft_sync_threads(options); + cal_perfermance_data(options, ptime); + if (ret) + return ret; + + uadk_engine_unregister(options); + free_soft_bd_pool(); + + return 0; +} diff --git a/uadk/uadk_tool/benchmark/sec_soft_benchmark.h b/uadk/uadk_tool/benchmark/sec_soft_benchmark.h new file mode 100644 index 0000000..c1374d6 --- /dev/null +++ b/uadk/uadk_tool/benchmark/sec_soft_benchmark.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +#ifndef SEC_SOFT_BENCHMARK_H +#define SEC_SOFT_BENCHMARK_H + +#include "uadk_benchmark.h" + +extern int sec_soft_benchmark(struct acc_option *options); +#endif /* SEC_SOFT_BENCHMARK_H */ diff --git a/uadk/uadk_tool/benchmark/sec_uadk_benchmark.c b/uadk/uadk_tool/benchmark/sec_uadk_benchmark.c new file mode 100644 index 0000000..09cd8f4 --- /dev/null +++ b/uadk/uadk_tool/benchmark/sec_uadk_benchmark.c @@ -0,0 +1,1074 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include "uadk_benchmark.h" + +#include "sec_uadk_benchmark.h" +#include "include/wd_cipher.h" +#include "include/wd_digest.h" +#include "include/wd_aead.h" +#include "include/wd_sched.h" + +#define SEC_TST_PRT printf +#define MAX_IVK_LENTH 64 +#define DEF_IVK_DATA 0xAA + +struct uadk_bd { + u8 *src; + u8 *dst; +}; + +struct bd_pool { + struct uadk_bd *bds; +}; + +struct thread_pool { + struct bd_pool *pool; + u8 *iv; + u8 *key; + u8 *mac; +} g_uadk_pool; + +typedef struct uadk_thread_res { + u32 subtype; + u32 alg; + u32 mode; + u32 keysize; + u32 ivsize; + u32 optype; + u32 td_id; +} thread_data; + +static struct wd_ctx_config g_ctx_cfg; +static struct wd_sched *g_sched; +static unsigned int g_thread_num; +static unsigned int g_ctxnum; +static unsigned int g_prefetch; +static unsigned int g_pktlen; + +static void *cipher_async_cb(struct wd_cipher_req *req, void *data) +{ + return NULL; +} + +static void *aead_async_cb(struct wd_aead_req *req, void *data) +{ + return NULL; +} + +static void *digest_async_cb(void *data) +{ + // struct wd_digest_req *req = (struct wd_digest_req *)data; + return NULL; +} + +static int sec_uadk_param_parse(thread_data *tddata, struct acc_option *options) +{ + u32 algtype = options->algtype; + u32 optype = options->optype; + u8 keysize = 0; + u8 ivsize = 0; + u8 mode; + u8 alg; + + switch(algtype) { + case AES_128_ECB: + keysize = 16; + ivsize = 0; + mode = WD_CIPHER_ECB; + alg = WD_CIPHER_AES; + break; + case AES_192_ECB: + keysize = 24; + ivsize = 0; + mode = WD_CIPHER_ECB; + alg = WD_CIPHER_AES; + break; + case AES_256_ECB: + keysize = 32; + ivsize = 0; + mode = WD_CIPHER_ECB; + alg = WD_CIPHER_AES; + break; + case AES_128_CBC: + keysize = 16; + ivsize = 16; + mode = WD_CIPHER_CBC; + alg = WD_CIPHER_AES; + break; + case AES_192_CBC: + keysize = 24; + ivsize = 16; + mode = WD_CIPHER_CBC; + alg = WD_CIPHER_AES; + break; + case AES_256_CBC: + keysize = 32; + ivsize = 16; + mode = WD_CIPHER_CBC; + alg = WD_CIPHER_AES; + break; + case AES_128_CTR: + keysize = 16; + ivsize = 16; + mode = WD_CIPHER_CTR; + alg = WD_CIPHER_AES; + break; + case AES_192_CTR: + keysize = 24; + ivsize = 16; + mode = WD_CIPHER_CTR; + alg = WD_CIPHER_AES; + break; + case AES_256_CTR: + keysize = 32; + ivsize = 16; + mode = WD_CIPHER_CTR; + alg = WD_CIPHER_AES; + break; + case AES_128_OFB: + keysize = 16; + ivsize = 16; + mode = WD_CIPHER_OFB; + alg = WD_CIPHER_AES; + break; + case AES_192_OFB: + keysize = 24; + ivsize = 16; + mode = WD_CIPHER_OFB; + alg = WD_CIPHER_AES; + break; + case AES_256_OFB: + keysize = 32; + ivsize = 16; + mode = WD_CIPHER_OFB; + alg = WD_CIPHER_AES; + break; + case AES_128_CFB: + keysize = 16; + ivsize = 16; + mode = WD_CIPHER_CFB; + alg = WD_CIPHER_AES; + break; + case AES_192_CFB: + keysize = 24; + ivsize = 16; + mode = WD_CIPHER_CFB; + alg = WD_CIPHER_AES; + break; + case AES_256_CFB: + keysize = 32; + ivsize = 16; + mode = WD_CIPHER_CFB; + alg = WD_CIPHER_AES; + break; + case AES_256_XTS: + keysize = 32; + ivsize = 16; + mode = WD_CIPHER_XTS; + alg = WD_CIPHER_AES; + break; + case AES_512_XTS: + keysize = 64; + ivsize = 16; + mode = WD_CIPHER_XTS; + alg = WD_CIPHER_AES; + break; + case DES3_128_ECB: + keysize = 16; + ivsize = 0; + mode = WD_CIPHER_ECB; + alg = WD_CIPHER_3DES; + break; + case DES3_192_ECB: + keysize = 24; + ivsize = 0; + mode = WD_CIPHER_ECB; + alg = WD_CIPHER_3DES; + break; + case DES3_128_CBC: + keysize = 16; + ivsize = 8; + mode = WD_CIPHER_CBC; + alg = WD_CIPHER_3DES; + break; + case DES3_192_CBC: + keysize = 24; + ivsize = 8; + mode = WD_CIPHER_CBC; + alg = WD_CIPHER_3DES; + break; + case SM4_128_ECB: + keysize = 16; + ivsize = 0; + mode = WD_CIPHER_ECB; + alg = WD_CIPHER_SM4; + break; + case SM4_128_CBC: + keysize = 16; + ivsize = 16; + mode = WD_CIPHER_CBC; + alg = WD_CIPHER_SM4; + break; + case SM4_128_CTR: + keysize = 16; + ivsize = 16; + mode = WD_CIPHER_CTR; + alg = WD_CIPHER_SM4; + break; + case SM4_128_OFB: + keysize = 16; + ivsize = 16; + mode = WD_CIPHER_OFB; + alg = WD_CIPHER_SM4; + break; + case SM4_128_CFB: + keysize = 16; + ivsize = 16; + mode = WD_CIPHER_CFB; + alg = WD_CIPHER_SM4; + break; + case SM4_128_XTS: + keysize = 32; + ivsize = 16; + mode = WD_CIPHER_XTS; + alg = WD_CIPHER_SM4; + break; + case AES_128_CCM: + keysize = 16; + ivsize = 16; + mode = WD_CIPHER_CCM; + alg = WD_CIPHER_AES; + break; + case AES_192_CCM: + keysize = 24; + ivsize = 16; + mode = WD_CIPHER_CCM; + alg = WD_CIPHER_AES; + break; + case AES_256_CCM: + keysize = 32; + ivsize = 16; + mode = WD_CIPHER_CCM; + alg = WD_CIPHER_AES; + break; + case AES_128_GCM: + keysize = 16; + ivsize = 12; + mode = WD_CIPHER_GCM; + alg = WD_CIPHER_AES; + break; + case AES_192_GCM: + keysize = 24; + ivsize = 12; + mode = WD_CIPHER_GCM; + alg = WD_CIPHER_AES; + break; + case AES_256_GCM: + keysize = 32; + ivsize = 12; + mode = WD_CIPHER_GCM; + alg = WD_CIPHER_AES; + break; + case SM4_128_CCM: + keysize = 16; + ivsize = 16; + mode = WD_CIPHER_CCM; + alg = WD_CIPHER_SM4; + break; + case SM4_128_GCM: + keysize = 16; + ivsize = 12; + mode = WD_CIPHER_GCM; + alg = WD_CIPHER_SM4; + break; + case SM3_ALG: // digest mode is optype + keysize = 4; + mode = optype; + alg = WD_DIGEST_SM3; + break; + case MD5_ALG: + keysize = 4; + mode = optype; + alg = WD_DIGEST_MD5; + break; + case SHA1_ALG: + keysize = 4; + mode = optype; + alg = WD_DIGEST_SHA1; + break; + case SHA256_ALG: + keysize = 4; + mode = optype; + alg = WD_DIGEST_SHA256; + break; + case SHA224_ALG: + keysize = 4; + mode = optype; + alg = WD_DIGEST_SHA224; + break; + case SHA384_ALG: + keysize = 4; + mode = optype; + alg = WD_DIGEST_SHA384; + break; + case SHA512_ALG: + keysize = 4; + mode = optype; + alg = WD_DIGEST_SHA512; + break; + case SHA512_224: + keysize = 4; + mode = optype; + alg = WD_DIGEST_SHA512_224; + break; + case SHA512_256: + keysize = 4; + mode = optype; + alg = WD_DIGEST_SHA512_256; + break; + default: + SEC_TST_PRT("Fail to set sec alg\n"); + return -EINVAL; + } + + tddata->alg = alg; + tddata->mode = mode; + tddata->ivsize = ivsize; + tddata->keysize = keysize; + tddata->optype = options->optype; + tddata->subtype = options->subtype; + + return 0; +} + +static int init_ctx_config(char *alg, int subtype, int mode) +{ + struct uacce_dev_list *list; + struct sched_params param; + int i, max_node; + int ret = 0; + + max_node = numa_max_node() + 1; + if (max_node <= 0) + return -EINVAL; + + list = wd_get_accel_list(alg); + if (!list) { + SEC_TST_PRT("Fail to get %s device\n", alg); + return -ENODEV; + } + memset(&g_ctx_cfg, 0, sizeof(struct wd_ctx_config)); + g_ctx_cfg.ctx_num = g_ctxnum; + g_ctx_cfg.ctxs = calloc(g_ctxnum, sizeof(struct wd_ctx)); + if (!g_ctx_cfg.ctxs) + return -ENOMEM; + + for (i = 0; i < g_ctxnum; i++) { + g_ctx_cfg.ctxs[i].ctx = wd_request_ctx(list->dev); + g_ctx_cfg.ctxs[i].op_type = 0; // default op_type + g_ctx_cfg.ctxs[i].ctx_mode = (__u8)mode; + } + + switch(subtype) { + case CIPHER_TYPE: + g_sched = wd_sched_rr_alloc(SCHED_POLICY_RR, 1, max_node, wd_cipher_poll_ctx); + break; + case AEAD_TYPE: + g_sched = wd_sched_rr_alloc(SCHED_POLICY_RR, 1, max_node, wd_aead_poll_ctx); + break; + case DIGEST_TYPE: + g_sched = wd_sched_rr_alloc(SCHED_POLICY_RR, 1, max_node, wd_digest_poll_ctx); + break; + default: + SEC_TST_PRT("Fail to parse alg subtype!\n"); + goto out; + } + if (!g_sched) { + SEC_TST_PRT("Fail to alloc sched!\n"); + goto out; + } + + /* If there is no numa, we defualt config to zero */ + if (list->dev->numa_id < 0) + list->dev->numa_id = 0; + + g_sched->name = SCHED_SINGLE; + param.numa_id = list->dev->numa_id; + param.type = 0; + param.mode = mode; + param.begin = 0; + param.end = g_ctxnum - 1; + ret = wd_sched_rr_instance(g_sched, ¶m); + if (ret) { + SEC_TST_PRT("Fail to fill sched data!\n"); + goto out; + } + + /* init */ + switch(subtype) { + case CIPHER_TYPE: + ret = wd_cipher_init(&g_ctx_cfg, g_sched); + break; + case AEAD_TYPE: + ret = wd_aead_init(&g_ctx_cfg, g_sched); + break; + case DIGEST_TYPE: + ret = wd_digest_init(&g_ctx_cfg, g_sched); + break; + default: + goto out; + } + if (ret) { + SEC_TST_PRT("Fail to cipher ctx!\n"); + goto out; + } + + wd_free_list_accels(list); + + return 0; +out: + free(g_ctx_cfg.ctxs); + wd_sched_rr_release(g_sched); + + return ret; +} + +static void uninit_ctx_config(int subtype) +{ + int i; + + /* uninit */ + switch(subtype) { + case CIPHER_TYPE: + wd_cipher_uninit(); + break; + case AEAD_TYPE: + wd_aead_uninit(); + break; + case DIGEST_TYPE: + wd_digest_uninit(); + break; + default: + SEC_TST_PRT("Fail to parse alg subtype on uninit!\n"); + return; + } + + for (i = 0; i < g_ctx_cfg.ctx_num; i++) + wd_release_ctx(g_ctx_cfg.ctxs[i].ctx); + free(g_ctx_cfg.ctxs); + wd_sched_rr_release(g_sched); +} + +static int init_uadk_bd_pool(void) +{ + unsigned long step; + int i, j; + + // make the block not align to 4K + step = sizeof(char) * g_pktlen * 2; + + g_uadk_pool.iv = malloc(g_thread_num * MAX_IVK_LENTH * sizeof(char)); + g_uadk_pool.key = malloc(g_thread_num * MAX_IVK_LENTH * sizeof(char)); + g_uadk_pool.mac = malloc(g_thread_num * MAX_IVK_LENTH * sizeof(char)); + + g_uadk_pool.pool = malloc(g_thread_num * sizeof(struct bd_pool)); + if (!g_uadk_pool.pool) { + SEC_TST_PRT("init uadk pool alloc thread failed!\n"); + return -ENOMEM; + } else { + for (i = 0; i < g_thread_num; i++) { + g_uadk_pool.pool[i].bds = malloc(MAX_POOL_LENTH * + sizeof(struct uadk_bd)); + if (!g_uadk_pool.pool[i].bds) { + SEC_TST_PRT("init uadk bds alloc failed!\n"); + goto malloc_error1; + } + for (j = 0; j < MAX_POOL_LENTH; j++) { + g_uadk_pool.pool[i].bds[j].src = malloc(step); + if (!g_uadk_pool.pool[i].bds[j].src) + goto malloc_error2; + g_uadk_pool.pool[i].bds[j].dst = malloc(step); + if (!g_uadk_pool.pool[i].bds[j].dst) + goto malloc_error3; + + get_rand_data(g_uadk_pool.pool[i].bds[j].src, g_pktlen); + if (g_prefetch) + get_rand_data(g_uadk_pool.pool[i].bds[j].dst, g_pktlen); + } + } + } + + return 0; + +malloc_error3: + free(g_uadk_pool.pool[i].bds[j].src); +malloc_error2: + for (j--; j >= 0; j--) { + free(g_uadk_pool.pool[i].bds[j].src); + free(g_uadk_pool.pool[i].bds[j].dst); + } +malloc_error1: + for (i--; i >= 0; i--) { + for (j = 0; j < MAX_POOL_LENTH; j++) { + free(g_uadk_pool.pool[i].bds[j].src); + free(g_uadk_pool.pool[i].bds[j].dst); + } + free(g_uadk_pool.pool[i].bds); + g_uadk_pool.pool[i].bds = NULL; + } + free(g_uadk_pool.pool); + g_uadk_pool.pool = NULL; + + free(g_uadk_pool.iv); + free(g_uadk_pool.key); + free(g_uadk_pool.mac); + + SEC_TST_PRT("init uadk bd pool alloc failed!\n"); + return -ENOMEM; +} + +static void free_uadk_bd_pool(void) +{ + int i, j; + + for (i = 0; i < g_thread_num; i++) { + if (g_uadk_pool.pool[i].bds) { + for (j = 0; j < MAX_POOL_LENTH; j++) { + free(g_uadk_pool.pool[i].bds[j].src); + free(g_uadk_pool.pool[i].bds[j].dst); + } + } + free(g_uadk_pool.pool[i].bds); + g_uadk_pool.pool[i].bds = NULL; + } + free(g_uadk_pool.pool); + g_uadk_pool.pool = NULL; + + free(g_uadk_pool.iv); + free(g_uadk_pool.key); + free(g_uadk_pool.mac); +} + +/*-------------------------------uadk benchmark main code-------------------------------------*/ + +static void *sec_uadk_poll(void *data) +{ + typedef int (*poll_ctx)(__u32 idx, __u32 expt, __u32 *count); + poll_ctx uadk_poll_ctx = NULL; + thread_data *pdata = (thread_data *)data; + u32 expt = ACC_QUEUE_SIZE * g_thread_num; + u32 id = pdata->td_id; + u32 last_time = 2; // poll need one more recv time + u32 count = 0; + u32 recv = 0; + int ret; + + if (id > g_ctxnum) + return NULL; + + switch(pdata->subtype) { + case CIPHER_TYPE: + uadk_poll_ctx = wd_cipher_poll_ctx; + break; + case AEAD_TYPE: + uadk_poll_ctx = wd_aead_poll_ctx; + break; + case DIGEST_TYPE: + uadk_poll_ctx = wd_digest_poll_ctx; + break; + default: + SEC_TST_PRT("<<<<<td_id > g_thread_num) + return NULL; + + uadk_pool = &g_uadk_pool.pool[pdata->td_id]; + priv_iv = &g_uadk_pool.iv[pdata->td_id]; + priv_key = &g_uadk_pool.key[pdata->td_id]; + priv_mac = &g_uadk_pool.mac[pdata->td_id]; + + memset(priv_iv, DEF_IVK_DATA, MAX_IVK_LENTH); + memset(priv_key, DEF_IVK_DATA, MAX_IVK_LENTH); + + switch(pdata->subtype) { + case CIPHER_TYPE: + cipher_setup.alg = pdata->alg; + cipher_setup.mode = pdata->mode; + h_sess = wd_cipher_alloc_sess(&cipher_setup); + if (!h_sess) + return NULL; + ret = wd_cipher_set_key(h_sess, (const __u8*)priv_key, pdata->keysize); + if (ret) { + SEC_TST_PRT("test sec cipher set key is failed!\n"); + wd_cipher_free_sess(h_sess); + return NULL; + } + + creq.op_type = pdata->optype; + creq.iv = priv_iv; + creq.iv_bytes = pdata->ivsize; + creq.in_bytes = g_pktlen; + creq.out_bytes = g_pktlen; + creq.out_buf_bytes = g_pktlen; + creq.data_fmt = 0; + creq.state = 0; + creq.cb = cipher_async_cb; + + while(1) { + if (get_run_state() == 0) + break; + try_cnt = 0; + i = count % MAX_POOL_LENTH; + creq.src = uadk_pool->bds[i].src; + creq.dst = uadk_pool->bds[i].dst; + + ret = wd_do_cipher_async(h_sess, &creq); + if (ret < 0) { + usleep(SEND_USLEEP * try_cnt); + try_cnt++; + if (try_cnt > MAX_TRY_CNT) { + SEC_TST_PRT("Test cipher send fail %d times!\n", MAX_TRY_CNT); + try_cnt = 0; + } + continue; + } + count++; + } + wd_cipher_free_sess(h_sess); + break; + case AEAD_TYPE: // just ccm and gcm + aead_setup.calg = pdata->alg; + aead_setup.cmode = pdata->mode; + h_sess = wd_aead_alloc_sess(&aead_setup); + if (!h_sess) + return NULL; + ret = wd_aead_set_ckey(h_sess, (const __u8*)priv_key, pdata->keysize); + if (ret) { + SEC_TST_PRT("test sec cipher set key is failed!\n"); + wd_aead_free_sess(h_sess); + return NULL; + } + ret = wd_aead_set_authsize(h_sess, auth_size); + if (ret) { + SEC_TST_PRT("set auth size fail, authsize: 16\n"); + wd_aead_free_sess(h_sess); + return NULL; + } + + areq.op_type = pdata->optype; + areq.iv = priv_iv; // aead IV need update with param + areq.mac = priv_mac; + areq.iv_bytes = pdata->ivsize; + areq.mac_bytes = auth_size; + areq.assoc_bytes = 16; + areq.in_bytes = g_pktlen; + if (areq.op_type)// decrypto + areq.out_bytes = g_pktlen + 16; // aadsize = 16; + else + areq.out_bytes = g_pktlen + 32; // aadsize + authsize = 32; + + areq.data_fmt = 0; + areq.state = 0; + areq.cb = aead_async_cb; + + while(1) { + if (get_run_state() == 0) + break; + try_cnt = 0; + i = count % MAX_POOL_LENTH; + areq.src = uadk_pool->bds[i].src; + areq.dst = uadk_pool->bds[i].dst; + + ret = wd_do_aead_async(h_sess, &areq); + if (ret < 0) { + usleep(SEND_USLEEP * try_cnt); + try_cnt++; + if (try_cnt > MAX_TRY_CNT) { + SEC_TST_PRT("Test aead send fail %d times!\n", MAX_TRY_CNT); + try_cnt = 0; + } + continue; + } + count++; + } + wd_aead_free_sess(h_sess); + break; + case DIGEST_TYPE: + digest_setup.alg = pdata->alg; + digest_setup.mode = pdata->mode; // digest mode is optype + h_sess = wd_digest_alloc_sess(&digest_setup); + if (!h_sess) + return NULL; + if (digest_setup.mode == WD_DIGEST_HMAC) { + ret = wd_digest_set_key(h_sess, (const __u8*)priv_key, 4); + if (ret) { + SEC_TST_PRT("test sec digest set key is failed!\n"); + wd_digest_free_sess(h_sess); + return NULL; + } + } + dreq.in_bytes = g_pktlen; + dreq.out_bytes = 16; + dreq.out_buf_bytes = 16; + dreq.data_fmt = 0; + dreq.state = 0; + dreq.has_next = 0; + dreq.cb = digest_async_cb; + + while(1) { + if (get_run_state() == 0) + break; + try_cnt = 0; + i = count % MAX_POOL_LENTH; + dreq.in = uadk_pool->bds[i].src; + dreq.out = uadk_pool->bds[i].dst; + + ret = wd_do_digest_async(h_sess, &dreq); + if (ret < 0) { + usleep(SEND_USLEEP * try_cnt); + try_cnt++; + if (try_cnt > MAX_TRY_CNT) { + SEC_TST_PRT("Test digest send fail %d times!\n", MAX_TRY_CNT); + try_cnt = 0; + } + continue; + } + count++; + } + wd_digest_free_sess(h_sess); + break; + } + + add_send_complete(); + + return NULL; +} + +static void *sec_uadk_sync_run(void *arg) +{ + thread_data *pdata = (thread_data *)arg; + struct wd_cipher_sess_setup cipher_setup = {0}; + struct wd_aead_sess_setup aead_setup = {0}; + struct wd_digest_sess_setup digest_setup = {0}; + struct wd_cipher_req creq; + struct wd_aead_req areq; + struct wd_digest_req dreq; + struct bd_pool *uadk_pool; + u8 *priv_iv, *priv_key, *priv_mac; + handle_t h_sess; + u32 auth_size = 16; + u32 count = 0; + int ret, i = 0; + + if (pdata->td_id > g_thread_num) + return NULL; + + uadk_pool = &g_uadk_pool.pool[pdata->td_id]; + priv_iv = &g_uadk_pool.iv[pdata->td_id]; + priv_key = &g_uadk_pool.key[pdata->td_id]; + priv_mac = &g_uadk_pool.mac[pdata->td_id]; + + memset(priv_iv, DEF_IVK_DATA, MAX_IVK_LENTH); + memset(priv_key, DEF_IVK_DATA, MAX_IVK_LENTH); + + switch(pdata->subtype) { + case CIPHER_TYPE: + cipher_setup.alg = pdata->alg; + cipher_setup.mode = pdata->mode; + h_sess = wd_cipher_alloc_sess(&cipher_setup); + if (!h_sess) + return NULL; + ret = wd_cipher_set_key(h_sess, (const __u8*)priv_key, pdata->keysize); + if (ret) { + SEC_TST_PRT("test sec cipher set key is failed!\n"); + wd_cipher_free_sess(h_sess); + return NULL; + } + + creq.op_type = pdata->optype; + creq.iv = priv_iv; + creq.iv_bytes = pdata->ivsize; + creq.in_bytes = g_pktlen; + creq.out_bytes = g_pktlen; + creq.out_buf_bytes = g_pktlen; + creq.data_fmt = 0; + creq.state = 0; + + while(1) { + i = count % MAX_POOL_LENTH; + creq.src = uadk_pool->bds[i].src; + creq.dst = uadk_pool->bds[i].dst; + ret = wd_do_cipher_sync(h_sess, &creq); + if ((ret < 0 && ret != -WD_EBUSY) || creq.state) + break; + count++; + if (get_run_state() == 0) + break; + } + wd_cipher_free_sess(h_sess); + break; + case AEAD_TYPE: // just ccm and gcm + aead_setup.calg = pdata->alg; + aead_setup.cmode = pdata->mode; + h_sess = wd_aead_alloc_sess(&aead_setup); + if (!h_sess) + return NULL; + ret = wd_aead_set_ckey(h_sess, (const __u8*)priv_key, pdata->keysize); + if (ret) { + SEC_TST_PRT("test sec cipher set key is failed!\n"); + wd_aead_free_sess(h_sess); + return NULL; + } + ret = wd_aead_set_authsize(h_sess, auth_size); + if (ret) { + SEC_TST_PRT("set auth size fail, authsize: 16\n"); + wd_aead_free_sess(h_sess); + return NULL; + } + + areq.op_type = pdata->optype; + areq.iv = priv_iv; // aead IV need update with param + areq.mac = priv_mac; + areq.mac_bytes = 16; + areq.iv_bytes = pdata->ivsize; + areq.assoc_bytes = 16; + areq.in_bytes = g_pktlen; + areq.mac_bytes = auth_size; + if (areq.op_type)// decrypto + areq.out_bytes = g_pktlen + 16; // aadsize = 16; + else + areq.out_bytes = g_pktlen + 32; // aadsize + authsize = 32; + + areq.data_fmt = 0; + areq.state = 0; + + while(1) { + i = count % MAX_POOL_LENTH; + areq.src = uadk_pool->bds[i].src; + areq.dst = uadk_pool->bds[i].dst; + count++; + ret = wd_do_aead_sync(h_sess, &areq); + if (ret || areq.state) + break; + if (get_run_state() == 0) + break; + } + wd_aead_free_sess(h_sess); + break; + case DIGEST_TYPE: + digest_setup.alg = pdata->alg; + digest_setup.mode = pdata->mode; // digest mode is optype + h_sess = wd_digest_alloc_sess(&digest_setup); + if (!h_sess) + return NULL; + if (digest_setup.mode == WD_DIGEST_HMAC) { + ret = wd_digest_set_key(h_sess, (const __u8*)priv_key, 4); + if (ret) { + SEC_TST_PRT("test sec digest set key is failed!\n"); + wd_digest_free_sess(h_sess); + return NULL; + } + } + dreq.in_bytes = g_pktlen; + dreq.out_bytes = 16; + dreq.out_buf_bytes = 16; + dreq.data_fmt = 0; + dreq.state = 0; + dreq.has_next = 0; + + while(1) { + i = count % MAX_POOL_LENTH; + dreq.in = uadk_pool->bds[i].src; + dreq.out = uadk_pool->bds[i].dst; + ret = wd_do_digest_sync(h_sess, &dreq); + if (ret || dreq.state) + break; + count++; + if (get_run_state() == 0) + break; + } + wd_digest_free_sess(h_sess); + break; + } + + add_recv_data(count, g_pktlen); + + return NULL; +} + +int sec_uadk_sync_threads(struct acc_option *options) +{ + thread_data threads_args[THREADS_NUM]; + thread_data threads_option; + pthread_t tdid[THREADS_NUM]; + int i, ret; + + /* alg param parse and set to thread data */ + ret = sec_uadk_param_parse(&threads_option, options); + if (ret) + return ret; + + for (i = 0; i < g_thread_num; i++) { + threads_args[i].subtype = threads_option.subtype; + threads_args[i].alg = threads_option.alg; + threads_args[i].mode = threads_option.mode; + threads_args[i].keysize = threads_option.keysize; + threads_args[i].ivsize = threads_option.ivsize; + threads_args[i].optype = threads_option.optype; + threads_args[i].td_id = i; + ret = pthread_create(&tdid[i], NULL, sec_uadk_sync_run, &threads_args[i]); + if (ret) { + SEC_TST_PRT("Create sync thread fail!\n"); + goto sync_error; + } + } + + /* join thread */ + for (i = 0; i < g_thread_num; i++) { + ret = pthread_join(tdid[i], NULL); + if (ret) { + SEC_TST_PRT("Join sync thread fail!\n"); + goto sync_error; + } + } + +sync_error: + return ret; +} + +int sec_uadk_async_threads(struct acc_option *options) +{ + thread_data threads_args[THREADS_NUM]; + thread_data threads_option; + pthread_t tdid[THREADS_NUM]; + pthread_t pollid[THREADS_NUM]; + int i, ret; + + /* alg param parse and set to thread data */ + ret = sec_uadk_param_parse(&threads_option, options); + if (ret) + return ret; + + for (i = 0; i < g_ctxnum; i++) { + threads_args[i].subtype = threads_option.subtype; + threads_args[i].td_id = i; + /* poll thread */ + ret = pthread_create(&pollid[i], NULL, sec_uadk_poll, &threads_args[i]); + if (ret) { + SEC_TST_PRT("Create poll thread fail!\n"); + goto async_error; + } + } + + for (i = 0; i < g_thread_num; i++) { + threads_args[i].subtype = threads_option.subtype; + threads_args[i].alg = threads_option.alg; + threads_args[i].mode = threads_option.mode; + threads_args[i].keysize = threads_option.keysize; + threads_args[i].ivsize = threads_option.ivsize; + threads_args[i].optype = threads_option.optype; + threads_args[i].td_id = i; + ret = pthread_create(&tdid[i], NULL, sec_uadk_async_run, &threads_args[i]); + if (ret) { + SEC_TST_PRT("Create async thread fail!\n"); + goto async_error; + } + } + + /* join thread */ + for (i = 0; i < g_thread_num; i++) { + ret = pthread_join(tdid[i], NULL); + if (ret) { + SEC_TST_PRT("Join async thread fail!\n"); + goto async_error; + } + } + + for (i = 0; i < g_ctxnum; i++) { + ret = pthread_join(pollid[i], NULL); + if (ret) { + SEC_TST_PRT("Join poll thread fail!\n"); + goto async_error; + } + } + +async_error: + return ret; +} + +int sec_uadk_benchmark(struct acc_option *options) +{ + u32 ptime; + int ret; + + g_thread_num = options->threads; + g_pktlen = options->pktlen; + g_ctxnum = options->ctxnums; + g_prefetch = options->prefetch; + if (options->optype > WD_CIPHER_DECRYPTION) { + SEC_TST_PRT("SEC optype error: %u\n", options->optype); + return -EINVAL; + } + + ret = init_ctx_config(options->algclass, options->subtype, options->syncmode); + if (ret) + return ret; + + ret = init_uadk_bd_pool(); + if (ret) + return ret; + + get_pid_cpu_time(&ptime); + time_start(options->times); + if (options->syncmode) + ret = sec_uadk_async_threads(options); + else + ret = sec_uadk_sync_threads(options); + cal_perfermance_data(options, ptime); + if (ret) + return ret; + + free_uadk_bd_pool(); + uninit_ctx_config(options->subtype); + + return 0; +} diff --git a/uadk/uadk_tool/benchmark/sec_uadk_benchmark.h b/uadk/uadk_tool/benchmark/sec_uadk_benchmark.h new file mode 100644 index 0000000..16cf224 --- /dev/null +++ b/uadk/uadk_tool/benchmark/sec_uadk_benchmark.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +#ifndef SEC_UADK_BENCHMARK_H +#define SEC_UADK_BENCHMARK_H + +extern int sec_uadk_benchmark(struct acc_option *options); +#endif /* SEC_UADK_BENCHMARK_H */ diff --git a/uadk/uadk_tool/benchmark/sec_wd_benchmark.c b/uadk/uadk_tool/benchmark/sec_wd_benchmark.c new file mode 100644 index 0000000..d2da73b --- /dev/null +++ b/uadk/uadk_tool/benchmark/sec_wd_benchmark.c @@ -0,0 +1,1188 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include "uadk_benchmark.h" +#include "sec_wd_benchmark.h" + +#include "v1/wd.h" +#include "v1/wd_cipher.h" +#include "v1/wd_aead.h" +#include "v1/wd_digest.h" +#include "v1/wd_bmm.h" +#include "v1/wd_util.h" + +#define SEC_TST_PRT printf +#define MAX_IVK_LENTH 64 +#define DEF_IVK_DATA 0xAA +#define SQE_SIZE 128 + +typedef struct wd_thread_res { + u32 subtype; + u32 alg; + u32 mode; + u32 keysize; + u32 ivsize; + u32 optype; + u32 td_id; +} thread_data; + +struct thread_bd_res { + struct wd_queue *queue; + void *pool; + void **in; + void **out; + void **iv; +}; + +struct thread_queue_res { + struct thread_bd_res *bd_res; +}; + +struct wcrypto_async_tag { + void *ctx; + int thread_id; + int cnt; +}; + +static struct thread_queue_res g_thread_queue; +static unsigned int g_thread_num; +static unsigned int g_pktlen; + +static void *cipher_async_cb(void *message, void *cipher_tag) +{ + return NULL; +} + +static void *aead_async_cb(void *message, void *cipher_tag) +{ + return NULL; +} + +static void *digest_async_cb(void *message, void *digest_tag) +{ + // struct WCRYPTO_req *req = (struct WCRYPTO_req *)data; + return NULL; +} + +static int sec_wd_param_parse(thread_data *tddata, struct acc_option *options) +{ + u32 algtype = options->algtype; + u32 optype = options->optype; + u8 keysize = 0; + u8 ivsize = 0; + u8 mode; + u8 alg; + + switch(algtype) { + case AES_128_ECB: + keysize = 16; + ivsize = 0; + mode = WCRYPTO_CIPHER_ECB; + alg = WCRYPTO_CIPHER_AES; + break; + case AES_192_ECB: + keysize = 24; + ivsize = 0; + mode = WCRYPTO_CIPHER_ECB; + alg = WCRYPTO_CIPHER_AES; + break; + case AES_256_ECB: + keysize = 32; + ivsize = 0; + mode = WCRYPTO_CIPHER_ECB; + alg = WCRYPTO_CIPHER_AES; + break; + case AES_128_CBC: + keysize = 16; + ivsize = 16; + mode = WCRYPTO_CIPHER_CBC; + alg = WCRYPTO_CIPHER_AES; + break; + case AES_192_CBC: + keysize = 24; + ivsize = 16; + mode = WCRYPTO_CIPHER_CBC; + alg = WCRYPTO_CIPHER_AES; + break; + case AES_256_CBC: + keysize = 32; + ivsize = 16; + mode = WCRYPTO_CIPHER_CBC; + alg = WCRYPTO_CIPHER_AES; + break; + case AES_128_CTR: + keysize = 16; + ivsize = 16; + mode = WCRYPTO_CIPHER_CTR; + alg = WCRYPTO_CIPHER_AES; + break; + case AES_192_CTR: + keysize = 24; + ivsize = 16; + mode = WCRYPTO_CIPHER_CTR; + alg = WCRYPTO_CIPHER_AES; + break; + case AES_256_CTR: + keysize = 32; + ivsize = 16; + mode = WCRYPTO_CIPHER_CTR; + alg = WCRYPTO_CIPHER_AES; + break; + case AES_128_OFB: + keysize = 16; + ivsize = 16; + mode = WCRYPTO_CIPHER_OFB; + alg = WCRYPTO_CIPHER_AES; + break; + case AES_192_OFB: + keysize = 24; + ivsize = 16; + mode = WCRYPTO_CIPHER_OFB; + alg = WCRYPTO_CIPHER_AES; + break; + case AES_256_OFB: + keysize = 32; + ivsize = 16; + mode = WCRYPTO_CIPHER_OFB; + alg = WCRYPTO_CIPHER_AES; + break; + case AES_128_CFB: + keysize = 16; + ivsize = 16; + mode = WCRYPTO_CIPHER_CFB; + alg = WCRYPTO_CIPHER_AES; + break; + case AES_192_CFB: + keysize = 24; + ivsize = 16; + mode = WCRYPTO_CIPHER_CFB; + alg = WCRYPTO_CIPHER_AES; + break; + case AES_256_CFB: + keysize = 32; + ivsize = 16; + mode = WCRYPTO_CIPHER_CFB; + alg = WCRYPTO_CIPHER_AES; + break; + case AES_256_XTS: + keysize = 32; + ivsize = 16; + mode = WCRYPTO_CIPHER_XTS; + alg = WCRYPTO_CIPHER_AES; + break; + case AES_512_XTS: + keysize = 64; + ivsize = 16; + mode = WCRYPTO_CIPHER_XTS; + alg = WCRYPTO_CIPHER_AES; + break; + case DES3_128_ECB: + keysize = 16; + ivsize = 0; + mode = WCRYPTO_CIPHER_ECB; + alg = WCRYPTO_CIPHER_3DES; + break; + case DES3_192_ECB: + keysize = 24; + ivsize = 0; + mode = WCRYPTO_CIPHER_ECB; + alg = WCRYPTO_CIPHER_3DES; + break; + case DES3_128_CBC: + keysize = 16; + ivsize = 8; + mode = WCRYPTO_CIPHER_CBC; + alg = WCRYPTO_CIPHER_3DES; + break; + case DES3_192_CBC: + keysize = 24; + ivsize = 8; + mode = WCRYPTO_CIPHER_CBC; + alg = WCRYPTO_CIPHER_3DES; + break; + case SM4_128_ECB: + keysize = 16; + ivsize = 0; + mode = WCRYPTO_CIPHER_ECB; + alg = WCRYPTO_CIPHER_SM4; + break; + case SM4_128_CBC: + keysize = 16; + ivsize = 16; + mode = WCRYPTO_CIPHER_CBC; + alg = WCRYPTO_CIPHER_SM4; + break; + case SM4_128_CTR: + keysize = 16; + ivsize = 16; + mode = WCRYPTO_CIPHER_CTR; + alg = WCRYPTO_CIPHER_SM4; + break; + case SM4_128_OFB: + keysize = 16; + ivsize = 16; + mode = WCRYPTO_CIPHER_OFB; + alg = WCRYPTO_CIPHER_SM4; + break; + case SM4_128_CFB: + keysize = 16; + ivsize = 16; + mode = WCRYPTO_CIPHER_CFB; + alg = WCRYPTO_CIPHER_SM4; + break; + case SM4_128_XTS: + keysize = 32; + ivsize = 16; + mode = WCRYPTO_CIPHER_XTS; + alg = WCRYPTO_CIPHER_SM4; + break; + case AES_128_CCM: + keysize = 16; + ivsize = 16; + mode = WCRYPTO_CIPHER_CCM; + alg = WCRYPTO_CIPHER_AES; + break; + case AES_192_CCM: + keysize = 24; + ivsize = 16; + mode = WCRYPTO_CIPHER_CCM; + alg = WCRYPTO_CIPHER_AES; + break; + case AES_256_CCM: + keysize = 32; + ivsize = 16; + mode = WCRYPTO_CIPHER_CCM; + alg = WCRYPTO_CIPHER_AES; + break; + case AES_128_GCM: + keysize = 16; + ivsize = 12; + mode = WCRYPTO_CIPHER_GCM; + alg = WCRYPTO_CIPHER_AES; + break; + case AES_192_GCM: + keysize = 24; + ivsize = 12; + mode = WCRYPTO_CIPHER_GCM; + alg = WCRYPTO_CIPHER_AES; + break; + case AES_256_GCM: + keysize = 32; + ivsize = 12; + mode = WCRYPTO_CIPHER_GCM; + alg = WCRYPTO_CIPHER_AES; + break; + case SM4_128_CCM: + keysize = 16; + ivsize = 16; + mode = WCRYPTO_CIPHER_CCM; + alg = WCRYPTO_CIPHER_SM4; + break; + case SM4_128_GCM: + keysize = 16; + ivsize = 12; + mode = WCRYPTO_CIPHER_GCM; + alg = WCRYPTO_CIPHER_SM4; + break; + case SM3_ALG: // digest mode is optype + keysize = 4; + mode = optype; + alg = WCRYPTO_SM3; + break; + case MD5_ALG: + keysize = 4; + mode = optype; + alg = WCRYPTO_MD5; + break; + case SHA1_ALG: + keysize = 4; + mode = optype; + alg = WCRYPTO_SHA1; + break; + case SHA256_ALG: + keysize = 4; + mode = optype; + alg = WCRYPTO_SHA256; + break; + case SHA224_ALG: + keysize = 4; + mode = optype; + alg = WCRYPTO_SHA224; + break; + case SHA384_ALG: + keysize = 4; + mode = optype; + alg = WCRYPTO_SHA384; + break; + case SHA512_ALG: + keysize = 4; + mode = optype; + alg = WCRYPTO_SHA512; + break; + case SHA512_224: + keysize = 4; + mode = optype; + alg = WCRYPTO_SHA512_224; + break; + case SHA512_256: + keysize = 4; + mode = optype; + alg = WCRYPTO_SHA512_256; + break; + default: + SEC_TST_PRT("Fail to set sec alg\n"); + return -EINVAL; + } + + tddata->alg = alg; + tddata->mode = mode; + tddata->ivsize = ivsize; + tddata->keysize = keysize; + tddata->optype = options->optype; + tddata->subtype = options->subtype; + + return 0; +} + +static int init_wd_queue(struct acc_option *options) +{ + struct wd_blkpool_setup blksetup; + int i, j, m, n, k, idx, ret; + + g_thread_queue.bd_res = malloc(g_thread_num * sizeof(struct thread_bd_res)); + if (!g_thread_queue.bd_res) { + SEC_TST_PRT("malloc thread res memory fail!\n"); + return -ENOMEM; + } + + for (i = 0; i < g_thread_num; i++) { + g_thread_queue.bd_res[i].queue = malloc(sizeof(struct wd_queue)); + g_thread_queue.bd_res[i].queue->capa.alg = options->algclass; + // 0 is ENC, 1 is DEC + g_thread_queue.bd_res[i].queue->capa.priv.direction = options->optype; + /* nodemask need to be clean */ + g_thread_queue.bd_res[i].queue->node_mask = 0x0; + memset(g_thread_queue.bd_res[i].queue->dev_path, 0x0, PATH_STR_SIZE); + + ret = wd_request_queue(g_thread_queue.bd_res[i].queue); + if (ret) { + SEC_TST_PRT("request queue %d fail!\n", i); + goto queue_out; + } + } + + // use no-sva pbuffer + memset(&blksetup, 0, sizeof(blksetup)); + blksetup.block_size = g_pktlen + SQE_SIZE; //aead need mac and aad out + blksetup.block_num = MAX_BLOCK_NM; //set pool inv + key + in + out + blksetup.align_size = SQE_SIZE; + // SEC_TST_PRT("create pool memory: %d KB\n", (MAX_BLOCK_NM * blksetup.block_size) >> 10); + + for (j = 0; j < g_thread_num; j++) { + g_thread_queue.bd_res[j].pool = wd_blkpool_create(g_thread_queue.bd_res[j].queue, &blksetup); + if (!g_thread_queue.bd_res[j].pool) { + SEC_TST_PRT("create %dth pool fail!\n", j); + ret = -ENOMEM; + goto pool_err; + } + } + + // alloc in pbuffer res + for (m = 0; m < g_thread_num; m++) { + g_thread_queue.bd_res[m].in = malloc(MAX_POOL_LENTH * sizeof(void *)); + for (idx = 0; idx < MAX_POOL_LENTH; idx++) { + g_thread_queue.bd_res[m].in[idx] = wd_alloc_blk(g_thread_queue.bd_res[m].pool); + if (!g_thread_queue.bd_res[m].in[idx]) { + SEC_TST_PRT("create pool %dth in memory fail!\n", m); + for (idx--; idx >= 0; idx--) + wd_free_blk(g_thread_queue.bd_res[m].pool, + g_thread_queue.bd_res[m].in[idx]); + ret = -ENOMEM; + goto in_err; + } + } + } + + // alloc out pbuffer res + for (n = 0; n < g_thread_num; n++) { + g_thread_queue.bd_res[n].out = malloc(MAX_POOL_LENTH * sizeof(void *)); + for (idx = 0; idx < MAX_POOL_LENTH; idx++) { + g_thread_queue.bd_res[n].out[idx] = wd_alloc_blk(g_thread_queue.bd_res[n].pool); + if (!g_thread_queue.bd_res[n].out[idx]) { + SEC_TST_PRT("create pool %dth out memory fail!\n", n); + for (idx--; idx >= 0; idx--) + wd_free_blk(g_thread_queue.bd_res[n].pool, + g_thread_queue.bd_res[n].out[idx]); + ret = -ENOMEM; + goto out_err; + } + } + } + + // alloc iv pbuffer res + for (k = 0; k < g_thread_num; k++) { + g_thread_queue.bd_res[k].iv = malloc(MAX_POOL_LENTH * sizeof(void *)); + for (idx = 0; idx < MAX_POOL_LENTH; idx++) { + g_thread_queue.bd_res[k].iv[idx] = wd_alloc_blk(g_thread_queue.bd_res[k].pool); + if (!g_thread_queue.bd_res[k].iv[idx]) { + SEC_TST_PRT("create pool %dth iv memory fail!\n", k); + for (idx--; idx >= 0; idx--) + wd_free_blk(g_thread_queue.bd_res[k].pool, + g_thread_queue.bd_res[k].iv[idx]); + ret = -ENOMEM; + goto iv_err; + } + memset(g_thread_queue.bd_res[k].iv[idx], DEF_IVK_DATA, MAX_IVK_LENTH); + } + } + + return 0; + +iv_err: + for (k--; k >= 0; k--) { + for (idx = 0; idx < MAX_POOL_LENTH; idx++) + wd_free_blk(g_thread_queue.bd_res[k].pool, + g_thread_queue.bd_res[k].iv[idx]); + free(g_thread_queue.bd_res[k].iv); + } +out_err: + for (n--; n >= 0; n--) { + for (idx = 0; idx < MAX_POOL_LENTH; idx++) + wd_free_blk(g_thread_queue.bd_res[n].pool, + g_thread_queue.bd_res[n].out[idx]); + free(g_thread_queue.bd_res[n].out); + } +in_err: + for (m--; m >= 0; m--) { + for (idx = 0; idx < MAX_POOL_LENTH; idx++) + wd_free_blk(g_thread_queue.bd_res[m].pool, + g_thread_queue.bd_res[m].in[idx]); + free(g_thread_queue.bd_res[m].in); + } +pool_err: + for (j--; j >= 0; j--) + wd_blkpool_destroy(g_thread_queue.bd_res[j].pool); +queue_out: + for (i--; i >= 0; i--) { + wd_release_queue(g_thread_queue.bd_res[i].queue); + free(g_thread_queue.bd_res[i].queue); + } + free(g_thread_queue.bd_res); + return ret; +} + +static void uninit_wd_queue(void) +{ + int i, j, idx; + + for (i = 0; i < g_thread_num; i++) { + for (idx = 0; idx < MAX_POOL_LENTH; idx++) { + wd_free_blk(g_thread_queue.bd_res[i].pool, g_thread_queue.bd_res[i].iv[idx]); + wd_free_blk(g_thread_queue.bd_res[i].pool, g_thread_queue.bd_res[i].in[idx]); + wd_free_blk(g_thread_queue.bd_res[i].pool, g_thread_queue.bd_res[i].out[idx]); + } + free(g_thread_queue.bd_res[i].in); + free(g_thread_queue.bd_res[i].out); + free(g_thread_queue.bd_res[i].iv); + } + + for (j = 0; j < g_thread_num; j++) { + wd_blkpool_destroy(g_thread_queue.bd_res[j].pool); + wd_release_queue(g_thread_queue.bd_res[j].queue); + } + + free(g_thread_queue.bd_res); +} + +/*-------------------------------uadk benchmark main code-------------------------------------*/ + +void *sec_wd_poll(void *data) +{ + typedef int (*poll_ctx)(struct wd_queue *q, unsigned int num); + thread_data *pdata = (thread_data *)data; + poll_ctx wd_poll_ctx = NULL; + u32 expt = ACC_QUEUE_SIZE * g_thread_num; + u32 last_time = 2; // poll need one more recv time + u32 id = pdata->td_id; + u32 count = 0; + int recv = 0; + + switch(pdata->subtype) { + case CIPHER_TYPE: + wd_poll_ctx = wcrypto_cipher_poll; + break; + case AEAD_TYPE: + wd_poll_ctx = wcrypto_aead_poll; + break; + case DIGEST_TYPE: + wd_poll_ctx = wcrypto_digest_poll; + break; + default: + SEC_TST_PRT("<<<<< g_thread_num) + return NULL; + + while (last_time) { + recv = wd_poll_ctx(g_thread_queue.bd_res[id].queue, expt); + /* + * async mode poll easy to 100% with small package. + * SEC_TST_PRT("poll %d recv: %u!\n", i, recv); + */ + if (unlikely(recv < 0)) { + SEC_TST_PRT("poll ret: %u!\n", recv); + goto recv_error; + } + count += recv; + recv = 0; + + if (get_run_state() == 0) + last_time--; + } + +recv_error: + add_recv_data(count, g_pktlen); + + return NULL; +} + +static void *sec_wd_async_run(void *arg) +{ + thread_data *pdata = (thread_data *)arg; + struct wcrypto_cipher_ctx_setup cipher_setup = {0}; + struct wcrypto_aead_ctx_setup aead_setup = {0}; + struct wcrypto_digest_ctx_setup digest_setup = {0}; + struct wcrypto_cipher_op_data copdata; + struct wcrypto_aead_op_data aopdata; + struct wcrypto_digest_op_data dopdata; + struct wcrypto_async_tag *tag = NULL; + char priv_key[MAX_IVK_LENTH]; + struct thread_bd_res *bd_res; + struct wd_queue *queue; + void *ctx = NULL; + void **res_in; + void **res_out; + void **res_iv; + u32 count = 0; + int try_cnt = 0; + u32 authsize; + int ret, i = 0; + void *pool; + + if (pdata->td_id > g_thread_num) + return NULL; + + bd_res = &g_thread_queue.bd_res[pdata->td_id]; + queue = bd_res->queue; + pool = bd_res->pool; + res_in = bd_res->in; + res_out = bd_res->out; + res_iv = bd_res->iv; + + memset(priv_key, DEF_IVK_DATA, MAX_IVK_LENTH); + tag = malloc(sizeof(struct wcrypto_async_tag)); // set the user tag + if (!tag) { + SEC_TST_PRT("wcrypto async alloc tag fail!\n"); + return NULL; + } + tag->thread_id = pdata->td_id; + + switch(pdata->subtype) { + case CIPHER_TYPE: + cipher_setup.alg = pdata->alg; + cipher_setup.mode = pdata->mode; + cipher_setup.cb = (void *)cipher_async_cb; + cipher_setup.br.alloc = (void *)wd_alloc_blk; + cipher_setup.br.free = (void *)wd_free_blk; + cipher_setup.br.iova_map = (void *)wd_blk_iova_map; + cipher_setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + cipher_setup.br.get_bufsize = (void *)wd_blksize; + cipher_setup.br.usr = pool; + + ctx = wcrypto_create_cipher_ctx(queue, &cipher_setup); + if (!ctx) { + SEC_TST_PRT("wd create cipher ctx fail!\n"); + return NULL; + } + tag->ctx = ctx; + + ret = wcrypto_set_cipher_key(ctx, (__u8*)priv_key, (__u16)pdata->keysize); + if (ret) { + SEC_TST_PRT("wd cipher set key fail!\n"); + wcrypto_del_cipher_ctx(ctx); + return NULL; + } + + if (queue->capa.priv.direction == 0) + copdata.op_type = WCRYPTO_CIPHER_ENCRYPTION; + else + copdata.op_type = WCRYPTO_CIPHER_DECRYPTION; + + copdata.in_bytes = g_pktlen; + copdata.out_bytes = g_pktlen; + copdata.iv_bytes = pdata->ivsize; + copdata.priv = NULL; + + tag->cnt = 0; + copdata.in = res_in[0]; + copdata.out = res_out[0]; + copdata.iv = res_iv[0]; + usleep(SEND_USLEEP); + while(1) { + if (get_run_state() == 0) + break; + + ret = wcrypto_do_cipher(ctx, &copdata, (void *)tag); + if (ret == -WD_EBUSY) { + usleep(SEND_USLEEP * try_cnt); + try_cnt++; + if (try_cnt > MAX_TRY_CNT) { + SEC_TST_PRT("Test cipher send fail %d times!\n", MAX_TRY_CNT); + try_cnt = 0; + } + continue; + } + + count++; + i = count % MAX_POOL_LENTH; + tag->cnt = i; + try_cnt = 0; + copdata.in = res_in[i]; + copdata.out = res_out[i]; + copdata.iv = res_iv[i]; + } + + break; + case AEAD_TYPE: // just ccm and gcm + aead_setup.calg = pdata->alg; + aead_setup.cmode = pdata->mode; + aead_setup.cb = (void *)aead_async_cb; + aead_setup.br.alloc = (void *)wd_alloc_blk; + aead_setup.br.free = (void *)wd_free_blk; + aead_setup.br.iova_map = (void *)wd_blk_iova_map; + aead_setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + aead_setup.br.get_bufsize = (void *)wd_blksize; + aead_setup.br.usr = pool; + + ctx = wcrypto_create_aead_ctx(queue, &aead_setup); + if (!ctx) { + SEC_TST_PRT("wd create aead ctx fail!\n"); + return NULL; + } + tag->ctx = ctx; + + ret = wcrypto_set_aead_ckey(ctx, (__u8*)priv_key, (__u16)pdata->keysize); + if (ret) { + SEC_TST_PRT("wd aead set key fail!\n"); + wcrypto_del_aead_ctx(ctx); + return NULL; + } + + authsize = 16; //set defaut size + ret = wcrypto_aead_setauthsize(ctx, authsize); + if (ret) { + SEC_TST_PRT("set authsize fail!\n"); + wcrypto_del_aead_ctx(ctx); + return NULL; + } + + if (queue->capa.priv.direction == 0) { + aopdata.op_type = WCRYPTO_CIPHER_ENCRYPTION_DIGEST; + aopdata.out_bytes = g_pktlen + 32; // aad + plen + authsize; + } else { + aopdata.op_type = WCRYPTO_CIPHER_DECRYPTION_DIGEST; + aopdata.out_bytes = g_pktlen + 16; // aad + plen; + } + + aopdata.assoc_size = 16; + aopdata.in_bytes = g_pktlen; + aopdata.out_bytes = g_pktlen; + aopdata.iv_bytes = pdata->ivsize; + aopdata.priv = NULL; + aopdata.out_buf_bytes = g_pktlen * 2; + + tag->cnt = 0; + aopdata.in = res_in[0]; + aopdata.out = res_out[0]; + aopdata.iv = res_iv[0]; + usleep(SEND_USLEEP); + while(1) { + if (get_run_state() == 0) + break; + + ret = wcrypto_do_aead(ctx, &aopdata, (void *)tag); + if (ret == -WD_EBUSY) { + usleep(SEND_USLEEP * try_cnt); + try_cnt++; + if (try_cnt > MAX_TRY_CNT) { + SEC_TST_PRT("Test aead send fail %d times!\n", MAX_TRY_CNT); + try_cnt = 0; + } + continue; + } + + count++; + i = count % MAX_POOL_LENTH; + tag->cnt = i; + try_cnt = 0; + aopdata.in = res_in[i]; + aopdata.out = res_out[i]; + aopdata.iv = res_iv[i]; + } + + break; + case DIGEST_TYPE: + digest_setup.alg = pdata->alg; + digest_setup.mode = pdata->mode; + digest_setup.cb = (void *)digest_async_cb; + digest_setup.br.alloc = (void *)wd_alloc_blk; + digest_setup.br.free = (void *)wd_free_blk; + digest_setup.br.iova_map = (void *)wd_blk_iova_map; + digest_setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + digest_setup.br.get_bufsize = (void *)wd_blksize; + digest_setup.br.usr = pool; + + ctx = wcrypto_create_digest_ctx(queue, &digest_setup); + if (!ctx) { + SEC_TST_PRT("wd create digest ctx fail!\n"); + return NULL; + } + tag->ctx = ctx; + + if (digest_setup.mode == WCRYPTO_DIGEST_HMAC) { + ret = wcrypto_set_digest_key(ctx, (__u8*)priv_key, + (__u16)pdata->keysize); + if (ret) { + SEC_TST_PRT("wd digest set key fail!\n"); + wcrypto_del_digest_ctx(ctx); + return NULL; + } + } + + dopdata.in_bytes = g_pktlen; + dopdata.out_bytes = 16; + dopdata.has_next = 0; + dopdata.priv = NULL; + + tag->cnt = 0; + dopdata.in = res_in[0]; + dopdata.out = res_out[0]; + usleep(SEND_USLEEP); + while(1) { + if (get_run_state() == 0) + break; + + ret = wcrypto_do_digest(ctx, &dopdata, (void *)tag); + if (ret == -WD_EBUSY) { + usleep(SEND_USLEEP * try_cnt); + try_cnt++; + if (try_cnt > MAX_TRY_CNT) { + SEC_TST_PRT("Test digest send fail %d times!\n", MAX_TRY_CNT); + try_cnt = 0; + } + continue; + } + + count++; + i = count % MAX_POOL_LENTH; + tag->cnt = i; + try_cnt = 0; + dopdata.in = res_in[i]; + dopdata.out = res_out[i]; + } + + break; + } + + add_send_complete(); + + while (1) { + if (get_recv_time() > 0) // wait Async mode finish recv + break; + usleep(SEND_USLEEP); + } + + switch(pdata->subtype) { + case CIPHER_TYPE: + wcrypto_del_cipher_ctx(ctx); + break; + case AEAD_TYPE: + wcrypto_del_aead_ctx(ctx); + break; + case DIGEST_TYPE: + wcrypto_del_digest_ctx(ctx); + break; + } + + return NULL; +} + +static void *sec_wd_sync_run(void *arg) +{ + thread_data *pdata = (thread_data *)arg; + struct wcrypto_cipher_ctx_setup cipher_setup = {0}; + struct wcrypto_aead_ctx_setup aead_setup = {0}; + struct wcrypto_digest_ctx_setup digest_setup = {0}; + struct wcrypto_cipher_op_data copdata; + struct wcrypto_aead_op_data aopdata; + struct wcrypto_digest_op_data dopdata; + char priv_key[MAX_IVK_LENTH]; + struct thread_bd_res *bd_res; + struct wd_queue *queue; + void *ctx = NULL; + void *tag = NULL; + void **res_in; + void **res_out; + void **res_iv; + u32 count = 0; + int try_cnt = 0; + u32 authsize; + int ret, i = 0; + void *pool; + + if (pdata->td_id > g_thread_num) + return NULL; + + bd_res = &g_thread_queue.bd_res[pdata->td_id]; + queue = bd_res->queue; + pool = bd_res->pool; + res_in = bd_res->in; + res_out = bd_res->out; + res_iv = bd_res->iv; + + memset(priv_key, DEF_IVK_DATA, MAX_IVK_LENTH); + + switch(pdata->subtype) { + case CIPHER_TYPE: + cipher_setup.alg = pdata->alg; + cipher_setup.mode = pdata->mode; + cipher_setup.br.alloc = (void *)wd_alloc_blk; + cipher_setup.br.free = (void *)wd_free_blk; + cipher_setup.br.iova_map = (void *)wd_blk_iova_map; + cipher_setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + cipher_setup.br.get_bufsize = (void *)wd_blksize; + cipher_setup.br.usr = pool; + + ctx = wcrypto_create_cipher_ctx(queue, &cipher_setup); + if (!ctx) { + SEC_TST_PRT("wd create cipher ctx fail!\n"); + return NULL; + } + + ret = wcrypto_set_cipher_key(ctx, (__u8*)priv_key, (__u16)pdata->keysize); + if (ret) { + SEC_TST_PRT("wd cipher set key fail!\n"); + wcrypto_del_cipher_ctx(ctx); + return NULL; + } + + if (queue->capa.priv.direction == 0) + copdata.op_type = WCRYPTO_CIPHER_ENCRYPTION; + else + copdata.op_type = WCRYPTO_CIPHER_DECRYPTION; + + copdata.in_bytes = g_pktlen; + copdata.out_bytes = g_pktlen; + copdata.iv_bytes = pdata->ivsize; + copdata.priv = NULL; + + copdata.in = res_in[0]; + copdata.out = res_out[0]; + copdata.iv = res_iv[0]; + usleep(SEND_USLEEP); + while(1) { + if (get_run_state() == 0) + break; + + ret = wcrypto_do_cipher(ctx, &copdata, tag); + if (ret == -WD_EBUSY) { + usleep(SEND_USLEEP * try_cnt); + try_cnt++; + if (try_cnt > MAX_TRY_CNT) { + SEC_TST_PRT("Test cipher send fail %d times!\n", MAX_TRY_CNT); + try_cnt = 0; + } + continue; + } + + count++; + try_cnt = 0; + i = count % MAX_POOL_LENTH; + copdata.in = res_in[i]; + copdata.out = res_out[i]; + copdata.iv = res_iv[i]; + } + wcrypto_del_cipher_ctx(ctx); + + break; + case AEAD_TYPE: // just ccm and gcm + aead_setup.calg = pdata->alg; + aead_setup.cmode = pdata->mode; + aead_setup.br.alloc = (void *)wd_alloc_blk; + aead_setup.br.free = (void *)wd_free_blk; + aead_setup.br.iova_map = (void *)wd_blk_iova_map; + aead_setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + aead_setup.br.get_bufsize = (void *)wd_blksize; + aead_setup.br.usr = pool; + + ctx = wcrypto_create_aead_ctx(queue, &aead_setup); + if (!ctx) { + SEC_TST_PRT("wd create aead ctx fail!\n"); + return NULL; + } + + ret = wcrypto_set_aead_ckey(ctx, (__u8*)priv_key, (__u16)pdata->keysize); + if (ret) { + SEC_TST_PRT("wd aead set key fail!\n"); + wcrypto_del_aead_ctx(ctx); + return NULL; + } + + authsize = 16; //set defaut size + ret = wcrypto_aead_setauthsize(ctx, authsize); + if (ret) { + SEC_TST_PRT("set authsize fail!\n"); + wcrypto_del_aead_ctx(ctx); + return NULL; + } + + if (queue->capa.priv.direction == 0) { + aopdata.op_type = WCRYPTO_CIPHER_ENCRYPTION_DIGEST; + aopdata.out_bytes = g_pktlen + 32; // aad + plen + authsize; + } else { + aopdata.op_type = WCRYPTO_CIPHER_DECRYPTION_DIGEST; + aopdata.out_bytes = g_pktlen + 16; // aad + plen; + } + + aopdata.assoc_size = 16; + aopdata.in_bytes = g_pktlen; + aopdata.out_bytes = g_pktlen; + aopdata.iv_bytes = pdata->ivsize; + aopdata.priv = NULL; + aopdata.out_buf_bytes = g_pktlen * 2; + + aopdata.in = res_in[0]; + aopdata.out = res_out[0]; + aopdata.iv = res_iv[0]; + usleep(SEND_USLEEP); + while(1) { + if (get_run_state() == 0) + break; + + ret = wcrypto_do_aead(ctx, &aopdata, tag); + if (ret == -WD_EBUSY) { + usleep(SEND_USLEEP * try_cnt); + try_cnt++; + if (try_cnt > MAX_TRY_CNT) { + SEC_TST_PRT("Test aead send fail %d times!\n", MAX_TRY_CNT); + try_cnt = 0; + } + continue; + } + + count++; + try_cnt = 0; + i = count % MAX_POOL_LENTH; + aopdata.in = res_in[i]; + aopdata.out = res_out[i]; + aopdata.iv = res_iv[i]; + } + wcrypto_del_aead_ctx(ctx); + + break; + case DIGEST_TYPE: + digest_setup.alg = pdata->alg; + digest_setup.mode = pdata->mode; + digest_setup.br.alloc = (void *)wd_alloc_blk; + digest_setup.br.free = (void *)wd_free_blk; + digest_setup.br.iova_map = (void *)wd_blk_iova_map; + digest_setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + digest_setup.br.get_bufsize = (void *)wd_blksize; + digest_setup.br.usr = pool; + + ctx = wcrypto_create_digest_ctx(queue, &digest_setup); + if (!ctx) { + SEC_TST_PRT("wd create digest ctx fail!\n"); + return NULL; + } + + if (digest_setup.mode == WCRYPTO_DIGEST_HMAC) { + ret = wcrypto_set_digest_key(ctx, (__u8*)priv_key, + (__u16)pdata->keysize); + if (ret) { + SEC_TST_PRT("wd digest set key fail!\n"); + wcrypto_del_digest_ctx(ctx); + return NULL; + } + } + + dopdata.in_bytes = g_pktlen; + dopdata.out_bytes = 16; + dopdata.has_next = 0; + dopdata.priv = NULL; + + dopdata.in = res_in[0]; + dopdata.out = res_out[0]; + usleep(SEND_USLEEP); + while(1) { + if (get_run_state() == 0) + break; + + ret = wcrypto_do_digest(ctx, &dopdata, (void *)tag); + if (ret == -WD_EBUSY) { + usleep(SEND_USLEEP * try_cnt); + try_cnt++; + if (try_cnt > MAX_TRY_CNT) { + SEC_TST_PRT("Test digest send fail %d times!\n", MAX_TRY_CNT); + try_cnt = 0; + } + continue; + } + + count++; + try_cnt = 0; + i = count % MAX_POOL_LENTH; + dopdata.in = res_in[i]; + dopdata.out = res_out[i]; + } + wcrypto_del_digest_ctx(ctx); + break; + } + + add_recv_data(count, g_pktlen); + + return NULL; +} + +int sec_wd_sync_threads(struct acc_option *options) +{ + thread_data threads_args[THREADS_NUM]; + thread_data threads_option; + pthread_t tdid[THREADS_NUM]; + int i, ret; + + /* alg param parse and set to thread data */ + ret = sec_wd_param_parse(&threads_option, options); + if (ret) + return ret; + + for (i = 0; i < g_thread_num; i++) { + threads_args[i].subtype = threads_option.subtype; + threads_args[i].alg = threads_option.alg; + threads_args[i].mode = threads_option.mode; + threads_args[i].keysize = threads_option.keysize; + threads_args[i].ivsize = threads_option.ivsize; + threads_args[i].optype = threads_option.optype; + threads_args[i].td_id = i; + ret = pthread_create(&tdid[i], NULL, sec_wd_sync_run, &threads_args[i]); + if (ret) { + SEC_TST_PRT("Create sync thread fail!\n"); + goto sync_error; + } + } + + /* join thread */ + for (i = 0; i < g_thread_num; i++) { + ret = pthread_join(tdid[i], NULL); + if (ret) { + SEC_TST_PRT("Join sync thread fail!\n"); + goto sync_error; + } + } + +sync_error: + return ret; + +} + +int sec_wd_async_threads(struct acc_option *options) +{ + thread_data threads_args[THREADS_NUM]; + thread_data threads_option; + pthread_t tdid[THREADS_NUM]; + pthread_t pollid[THREADS_NUM]; + int i, ret; + + /* alg param parse and set to thread data */ + ret = sec_wd_param_parse(&threads_option, options); + if (ret) + return ret; + + /* poll thread */ + for (i = 0; i < g_thread_num; i++) { + threads_args[i].subtype = threads_option.subtype; + threads_args[i].td_id = i; + ret = pthread_create(&pollid[i], NULL, sec_wd_poll, &threads_args[i]); + if (ret) { + SEC_TST_PRT("Create poll thread fail!\n"); + goto async_error; + } + } + + for (i = 0; i < g_thread_num; i++) { + threads_args[i].subtype = threads_option.subtype; + threads_args[i].alg = threads_option.alg; + threads_args[i].mode = threads_option.mode; + threads_args[i].keysize = threads_option.keysize; + threads_args[i].ivsize = threads_option.ivsize; + threads_args[i].optype = threads_option.optype; + threads_args[i].td_id = i; + ret = pthread_create(&tdid[i], NULL, sec_wd_async_run, &threads_args[i]); + if (ret) { + SEC_TST_PRT("Create async thread fail!\n"); + goto async_error; + } + } + + /* join thread */ + for (i = 0; i < g_thread_num; i++) { + ret = pthread_join(tdid[i], NULL); + if (ret) { + SEC_TST_PRT("Join async thread fail!\n"); + goto async_error; + } + } + + for (i = 0; i < g_thread_num; i++) { + ret = pthread_join(pollid[i], NULL); + if (ret) { + SEC_TST_PRT("Join poll thread fail!\n"); + goto async_error; + } + } + +async_error: + return ret; +} + +int sec_wd_benchmark(struct acc_option *options) +{ + u32 ptime; + int ret; + + g_thread_num = options->threads; + g_pktlen = options->pktlen; + if (options->optype > WCRYPTO_CIPHER_DECRYPTION) { + SEC_TST_PRT("SEC optype error: %u\n", options->optype); + return -EINVAL; + } + + ret = init_wd_queue(options); + if (ret) + return ret; + + get_pid_cpu_time(&ptime); + time_start(options->times); + if (options->syncmode) + ret = sec_wd_async_threads(options); + else + ret = sec_wd_sync_threads(options); + cal_perfermance_data(options, ptime); + if (ret) + return ret; + + uninit_wd_queue(); + + return 0; +} diff --git a/uadk/uadk_tool/benchmark/sec_wd_benchmark.h b/uadk/uadk_tool/benchmark/sec_wd_benchmark.h new file mode 100644 index 0000000..ce4f73f --- /dev/null +++ b/uadk/uadk_tool/benchmark/sec_wd_benchmark.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +#ifndef SEC_WD_BENCHMARK_H +#define SEC_WD_BENCHMARK_H + +#include "uadk_benchmark.h" + +extern int sec_wd_benchmark(struct acc_option *options); +#endif /* SEC_WD_BENCHMARK_H */ diff --git a/uadk/uadk_tool/benchmark/uadk_benchmark.c b/uadk/uadk_tool/benchmark/uadk_benchmark.c new file mode 100644 index 0000000..d3b9ef3 --- /dev/null +++ b/uadk/uadk_tool/benchmark/uadk_benchmark.c @@ -0,0 +1,743 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include + +#include "uadk_benchmark.h" +#include "sec_uadk_benchmark.h" +#include "sec_wd_benchmark.h" +#include "sec_soft_benchmark.h" + +#include "hpre_uadk_benchmark.h" +#include "hpre_wd_benchmark.h" + +#include "zip_uadk_benchmark.h" +#include "zip_wd_benchmark.h" + +#define TABLE_SPACE_SIZE 8 + +/*----------------------------------------head struct--------------------------------------------------------*/ +static unsigned int g_run_state = 1; +static pthread_mutex_t acc_mutex = PTHREAD_MUTEX_INITIALIZER; +static struct _recv_data { + double pkg_len; + u64 send_cnt; + u64 recv_cnt; + u32 send_times; + u32 recv_times; +} g_recv_data; + +/* SVA mode and NOSVA mode change need re_insmod driver ko */ +enum test_type { + SVA_MODE = 0x1, + NOSVA_MODE = 0x2, + SOFT_MODE = 0x4, + SVA_SOFT = 0x5, + NOSVA_SOFT = 0x6, + INVALID_MODE = 0x8, +}; + +struct acc_sva_item { + char *name; + u32 type; +}; + +static struct acc_sva_item sys_name_item[] = { + {"sva", SVA_MODE}, + {"nosva", NOSVA_MODE}, + {"soft", SOFT_MODE}, + {"sva-soft", SVA_SOFT}, + {"nosva-soft", NOSVA_SOFT}, +}; + +struct acc_alg_item { + char *name; + int alg; +}; + +static struct acc_alg_item alg_options[] = { + {"zlib", ZLIB}, + {"gzip", GZIP}, + {"deflate", DEFLATE}, + {"lz77_zstd", LZ77_ZSTD}, + {"rsa-1024", RSA_1024}, + {"rsa-2048", RSA_2048}, + {"rsa-3072", RSA_3072}, + {"rsa-4096", RSA_4096}, + {"rsa-1024-crt", RSA_1024_CRT}, + {"rsa-2048-crt", RSA_2048_CRT}, + {"rsa-3072-crt", RSA_3072_CRT}, + {"rsa-4096-crt", RSA_4096_CRT}, + {"dh-768", DH_768}, + {"dh-1024", DH_1024}, + {"dh-1536", DH_1536}, + {"dh-2048", DH_2048}, + {"dh-3072", DH_3072}, + {"dh-4096", DH_4096}, + {"ecdh-256", ECDH_256}, + {"ecdh-384", ECDH_384}, + {"ecdh-521", ECDH_521}, + {"ecdsa-256", ECDSA_256}, + {"ecdsa-384", ECDSA_384}, + {"ecdsa-521", ECDSA_521}, + {"sm2", SM2_ALG}, + {"x25519", X25519_ALG}, + {"x448", X448_ALG}, + {"aes-128-ecb", AES_128_ECB}, + {"aes-192-ecb", AES_192_ECB}, + {"aes-256-ecb", AES_256_ECB}, + {"aes-128-cbc", AES_128_CBC}, + {"aes-192-cbc", AES_192_CBC}, + {"aes-256-cbc", AES_256_CBC}, + {"aes-128-ctr", AES_128_CTR}, + {"aes-192-ctr", AES_192_CTR}, + {"aes-256-ctr", AES_256_CTR}, + {"aes-128-ofb", AES_128_OFB}, + {"aes-192-ofb", AES_192_OFB}, + {"aes-256-ofb", AES_256_OFB}, + {"aes-128-cfb", AES_128_CFB}, + {"aes-192-cfb", AES_192_CFB}, + {"aes-256-cfb", AES_256_CFB}, + {"aes-256-xts", AES_256_XTS}, + {"aes-512-xts", AES_512_XTS}, + {"3des-128-ecb", DES3_128_ECB}, + {"3des-192-ecb", DES3_192_ECB}, + {"3des-128-cbc", DES3_128_CBC}, + {"3des-192-cbc", DES3_192_CBC}, + {"sm4-128-ecb", SM4_128_ECB}, + {"sm4-128-cbc", SM4_128_CBC}, + {"sm4-128-ctr", SM4_128_CTR}, + {"sm4-128-ofb", SM4_128_OFB}, + {"sm4-128-cfb", SM4_128_CFB}, + {"sm4-128-xts", SM4_128_XTS}, + {"aes-128-ccm", AES_128_CCM}, + {"aes-192-ccm", AES_192_CCM}, + {"aes-256-ccm", AES_256_CCM}, + {"aes-128-gcm", AES_128_GCM}, + {"aes-192-gcm", AES_192_GCM}, + {"aes-256-gcm", AES_256_GCM}, + {"sm4-128-ccm", SM4_128_CCM}, + {"sm4-128-gcm", SM4_128_GCM}, + {"sm3", SM3_ALG}, + {"md5", MD5_ALG}, + {"sha1", SHA1_ALG}, + {"sha256", SHA256_ALG}, + {"sha224", SHA224_ALG}, + {"sha384", SHA384_ALG}, + {"sha512", SHA512_ALG}, + {"sha512-224", SHA512_224}, + {"sha512-256", SHA512_256}, + {"", ALG_MAX} +}; + +/*-------------------------------------tool code------------------------------------------------------*/ +void add_send_complete(void) +{ + __atomic_add_fetch(&g_recv_data.send_times, 1, __ATOMIC_RELAXED); +} + +void add_recv_data(u32 cnt, u32 pkglen) +{ + pthread_mutex_lock(&acc_mutex); + g_recv_data.recv_cnt += cnt; + if (g_recv_data.pkg_len == 0) + g_recv_data.pkg_len = pkglen; + else + g_recv_data.pkg_len = ((double)pkglen + g_recv_data.pkg_len) / 2; + g_recv_data.recv_times++; + pthread_mutex_unlock(&acc_mutex); +} + +u32 get_recv_time(void) +{ + return g_recv_data.recv_times; +} + +void init_recv_data(void) +{ + g_recv_data.send_cnt = 0; + g_recv_data.recv_cnt = 0; + g_recv_data.pkg_len = 0.0; + g_recv_data.send_times = 0; + g_recv_data.recv_times = 0; +} + +int get_run_state(void) +{ + return g_run_state; +} + +void set_run_state(int state) +{ + g_run_state = state; +} + +static int get_alg_type(const char *alg_name) +{ + int alg = ALG_MAX; + int i; + + for (i = 0; i < ALG_MAX; i++) { + if (strcmp(alg_name, alg_options[i].name) == 0) { + alg = alg_options[i].alg; + break; + } + } + + return alg; +} + +static int get_mode_type(const char *mode_name) +{ + u32 modetype = INVALID_MODE; + int i; + + for (i = 0; i < ARRAY_SIZE(sys_name_item); i++) { + if (strcmp(mode_name, sys_name_item[i].name) == 0) { + modetype = sys_name_item[i].type; + break; + } + } + + return modetype; +} + +int get_pid_cpu_time(u32 *ptime) +{ + u64 caltime[8] = {0}; + int pid = getpid(); + char dev_path[64]; + char buf[256]; + int i, fd, ret, bgidx; + + memset(dev_path, 0, 64); + snprintf(dev_path, 64, "/proc/%d/stat", pid); + fd = open(dev_path, O_RDONLY, 0); + if (fd < 0) { + printf("open cpu dir fail!\n"); + *ptime = 0; + return -1; + } + + memset(buf, 0, 256); + ret = read(fd, buf, 255); + if (ret <= 0) { + printf("read data fail!\n"); + *ptime = 0; + return -1; + } + close(fd); + + bgidx = 13; // process time data begin with index 13 + for (i = 0; i < ret; i++) { + if (buf[i] == ' ') { + bgidx--; + if (bgidx == 0) + break; + } + } + ret = sscanf(&buf[i], "%llu %llu %llu %llu", &caltime[0], &caltime[1], + &caltime[2], &caltime[3]); + *ptime = caltime[0] + caltime[1] + caltime[2] + caltime[3]; + + return 0; +} + +void mdelay(u32 ms) +{ + int clock_tcy = 2600000000; // 2.6Ghz CPU; + int i; + + while(ms) { + i++; + if (i == clock_tcy) + ms--; + } +} + +static void alarm_end(int sig) +{ + if (sig == SIGALRM) { + set_run_state(0); + alarm(0); + } + signal(SIGALRM, alarm_end); + alarm(1); +} + +void time_start(u32 seconds) +{ + set_run_state(1); + init_recv_data(); + signal(SIGALRM, alarm_end); + alarm(seconds); +} + +void get_rand_data(u8 *addr, u32 size) +{ + unsigned short rand_state[3] = { + (0xae >> 16) & 0xffff, 0xae & 0xffff, 0x330e}; + int i; + +#if 1 + // only 32bit valid, other 32bit is zero + for (i = 0; i < size >> 3; i++) + *((u64 *)addr + i) = nrand48(rand_state); +#else + // full 64bit valid + for (i = 0; i < size >> 2; i++) + *((u32 *)addr + i) = nrand48(rand_state); +#endif +} + +/*-------------------------------------main code------------------------------------------------------*/ + +static void parse_alg_param(struct acc_option *option) +{ + switch(option->algtype) { + case ZLIB: + snprintf(option->algclass, MAX_ALG_NAME, "%s", "zlib"); + option->acctype = ZIP_TYPE; + option->subtype = DEFAULT_TYPE; + break; + case GZIP: + snprintf(option->algclass, MAX_ALG_NAME, "%s", "gzip"); + option->acctype = ZIP_TYPE; + option->subtype = DEFAULT_TYPE; + break; + case DEFLATE: + snprintf(option->algclass, MAX_ALG_NAME, "%s", "deflate"); + option->acctype = ZIP_TYPE; + option->subtype = DEFAULT_TYPE; + break; + case LZ77_ZSTD: + snprintf(option->algclass, MAX_ALG_NAME, "%s", "lz77_zstd"); + option->acctype = ZIP_TYPE; + option->subtype = DEFAULT_TYPE; + break; + case SM2_ALG: + snprintf(option->algclass, MAX_ALG_NAME, "%s", "sm2"); + option->acctype = HPRE_TYPE; + option->subtype = SM2_TYPE; + break; + case X25519_ALG: + snprintf(option->algclass, MAX_ALG_NAME, "%s", "x25519"); + option->acctype = HPRE_TYPE; + option->subtype = X25519_TYPE; + break; + case X448_ALG: + snprintf(option->algclass, MAX_ALG_NAME, "%s", "x448"); + option->acctype = HPRE_TYPE; + option->subtype = X448_TYPE; + break; + default: + if (option->algtype <= RSA_4096_CRT) { + snprintf(option->algclass, MAX_ALG_NAME, "%s", "rsa"); + option->acctype = HPRE_TYPE; + option->subtype = RSA_TYPE; + } else if (option->algtype <= DH_4096) { + snprintf(option->algclass, MAX_ALG_NAME, "%s", "dh"); + option->acctype = HPRE_TYPE; + option->subtype = DH_TYPE; + } else if (option->algtype <= ECDH_521) { + snprintf(option->algclass, MAX_ALG_NAME, "%s", "ecdh"); + option->acctype = HPRE_TYPE; + option->subtype = ECDH_TYPE; + } else if (option->algtype <= ECDSA_521) { + snprintf(option->algclass, MAX_ALG_NAME, "%s", "ecdsa"); + option->acctype = HPRE_TYPE; + option->subtype = ECDSA_TYPE; + } else if (option->algtype <= SM4_128_XTS) { + snprintf(option->algclass, MAX_ALG_NAME, "%s", "cipher"); + option->acctype = SEC_TYPE; + option->subtype = CIPHER_TYPE; + } else if (option->algtype <= SM4_128_GCM) { + snprintf(option->algclass, MAX_ALG_NAME, "%s", "aead"); + option->acctype = SEC_TYPE; + option->subtype = AEAD_TYPE; + } else if (option->algtype <= SHA512_256) { + snprintf(option->algclass, MAX_ALG_NAME, "%s", "digest"); + option->acctype = SEC_TYPE; + option->subtype = DIGEST_TYPE; + } + } +} + +void cal_perfermance_data(struct acc_option *option, u32 sttime) +{ + u8 palgname[MAX_ALG_NAME]; + double perfermance; + double cpu_rate; + u32 ttime = 1000; + double perfdata; + double perfops; + double ops; + u32 ptime; + int i, len; + + get_pid_cpu_time(&ptime); + + while(ttime) { + if (option->syncmode == SYNC_MODE) { + if (get_recv_time() == option->threads) + break; + } else { // ASYNC_MODE + if (get_recv_time() == 1) + break; + } + usleep(1000); + ttime--; + } + + memset(palgname, ' ', MAX_ALG_NAME); + len = strlen(option->algname); + for (i = 0; i < len; i++) { + palgname[i] = option->algname[i]; + } + if (len <= TABLE_SPACE_SIZE) + palgname[TABLE_SPACE_SIZE] = '\0'; + else + palgname[i] = '\0'; + + ptime = ptime - sttime; + perfdata = g_recv_data.pkg_len * g_recv_data.recv_cnt / 1024.0; + perfops = (double)(g_recv_data.recv_cnt) / 1000.0; + perfermance = perfdata / option->times; + ops = perfops / option->times; + cpu_rate = (double)ptime / option->times; + ACC_TST_PRT("algname: length: perf: iops: CPU_rate:\n" + "%s %-2uBytes %.1fKB/s %.1fKops %.2f%%\n", + palgname, option->pktlen, perfermance, ops, cpu_rate); +} + +static int benchmark_run(struct acc_option *option) +{ + int ret = 0; + + switch(option->acctype) { + case SEC_TYPE: + if (option->modetype & SVA_MODE) { + ret = sec_uadk_benchmark(option); + } else if (option->modetype & NOSVA_MODE) { + ret = sec_wd_benchmark(option); + } + usleep(20000); +#ifdef WITH_OPENSSL_DIR + if (option->modetype & SOFT_MODE) { + ret = sec_soft_benchmark(option); + } +#endif + break; + case HPRE_TYPE: + if (option->modetype & SVA_MODE) { + ret = hpre_uadk_benchmark(option); + } else if (option->modetype & NOSVA_MODE) { + ret = hpre_wd_benchmark(option); + } + break; + case ZIP_TYPE: + if (option->modetype & SVA_MODE) { + ret = zip_uadk_benchmark(option); + } else if (option->modetype & NOSVA_MODE) { + ret = zip_wd_benchmark(option); + } + break; + } + + return ret; +} + +static void dump_param(struct acc_option *option) +{ + ACC_TST_PRT(" [--algname]: %s\n", option->algname); + ACC_TST_PRT(" [--mode]: %u\n", option->modetype); + ACC_TST_PRT(" [--optype]: %u\n", option->optype); + ACC_TST_PRT(" [--syncmode]:%u\n", option->syncmode); + ACC_TST_PRT(" [--pktlen]: %u\n", option->pktlen); + ACC_TST_PRT(" [--seconds]: %u\n", option->times); + ACC_TST_PRT(" [--thread]: %u\n", option->threads); + ACC_TST_PRT(" [--multi]: %u\n", option->multis); + ACC_TST_PRT(" [--ctxnum]: %u\n", option->ctxnums); + ACC_TST_PRT(" [--algclass]:%s\n", option->algclass); + ACC_TST_PRT(" [--acctype]: %u\n", option->acctype); + ACC_TST_PRT(" [--prefetch]:%u\n", option->prefetch); + ACC_TST_PRT(" [--engine]: %s\n", option->engine); +} + +int acc_benchmark_run(struct acc_option *option) +{ + int nr_children = 0; + pid_t *pids, pid; + int i, ret = 0; + int status; + + ACC_TST_PRT("start UADK benchmark test.\n"); + parse_alg_param(option); + dump_param(option); + + pthread_mutex_init(&acc_mutex, NULL); + if (option->multis <= 1) { + ret = benchmark_run(option); + return ret; + } + + pids = calloc(option->multis, sizeof(pid_t)); + if (!pids) + return -ENOMEM; + + for (i = 0; i < option->multis; i++) { + pid = fork(); + if (pid < 0) { + ACC_TST_PRT("acc cannot fork: %d\n", errno); + break; + } else if (pid > 0) { + /* Parent */ + pids[nr_children++] = pid; + continue; + } + + /* Child */ + exit(benchmark_run(option)); + } + + ACC_TST_PRT("%d children uadk_benchmark spawned\n", nr_children); + for (i = 0; i < nr_children; i++) { + pid = pids[i]; + + ret = waitpid(pid, &status, 0); + if (ret < 0) { + ACC_TST_PRT("wait(pid=%d) error %d\n", pid, errno); + continue; + } + + if (WIFEXITED(status)) { + ret = WEXITSTATUS(status); + if (ret) { + ACC_TST_PRT("child %d returned with %d\n", pid, ret); + } + } else if (WIFSIGNALED(status)) { + ret = WTERMSIG(status); + ACC_TST_PRT("child %d killed by sig %d\n", pid, ret); + } else { + ACC_TST_PRT("unexpected status for child %d\n", pid); + } + } + free(pids); + + return ret; +} + +int acc_default_case(struct acc_option *option) +{ + ACC_TST_PRT("Test sec Cipher parameter default, alg: aes-128-cbc, set_times:3," + "set_pktlen:1024 bytes, sync mode, one process, one thread.\n"); + + strcpy(option->algname, "aes-128-cbc"); + option->algtype = AES_128_CBC; + option->syncmode = SYNC_MODE; + option->modetype = SVA_MODE; + option->optype = 0; + option->pktlen = 1024; + option->times = 3; + option->threads = 1; + option->multis = 1; + option->ctxnums = 2; + + return acc_benchmark_run(option); +} + +static void print_help(void) +{ + ACC_TST_PRT("NAME\n"); + ACC_TST_PRT(" uadk_tool benchmark: test UADK acc performance,etc\n"); + ACC_TST_PRT("USAGE\n"); + ACC_TST_PRT(" uadk_tool benchmark [--alg aes-128-cbc] [--alg rsa-2048]\n"); + ACC_TST_PRT(" uadk_tool benchmark [--mode] [--pktlen] [--keylen] [--seconds]\n"); + ACC_TST_PRT(" uadk_tool benchmark [--multi] [--sync] [--async] [--help]\n"); + ACC_TST_PRT(" numactl --cpubind=0 --membind=0,1 ./uadk_tool benchmark xxxx\n"); + ACC_TST_PRT(" specify numa nodes for cpu and memory\n"); + ACC_TST_PRT("DESCRIPTION\n"); + ACC_TST_PRT(" [--alg aes-128-cbc ]:\n"); + ACC_TST_PRT(" The name of the algorithm for benchmarking\n"); + ACC_TST_PRT(" [--mode sva/nosva/soft/sva-soft/nosva-soft]: start UADK or Warpdrive or Openssl mode test\n"); + ACC_TST_PRT(" [--sync/--async]: start asynchronous/synchronous mode test\n"); + ACC_TST_PRT(" [--opt 0,1,2,3,4,5]:\n"); + ACC_TST_PRT(" SEC/ZIP: 0/1:encryption/decryption or compression/decompression\n"); + ACC_TST_PRT(" HPRE: 0~5:keygen, key compute, Enc, Dec, Sign, Verify\n"); + ACC_TST_PRT(" [--pktlen]:\n"); + ACC_TST_PRT(" set the length of BD message in bytes\n"); + ACC_TST_PRT(" [--seconds]:\n"); + ACC_TST_PRT(" set the test times\n"); + ACC_TST_PRT(" [--multi]:\n"); + ACC_TST_PRT(" set the number of process\n"); + ACC_TST_PRT(" [--thread]:\n"); + ACC_TST_PRT(" set the number of threads\n"); + ACC_TST_PRT(" [--ctxnum]:\n"); + ACC_TST_PRT(" the number of QP queues used by the entire test task\n"); + ACC_TST_PRT(" [--prefetch]:\n"); + ACC_TST_PRT(" in SVA mode, Enable prefetch can reduce page faults and improve performance\n"); + ACC_TST_PRT(" [--engine]:\n"); + ACC_TST_PRT(" set the test openssl engine\n"); + ACC_TST_PRT(" [--alglist]:\n"); + ACC_TST_PRT(" list the all support alg\n"); + ACC_TST_PRT(" [--help] = usage\n"); + ACC_TST_PRT("Example\n"); + ACC_TST_PRT(" ./uadk_tool benchmark --alg aes-128-cbc --mode sva --opt 0 --sync\n"); + ACC_TST_PRT(" --pktlen 1024 --seconds 1 --multi 1 --thread 1 --ctxnum 4\n"); + ACC_TST_PRT("UPDATE:2022-7-18\n"); +} + +static void print_support_alg(void) +{ + int i; + + ACC_TST_PRT("UADK benchmark supported ALG:\n"); + for (i = 0; i < ALG_MAX; i++) { + ACC_TST_PRT("%s\n", alg_options[i].name); + } +} + +int acc_cmd_parse(int argc, char *argv[], struct acc_option *option) +{ + int option_index = 0; + int c; + + static struct option long_options[] = { + {"alg", required_argument, 0, 2}, + {"mode", required_argument, 0, 3}, + {"opt", required_argument, 0, 4}, + {"sync", no_argument, 0, 5}, + {"async", no_argument, 0, 6}, + {"pktlen", required_argument, 0, 7}, + {"seconds", required_argument, 0, 8}, + {"thread", required_argument, 0, 9}, + {"multi", required_argument, 0, 10}, + {"ctxnum", required_argument, 0, 11}, + {"prefetch", no_argument, 0, 12}, + {"engine", required_argument, 0, 13}, + {"alglist", no_argument, 0, 14}, + {"help", no_argument, 0, 15}, + {0, 0, 0, 0} + }; + + while (1) { + c = getopt_long(argc, argv, "", long_options, &option_index); + if (c == -1) + break; + + switch (c) { + case 2: + option->algtype = get_alg_type(optarg); + strcpy(option->algname, optarg); + break; + case 3: + option->modetype = get_mode_type(optarg); + break; + case 4: + option->optype = strtol(optarg, NULL, 0); + break; + case 5: + option->syncmode = SYNC_MODE; + break; + case 6: + option->syncmode = ASYNC_MODE; + break; + case 7: + option->pktlen = strtol(optarg, NULL, 0); + break; + case 8: + option->times = strtol(optarg, NULL, 0); + break; + case 9: + option->threads = strtol(optarg, NULL, 0); + break; + case 10: + option->multis = strtol(optarg, NULL, 0); + break; + case 11: + option->ctxnums = strtol(optarg, NULL, 0); + break; + case 12: + option->prefetch = 1; + break; + case 13: + strcpy(option->engine, optarg); + break; + case 14: + print_support_alg(); + goto to_exit; + case 15: + print_help(); + goto to_exit; + default: + ACC_TST_PRT("bad input test parameter!\n"); + print_help(); + goto to_exit; + } + } + + return 0; + +to_exit: + return -EINVAL; +} + +int acc_option_convert(struct acc_option *option) +{ + if (option->algtype >= ALG_MAX) { + ACC_TST_PRT("invalid: input algname is wrong!\n"); + goto param_err; + } + + if (option->modetype >= INVALID_MODE) + goto param_err; + + if (option->optype >= MAX_OPT_TYPE) + goto param_err; + + /* Min test package size is 64Bytes */ + if (option->pktlen > MAX_DATA_SIZE) + goto param_err; + else if (option->pktlen < 16) + option->pktlen = 16; + + if (option->times > MAX_TIME_SECONDS) { + ACC_TST_PRT("uadk benchmark max test times to 128 seconds\n"); + goto param_err; + } else if (!option->times) + option->times = 3; + + if (option->threads > THREADS_NUM) { + ACC_TST_PRT("uadk benchmark max threads is 64\n"); + goto param_err; + } else if (!option->threads) + option->threads = 3; + + if (option->multis > PROCESS_NUM) { + ACC_TST_PRT("uadk benchmark max process is 32\n"); + goto param_err; + } else if (!option->multis) + option->multis = 1; + + if (option->ctxnums > MAX_CTX_NUM) { + ACC_TST_PRT("uadk benchmark every process max ctx num is 64\n"); + goto param_err; + } else if (!option->ctxnums) + option->ctxnums = 1; + + option->engine_flag = true; + if (!strlen(option->engine)) { + option->engine_flag = false; + return 0; + } else if (strcmp(option->engine, "uadk")) { + option->engine_flag = false; + ACC_TST_PRT("uadk benchmark just support engine: uadk\n"); + goto param_err; + } + + return 0; + +param_err: + ACC_TST_PRT("input parameter error, please input --help\n"); + return -EINVAL; +} diff --git a/uadk/uadk_tool/benchmark/uadk_benchmark.h b/uadk/uadk_tool/benchmark/uadk_benchmark.h new file mode 100644 index 0000000..a344fac --- /dev/null +++ b/uadk/uadk_tool/benchmark/uadk_benchmark.h @@ -0,0 +1,186 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +#ifndef UADK_BENCHMARK_H +#define UADK_BENCHMARK_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ACC_TST_PRT printf +#define PROCESS_NUM 32 +#define THREADS_NUM 64 +#define MAX_CTX_NUM 64 +#define MAX_TIME_SECONDS 128 +#define BYTES_TO_MB 20 +#define MAX_OPT_TYPE 6 +#define MAX_DATA_SIZE (15 * 1024 * 1024) +#define MAX_ALG_NAME 64 +#define ACC_QUEUE_SIZE 1024 + +#define MAX_BLOCK_NM 16384 /* BLOCK_NUM must 4 times of POOL_LENTH */ +#define MAX_POOL_LENTH 4096 +#define MAX_TRY_CNT 5000 +#define SEND_USLEEP 100 + +typedef unsigned char u8; +typedef unsigned int u32; +typedef unsigned long long u64; +#define SCHED_SINGLE "sched_single" +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +/** + * struct acc_option - Define the test acc app option list. + * @algclass: 0:cipher 1:digest + * @acctype: The sub alg type, reference func get_cipher_resource. + * @syncmode: 0:sync mode 1:async mode + * @modetype: sva, no-sva, soft mode + * @optype: enc/dec, comp/decomp + * @prefetch: write allocated memory to prevent page faults + */ +struct acc_option { + char algname[64]; + u32 algtype; + u32 modetype; + u32 optype; + u32 syncmode; + u32 pktlen; + u32 times; + u32 threads; + u32 multis; + u32 ctxnums; + char algclass[64]; + u32 acctype; + u32 subtype; + char engine[64]; + u32 engine_flag; + u32 prefetch; +}; + +enum acc_type { + SEC_TYPE, + HPRE_TYPE, + ZIP_TYPE, +}; + +enum alg_type { + DEFAULT_TYPE, + CIPHER_TYPE, + AEAD_TYPE, + DIGEST_TYPE, + RSA_TYPE, + DH_TYPE, + ECDH_TYPE, + ECDSA_TYPE, + SM2_TYPE, + X25519_TYPE, + X448_TYPE, +}; + +enum sync_type { + SYNC_MODE, + ASYNC_MODE, +}; + +enum test_alg { + ZLIB, // zlib alg + GZIP, // gzip + DEFLATE, // deflate + LZ77_ZSTD, // lz77_zstd + RSA_1024, // rsa + RSA_2048, + RSA_3072, + RSA_4096, + RSA_1024_CRT, + RSA_2048_CRT, + RSA_3072_CRT, + RSA_4096_CRT, + DH_768, // dh + DH_1024, + DH_1536, + DH_2048, + DH_3072, + DH_4096, + ECDH_256, // ecdh + ECDH_384, + ECDH_521, + ECDSA_256, // ecdsa + ECDSA_384, + ECDSA_521, + SM2_ALG, // sm2, just support key 256 + X25519_ALG, // x25519, just support key 256 + X448_ALG, // x448, just support key 448 + AES_128_ECB, // cipher + AES_192_ECB, + AES_256_ECB, + AES_128_CBC, + AES_192_CBC, + AES_256_CBC, + AES_128_CTR, + AES_192_CTR, + AES_256_CTR, + AES_128_OFB, + AES_192_OFB, + AES_256_OFB, + AES_128_CFB, + AES_192_CFB, + AES_256_CFB, + AES_256_XTS, + AES_512_XTS, + DES3_128_ECB, + DES3_192_ECB, + DES3_128_CBC, + DES3_192_CBC, + SM4_128_ECB, + SM4_128_CBC, + SM4_128_CTR, + SM4_128_OFB, + SM4_128_CFB, + SM4_128_XTS, + AES_128_CCM, // aead + AES_192_CCM, + AES_256_CCM, + AES_128_GCM, + AES_192_GCM, + AES_256_GCM, + SM4_128_CCM, + SM4_128_GCM, + SM3_ALG, // digest + MD5_ALG, + SHA1_ALG, + SHA256_ALG, + SHA224_ALG, + SHA384_ALG, + SHA512_ALG, + SHA512_224, + SHA512_256, // digest key all set 4 Bytes + ALG_MAX, +}; + +extern void mdelay(u32 ms); +extern int get_pid_cpu_time(u32 *ptime); +extern void cal_perfermance_data(struct acc_option *option, u32 sttime); +extern void time_start(u32 seconds); +extern int get_run_state(void); +extern void set_run_state(int state); +extern void get_rand_data(u8 *addr, u32 size); +extern void add_recv_data(u32 cnt, u32 pkglen); +extern void add_send_complete(void); +extern u32 get_recv_time(void); + +int acc_cmd_parse(int argc, char *argv[], struct acc_option *option); +int acc_default_case(struct acc_option *option); +int acc_option_convert(struct acc_option *option); +int acc_benchmark_run(struct acc_option *option); + +#endif /* UADK_BENCHMARK_H */ diff --git a/uadk/uadk_tool/benchmark/zip_uadk_benchmark.c b/uadk/uadk_tool/benchmark/zip_uadk_benchmark.c new file mode 100644 index 0000000..ba18e6d --- /dev/null +++ b/uadk/uadk_tool/benchmark/zip_uadk_benchmark.c @@ -0,0 +1,1200 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include "uadk_benchmark.h" + +#include "zip_uadk_benchmark.h" +#include "include/wd_comp.h" +#include "include/wd_sched.h" +#include "include/fse.h" + +#define ZIP_TST_PRT printf +#define PATH_SIZE 64 +#define ZIP_FILE "./zip" +#define COMP_LEN_RATE 2 +#define DECOMP_LEN_RATE 2 + +struct uadk_bd { + u8 *src; + u8 *dst; + u32 src_len; + u32 dst_len; +}; + +struct bd_pool { + struct uadk_bd *bds; +}; + +struct thread_pool { + struct bd_pool *pool; +} g_zip_pool; + +enum ZIP_OP_MODE { + BLOCK_MODE, + STREAM_MODE +}; + +struct zip_async_tag { + handle_t sess; + u32 td_id; + u32 bd_idx; + u32 cm_len; + ZSTD_CCtx *cctx; +}; + +typedef struct uadk_thread_res { + u32 alg; + u32 mode; // block/stream + u32 optype; + u32 td_id; +} thread_data; + +struct zip_file_head { + u32 file_size; + u32 block_num; + u32 blk_sz[MAX_POOL_LENTH]; +}; + +static struct wd_ctx_config g_ctx_cfg; +static struct wd_sched *g_sched; +static unsigned int g_thread_num; +static unsigned int g_ctxnum; +static unsigned int g_pktlen; +static unsigned int g_prefetch; + +#ifndef ZLIB_FSE +static ZSTD_CCtx* zstd_soft_fse_init(unsigned int level) +{ + return NULL; +} + +static int zstd_soft_fse(void *Ftuple, ZSTD_inBuffer *input, ZSTD_outBuffer *output, ZSTD_CCtx * cctx, ZSTD_EndDirective cmode) +{ + return input->size; +} +#endif + +static int save_file_data(const char *alg, u32 pkg_len, u32 optype) +{ + struct zip_file_head *fhead = NULL; + char file_path[PATH_SIZE]; + u32 total_file_size = 0; + double comp_rate = 0.0; + u32 full_size; + ssize_t size; + int j, fd; + int ret = 0; + + optype = optype % WD_DIR_MAX; + if (optype != WD_DIR_COMPRESS) //compress + return 0; + + ret = snprintf(file_path, PATH_SIZE, "%s_%u.%s", ZIP_FILE, pkg_len, alg); + if (ret < 0) + return -EINVAL; + + ret = access(file_path, F_OK); + if (!ret) { + ZIP_TST_PRT("compress data file: %s has exist!\n", file_path); + return 0; + } + + fd = open(file_path, O_WRONLY|O_CREAT, 0777); + if (fd < 0) { + ZIP_TST_PRT("compress data file open %s fail (%d)!\n", file_path, -errno); + return -ENODEV; + } + + fhead = malloc(sizeof(*fhead)); + if (!fhead) { + ZIP_TST_PRT("failed to alloc file head memory\n"); + ret = -ENOMEM; + goto fd_error; + } + + // init file head informations + for (j = 0; j < MAX_POOL_LENTH; j++) { + fhead->blk_sz[j] = g_zip_pool.pool[0].bds[j].dst_len; + total_file_size += fhead->blk_sz[j]; + } + fhead->block_num = MAX_POOL_LENTH; + fhead->file_size = total_file_size; + size = write(fd, fhead, sizeof(*fhead)); + if (size < 0) { + ZIP_TST_PRT("compress write file head failed: %lu!\n", size); + ret = -EINVAL; + goto write_error; + } + + // write data for one buffer one buffer to file line. + for (j = 0; j < MAX_POOL_LENTH; j++) { + size = write(fd, g_zip_pool.pool[0].bds[j].dst, + fhead->blk_sz[j]); + if (size < 0) { + ZIP_TST_PRT("compress write data error size: %lu!\n", size); + ret = -ENODEV; + break; + } + } + +write_error: + free(fhead); +fd_error: + close(fd); + + full_size = g_pktlen * MAX_POOL_LENTH; + comp_rate = (double) total_file_size / full_size; + ZIP_TST_PRT("compress data rate: %.1f%%!\n", comp_rate * 100); + + return ret; +} + +static int load_file_data(const char *alg, u32 pkg_len, u32 optype) +{ + struct zip_file_head *fhead = NULL; + char file_path[PATH_SIZE]; + ssize_t size = 0xff; + int i, j, fd; + int ret; + + optype = optype % WD_DIR_MAX; + if (optype != WD_DIR_DECOMPRESS) //decompress + return 0; + + ret = snprintf(file_path, PATH_SIZE, "%s_%u.%s", ZIP_FILE, pkg_len, alg); + if (ret < 0) + return -EINVAL; + + ret = access(file_path, F_OK); + if (ret) { + ZIP_TST_PRT("Decompress data file: %s not exist!\n", file_path); + return -EINVAL; + } + + // read data from file + fd = open(file_path, O_RDONLY, 0); + if (fd < 0) { + ZIP_TST_PRT("Decompress data file open %s fail (%d)!\n", file_path, -errno); + return -ENODEV; + } + + fhead = malloc(sizeof(*fhead)); + if (!fhead) { + ZIP_TST_PRT("failed to alloc file head memory\n"); + ret = -ENOMEM; + goto fd_err; + } + size = read(fd, fhead, sizeof(*fhead)); + if (size < 0 || fhead->block_num != MAX_POOL_LENTH) { + ZIP_TST_PRT("failed to read file head\n"); + ret = -EINVAL; + goto read_err; + } + + // read data for one buffer one buffer from file line + for (j = 0; j < MAX_POOL_LENTH; j++) { + memset(g_zip_pool.pool[0].bds[j].src, 0x0, + g_zip_pool.pool[0].bds[j].src_len); + if (size != 0) { // zero size buffer no need to read; + size = read(fd, g_zip_pool.pool[0].bds[j].src, + fhead->blk_sz[j]); + if (size < 0) { + ZIP_TST_PRT("Decompress read data error size: %lu!\n", size); + ret = -EINVAL; + goto read_err; + } else if (size == 0) { + ZIP_TST_PRT("Read file to the end!"); + } + } + g_zip_pool.pool[0].bds[j].src_len = size; + } + + for (i = 1; i < g_thread_num; i++) { + for (j = 0; j < MAX_POOL_LENTH; j++) { + if (g_zip_pool.pool[0].bds[j].src_len) + memcpy(g_zip_pool.pool[i].bds[j].src, + g_zip_pool.pool[0].bds[j].src, + g_zip_pool.pool[0].bds[j].src_len); + g_zip_pool.pool[i].bds[j].src_len = + g_zip_pool.pool[0].bds[j].src_len; + } + } + +read_err: + free(fhead); +fd_err: + close(fd); + + return ret; +} + +static int zip_uadk_param_parse(thread_data *tddata, struct acc_option *options) +{ + u32 algtype = options->algtype; + u32 optype = options->optype; + u8 mode = BLOCK_MODE; + u8 alg; + + if (optype >= WD_DIR_MAX << 1) { + ZIP_TST_PRT("Fail to get zip optype!\n"); + return -EINVAL; + } else if (optype >= WD_DIR_MAX) { + mode = STREAM_MODE; + } + + optype = optype % WD_DIR_MAX; + + switch(algtype) { + case ZLIB: + alg = WD_ZLIB; + break; + case GZIP: + alg = WD_GZIP; + break; + case DEFLATE: + alg = WD_DEFLATE; + break; + case LZ77_ZSTD: + alg = WD_LZ77_ZSTD; + if (optype == WD_DIR_DECOMPRESS) + ZIP_TST_PRT("Zip LZ77_ZSTD just support compress!\n"); + optype = WD_DIR_COMPRESS; + break; + default: + ZIP_TST_PRT("Fail to set zip alg\n"); + return -EINVAL; + } + + tddata->alg = alg; + tddata->mode = mode; + tddata->optype = optype; + + return 0; +} + +static int init_ctx_config(char *alg, int mode, int optype) +{ + struct uacce_dev_list *list; + struct sched_params param; + int i, max_node; + int ret = 0; + + max_node = numa_max_node() + 1; + if (max_node <= 0) + return -EINVAL; + + list = wd_get_accel_list(alg); + if (!list) { + ZIP_TST_PRT("Fail to get %s device\n", alg); + return -ENODEV; + } + memset(&g_ctx_cfg, 0, sizeof(struct wd_ctx_config)); + g_ctx_cfg.ctx_num = g_ctxnum; + g_ctx_cfg.ctxs = calloc(g_ctxnum, sizeof(struct wd_ctx)); + if (!g_ctx_cfg.ctxs) + return -ENOMEM; + + g_sched = wd_sched_rr_alloc(SCHED_POLICY_RR, 2, max_node, wd_comp_poll_ctx); + if (!g_sched) { + ZIP_TST_PRT("Fail to alloc sched!\n"); + goto out; + } + + /* If there is no numa, we defualt config to zero */ + if (list->dev->numa_id < 0) + list->dev->numa_id = 0; + + for (i = 0; i < g_ctxnum; i++) { + g_ctx_cfg.ctxs[i].ctx = wd_request_ctx(list->dev); + g_ctx_cfg.ctxs[i].op_type = 0; // default op_type + g_ctx_cfg.ctxs[i].ctx_mode = (__u8)mode; + } + g_sched->name = SCHED_SINGLE; + + /* + * All contexts for 2 modes & 2 types. + * The test only uses one kind of contexts at the same time. + */ + optype = optype % WD_DIR_MAX; + param.numa_id = list->dev->numa_id; + param.type = optype; + param.mode = mode; + param.begin = 0; + param.end = g_ctxnum - 1; + ret = wd_sched_rr_instance(g_sched, ¶m); + if (ret) { + ZIP_TST_PRT("Fail to fill sched data!\n"); + goto out; + } + + /* init */ + ret = wd_comp_init(&g_ctx_cfg, g_sched); + if (ret) { + ZIP_TST_PRT("Fail to cipher ctx!\n"); + goto out; + } + + wd_free_list_accels(list); + + return 0; +out: + free(g_ctx_cfg.ctxs); + wd_sched_rr_release(g_sched); + + return ret; +} + +static void uninit_ctx_config(void) +{ + int i; + + /* uninit */ + wd_comp_uninit(); + + for (i = 0; i < g_ctx_cfg.ctx_num; i++) + wd_release_ctx(g_ctx_cfg.ctxs[i].ctx); + free(g_ctx_cfg.ctxs); + wd_sched_rr_release(g_sched); +} + +static int init_uadk_bd_pool(u32 optype) +{ + u32 outsize; + u32 insize; + int i, j; + + // make the block not align to 4K + optype = optype % WD_DIR_MAX; + if (optype == WD_DIR_COMPRESS) {//compress + insize = g_pktlen; + outsize = g_pktlen * COMP_LEN_RATE; + } else { // decompress + insize = g_pktlen; + outsize = g_pktlen * DECOMP_LEN_RATE; + } + + g_zip_pool.pool = malloc(g_thread_num * sizeof(struct bd_pool)); + if (!g_zip_pool.pool) { + ZIP_TST_PRT("init uadk pool alloc thread failed!\n"); + return -ENOMEM; + } else { + for (i = 0; i < g_thread_num; i++) { + g_zip_pool.pool[i].bds = malloc(MAX_POOL_LENTH * + sizeof(struct uadk_bd)); + if (!g_zip_pool.pool[i].bds) { + ZIP_TST_PRT("init uadk bds alloc failed!\n"); + goto malloc_error1; + } + for (j = 0; j < MAX_POOL_LENTH; j++) { + g_zip_pool.pool[i].bds[j].src = malloc(insize); + if (!g_zip_pool.pool[i].bds[j].src) + goto malloc_error2; + g_zip_pool.pool[i].bds[j].src_len = insize; + + g_zip_pool.pool[i].bds[j].dst = malloc(outsize); + if (!g_zip_pool.pool[i].bds[j].dst) + goto malloc_error3; + g_zip_pool.pool[i].bds[j].dst_len = outsize; + + get_rand_data(g_zip_pool.pool[i].bds[j].src, insize); + if (g_prefetch) + get_rand_data(g_zip_pool.pool[i].bds[j].dst, outsize); + } + } + } + + return 0; + +malloc_error3: + free(g_zip_pool.pool[i].bds[j].src); +malloc_error2: + for (j--; j >= 0; j--) { + free(g_zip_pool.pool[i].bds[j].src); + free(g_zip_pool.pool[i].bds[j].dst); + } +malloc_error1: + for (i--; i >= 0; i--) { + for (j = 0; j < MAX_POOL_LENTH; j++) { + free(g_zip_pool.pool[i].bds[j].src); + free(g_zip_pool.pool[i].bds[j].dst); + } + free(g_zip_pool.pool[i].bds); + g_zip_pool.pool[i].bds = NULL; + } + free(g_zip_pool.pool); + g_zip_pool.pool = NULL; + + ZIP_TST_PRT("init uadk bd pool alloc failed!\n"); + return -ENOMEM; +} + +static void free_uadk_bd_pool(void) +{ + int i, j; + + for (i = 0; i < g_thread_num; i++) { + if (g_zip_pool.pool[i].bds) { + for (j = 0; j < MAX_POOL_LENTH; j++) { + free(g_zip_pool.pool[i].bds[j].src); + free(g_zip_pool.pool[i].bds[j].dst); + } + } + free(g_zip_pool.pool[i].bds); + g_zip_pool.pool[i].bds = NULL; + } + free(g_zip_pool.pool); + g_zip_pool.pool = NULL; +} + +/*-------------------------------uadk benchmark main code-------------------------------------*/ +static void *zip_lz77_async_cb(struct wd_comp_req *req, void *data) +{ + struct zip_async_tag *tag = req->cb_param; + struct bd_pool *uadk_pool; + int td_id = tag->td_id; + int idx = tag->bd_idx; + ZSTD_inBuffer zstd_input; + ZSTD_outBuffer zstd_output; + ZSTD_CCtx *cctx = tag->cctx; + size_t fse_size; + + uadk_pool = &g_zip_pool.pool[td_id]; + uadk_pool->bds[idx].dst_len = req->dst_len; + + zstd_input.src = req->src; + zstd_input.size = req->src_len; + zstd_input.pos = 0; + zstd_output.dst = uadk_pool->bds[idx].dst; + zstd_output.size = tag->cm_len; + zstd_output.pos = 0; + fse_size = zstd_soft_fse(req->priv, &zstd_input, &zstd_output, cctx, ZSTD_e_end); + + uadk_pool->bds[idx].dst_len = fse_size; + + return NULL; +} + +static void *zip_async_cb(struct wd_comp_req *req, void *data) +{ + struct zip_async_tag *tag = req->cb_param; + struct bd_pool *uadk_pool; + int td_id = tag->td_id; + int idx = tag->bd_idx; + + uadk_pool = &g_zip_pool.pool[td_id]; + uadk_pool->bds[idx].dst_len = req->dst_len; + + return NULL; +} + +static void *zip_uadk_poll(void *data) +{ + thread_data *pdata = (thread_data *)data; + u32 expt = ACC_QUEUE_SIZE * g_thread_num; + u32 id = pdata->td_id; + u32 last_time = 2; // poll need one more recv time + u32 count = 0; + u32 recv = 0; + int ret; + + if (id > g_ctxnum) + return NULL; + + while (last_time) { + ret = wd_comp_poll_ctx(id, expt, &recv); + count += recv; + recv = 0; + if (unlikely(ret != -WD_EAGAIN && ret < 0)) { + ZIP_TST_PRT("poll ret: %u!\n", ret); + goto recv_error; + } + + if (get_run_state() == 0) + last_time--; + } + +recv_error: + add_recv_data(count, g_pktlen); + + return NULL; +} + +static void *zip_uadk_blk_lz77_sync_run(void *arg) +{ + thread_data *pdata = (thread_data *)arg; + struct wd_comp_sess_setup comp_setup = {0}; + ZSTD_CCtx *cctx = zstd_soft_fse_init(15); + ZSTD_inBuffer zstd_input = {0}; + ZSTD_outBuffer zstd_output = {0}; + COMP_TUPLE_TAG *ftuple = NULL; + struct bd_pool *uadk_pool; + struct wd_comp_req creq; + char *hw_buff_out = NULL; + size_t fse_size; + handle_t h_sess; + u32 first_len = 0; + u32 out_len = 0; + u32 count = 0; + int ret, i = 0; + + if (pdata->td_id > g_thread_num) + return NULL; + + uadk_pool = &g_zip_pool.pool[pdata->td_id]; + memset(&comp_setup, 0, sizeof(comp_setup)); + memset(&creq, 0, sizeof(creq)); + + comp_setup.alg_type = pdata->alg; + comp_setup.op_type = pdata->optype; + comp_setup.comp_lv = WD_COMP_L8; + comp_setup.win_sz = WD_COMP_WS_8K; + h_sess = wd_comp_alloc_sess(&comp_setup); + if (!h_sess) + return NULL; + + creq.op_type = pdata->optype; + creq.src_len = g_pktlen; + out_len = uadk_pool->bds[0].dst_len; + + creq.cb = NULL; + creq.data_fmt = 0; + creq.status = 0; + + ftuple = malloc(sizeof(COMP_TUPLE_TAG) * MAX_POOL_LENTH); + if (!ftuple) + goto fse_err; + + hw_buff_out = malloc(out_len * MAX_POOL_LENTH); + if (!hw_buff_out) + goto hw_buff_err; + memset(hw_buff_out, 0x0, out_len * MAX_POOL_LENTH); + + while(1) { + i = count % MAX_POOL_LENTH; + creq.src = uadk_pool->bds[i].src; + creq.dst = &hw_buff_out[i]; //temp out + creq.src_len = uadk_pool->bds[i].src_len; + creq.dst_len = out_len; + creq.priv = &ftuple[i]; + + ret = wd_do_comp_sync(h_sess, &creq); + if (ret || creq.status) + break; + + count++; + zstd_input.src = creq.src; + zstd_input.size = creq.src_len; + zstd_input.pos = 0; + zstd_output.dst = uadk_pool->bds[i].dst; + zstd_output.size = out_len; + zstd_output.pos = 0; + fse_size = zstd_soft_fse(creq.priv, &zstd_input, &zstd_output, cctx, ZSTD_e_end); + + uadk_pool->bds[i].dst_len = fse_size; + if (unlikely(i == 0)) + first_len = fse_size; + if (get_run_state() == 0) + break; + } + +hw_buff_err: + free(hw_buff_out); +fse_err: + free(ftuple); + wd_comp_free_sess(h_sess); + + // ZIP_TST_PRT("valid pool len: %u, send count BD: %u, output len: %u!\n", + // MAX_POOL_LENTH, count, creq.dst_len); + if (pdata->optype == WD_DIR_COMPRESS) + add_recv_data(count, creq.src_len); + else + add_recv_data(count, first_len); + + return NULL; +} + +static void *zip_uadk_stm_lz77_sync_run(void *arg) +{ + thread_data *pdata = (thread_data *)arg; + struct wd_comp_sess_setup comp_setup = {0}; + ZSTD_CCtx *cctx = zstd_soft_fse_init(15); + ZSTD_inBuffer zstd_input = {0}; + ZSTD_outBuffer zstd_output = {0}; + COMP_TUPLE_TAG *ftuple = NULL; + struct bd_pool *uadk_pool; + struct wd_comp_req creq; + char *hw_buff_out = NULL; + size_t fse_size; + handle_t h_sess; + u32 first_len = 0; + u32 out_len = 0; + u32 count = 0; + int ret, i = 0; + + if (pdata->td_id > g_thread_num) + return NULL; + + uadk_pool = &g_zip_pool.pool[pdata->td_id]; + memset(&comp_setup, 0, sizeof(comp_setup)); + memset(&creq, 0, sizeof(creq)); + + comp_setup.alg_type = pdata->alg; + comp_setup.op_type = pdata->optype; + comp_setup.comp_lv = WD_COMP_L8; + comp_setup.win_sz = WD_COMP_WS_8K; + h_sess = wd_comp_alloc_sess(&comp_setup); + if (!h_sess) + return NULL; + + creq.op_type = pdata->optype; + creq.src_len = g_pktlen; + out_len = uadk_pool->bds[0].dst_len; + + creq.cb = NULL; + creq.data_fmt = 0; + creq.status = 0; + + ftuple = malloc(sizeof(COMP_TUPLE_TAG) * MAX_POOL_LENTH); + if (!ftuple) + goto fse_err; + + hw_buff_out = malloc(out_len * MAX_POOL_LENTH); + if (!hw_buff_out) + goto hw_buff_err; + memset(hw_buff_out, 0x0, out_len * MAX_POOL_LENTH); + + while(1) { + i = count % MAX_POOL_LENTH; + creq.src = uadk_pool->bds[i].src; + creq.dst = &hw_buff_out[i]; //temp out + creq.src_len = uadk_pool->bds[i].src_len; + creq.dst_len = out_len; + creq.priv = &ftuple[i]; + + ret = wd_do_comp_strm(h_sess, &creq); + if (ret < 0 || creq.status == WD_IN_EPARA) { + ZIP_TST_PRT("wd comp, invalid or incomplete data! " + "ret(%d), req.status(%u)\n", ret, creq.status); + break; + } + + count++; + zstd_input.src = creq.src; + zstd_input.size = creq.src_len; + zstd_input.pos = 0; + zstd_output.dst = uadk_pool->bds[i].dst; + zstd_output.size = out_len; + zstd_output.pos = 0; + fse_size = zstd_soft_fse(creq.priv, &zstd_input, &zstd_output, cctx, ZSTD_e_end); + + uadk_pool->bds[i].dst_len = fse_size; + if (unlikely(i == 0)) + first_len = fse_size; + if (get_run_state() == 0) + break; + } + +hw_buff_err: + free(hw_buff_out); +fse_err: + free(ftuple); + wd_comp_free_sess(h_sess); + + // ZIP_TST_PRT("valid pool len: %u, send count BD: %u, output len: %u!\n", + // MAX_POOL_LENTH, count, creq.dst_len); + if (pdata->optype == WD_DIR_COMPRESS) + add_recv_data(count, creq.src_len); + else + add_recv_data(count, first_len); + + return NULL; +} + +static void *zip_uadk_blk_lz77_async_run(void *arg) +{ + thread_data *pdata = (thread_data *)arg; + struct wd_comp_sess_setup comp_setup = {0}; + ZSTD_CCtx *cctx = zstd_soft_fse_init(15); + COMP_TUPLE_TAG *ftuple = NULL; + struct bd_pool *uadk_pool; + struct wd_comp_req creq; + struct zip_async_tag *tag; + char *hw_buff_out = NULL; + handle_t h_sess; + u32 out_len = 0; + u32 count = 0; + u32 try_cnt = 0; + int ret, i = 0; + + if (pdata->td_id > g_thread_num) + return NULL; + + uadk_pool = &g_zip_pool.pool[pdata->td_id]; + memset(&comp_setup, 0, sizeof(comp_setup)); + memset(&creq, 0, sizeof(creq)); + + comp_setup.alg_type = pdata->alg; + comp_setup.op_type = pdata->optype; + comp_setup.comp_lv = WD_COMP_L8; + comp_setup.win_sz = WD_COMP_WS_8K; + h_sess = wd_comp_alloc_sess(&comp_setup); + if (!h_sess) + return NULL; + + creq.op_type = pdata->optype; + creq.src_len = g_pktlen; + out_len = uadk_pool->bds[0].dst_len; + + creq.cb = zip_lz77_async_cb; + creq.data_fmt = 0; + creq.status = 0; + + ftuple = malloc(sizeof(COMP_TUPLE_TAG) * MAX_POOL_LENTH); + if (!ftuple) + goto fse_err; + + hw_buff_out = malloc(out_len * MAX_POOL_LENTH); + if (!hw_buff_out) + goto hw_buff_err; + memset(hw_buff_out, 0x0, out_len * MAX_POOL_LENTH); + + tag = malloc(sizeof(*tag) * MAX_POOL_LENTH); + if (!tag) { + ZIP_TST_PRT("failed to malloc zip tag!\n"); + goto tag_err; + } + + while(1) { + if (get_run_state() == 0) + break; + + try_cnt = 0; + i = count % MAX_POOL_LENTH; + creq.src = uadk_pool->bds[i].src; + creq.dst = &hw_buff_out[i]; //temp out + creq.src_len = uadk_pool->bds[i].src_len; + creq.dst_len = out_len; + creq.priv = &ftuple[i]; + + tag[i].td_id = pdata->td_id; + tag[i].bd_idx = i; + tag[i].cm_len = out_len; + tag[i].cctx = cctx; + creq.cb_param = &tag[i]; + + ret = wd_do_comp_async(h_sess, &creq); + if (ret == -WD_EBUSY) { + usleep(SEND_USLEEP * try_cnt); + try_cnt++; + if (try_cnt > MAX_TRY_CNT) { + ZIP_TST_PRT("Test LZ77 compress send fail %d times!\n", MAX_TRY_CNT); + try_cnt = 0; + } + continue; + } else if (ret || creq.status) { + break; + } + count++; + } + + while (1) { + if (get_recv_time() > 0) // wait Async mode finish recv + break; + usleep(SEND_USLEEP); + } + +tag_err: + free(tag); +hw_buff_err: + free(hw_buff_out); +fse_err: + free(ftuple); + wd_comp_free_sess(h_sess); + + // ZIP_TST_PRT("LZ77 valid pool len: %u, send count BD: %u, output len: %u!\n", + // MAX_POOL_LENTH, count, creq.dst_len); + + add_send_complete(); + + return NULL; +} + +static void *zip_uadk_blk_sync_run(void *arg) +{ + thread_data *pdata = (thread_data *)arg; + struct wd_comp_sess_setup comp_setup = {0}; + struct bd_pool *uadk_pool; + struct wd_comp_req creq; + handle_t h_sess; + u32 out_len = 0; + u32 count = 0; + int ret, i = 0; + + if (pdata->td_id > g_thread_num) + return NULL; + + uadk_pool = &g_zip_pool.pool[pdata->td_id]; + memset(&comp_setup, 0, sizeof(comp_setup)); + memset(&creq, 0, sizeof(creq)); + + comp_setup.alg_type = pdata->alg; + comp_setup.op_type = pdata->optype; + comp_setup.comp_lv = WD_COMP_L8; + comp_setup.win_sz = WD_COMP_WS_8K; + h_sess = wd_comp_alloc_sess(&comp_setup); + if (!h_sess) + return NULL; + + creq.op_type = pdata->optype; + creq.src_len = g_pktlen; + out_len = uadk_pool->bds[0].dst_len; + + creq.cb = NULL; + creq.data_fmt = 0; + creq.priv = 0; + creq.status = 0; + + while(1) { + i = count % MAX_POOL_LENTH; + creq.src = uadk_pool->bds[i].src; + creq.dst = uadk_pool->bds[i].dst; + creq.src_len = uadk_pool->bds[i].src_len; + creq.dst_len = out_len; + + ret = wd_do_comp_sync(h_sess, &creq); + if (ret || creq.status) + break; + + count++; + uadk_pool->bds[i].dst_len = creq.dst_len; + if (get_run_state() == 0) + break; + } + wd_comp_free_sess(h_sess); + + //ZIP_TST_PRT("valid pool len: %u, send count BD: %u, input len: %u, output len: %u!\n", + // MAX_POOL_LENTH, count, creq.src_len, g_pktlen); + add_recv_data(count, g_pktlen); + + return NULL; +} + +static void *zip_uadk_stm_sync_run(void *arg) +{ + thread_data *pdata = (thread_data *)arg; + struct wd_comp_sess_setup comp_setup = {0}; + struct bd_pool *uadk_pool; + struct wd_comp_req creq; + handle_t h_sess; + u32 out_len = 0; + u32 count = 0; + int ret, i = 0; + + if (pdata->td_id > g_thread_num) + return NULL; + + uadk_pool = &g_zip_pool.pool[pdata->td_id]; + memset(&comp_setup, 0, sizeof(comp_setup)); + memset(&creq, 0, sizeof(creq)); + + comp_setup.alg_type = pdata->alg; + comp_setup.op_type = pdata->optype; + comp_setup.comp_lv = WD_COMP_L8; + comp_setup.win_sz = WD_COMP_WS_8K; + h_sess = wd_comp_alloc_sess(&comp_setup); + if (!h_sess) + return NULL; + + creq.op_type = pdata->optype; + creq.src_len = g_pktlen; + out_len = uadk_pool->bds[0].dst_len; + + creq.cb = NULL; + creq.data_fmt = 0; + creq.priv = 0; + creq.status = 0; + + while(1) { + i = count % MAX_POOL_LENTH; + creq.src = uadk_pool->bds[i].src; + creq.dst = uadk_pool->bds[i].dst; + creq.src_len = uadk_pool->bds[i].src_len; + creq.dst_len = out_len; + + ret = wd_do_comp_strm(h_sess, &creq); + if (ret < 0 || creq.status == WD_IN_EPARA) { + ZIP_TST_PRT("wd comp, invalid or incomplete data! " + "ret(%d), req.status(%u)\n", ret, creq.status); + break; + } + + count++; + uadk_pool->bds[i].dst_len = creq.dst_len; + + if (get_run_state() == 0) + break; + } + wd_comp_free_sess(h_sess); + + // ZIP_TST_PRT("valid pool len: %u, send count BD: %u, output len: %u!\n", + // MAX_POOL_LENTH, count, creq.dst_len); + add_recv_data(count, g_pktlen); + + return NULL; +} + +static void *zip_uadk_blk_async_run(void *arg) +{ + thread_data *pdata = (thread_data *)arg; + struct wd_comp_sess_setup comp_setup = {0}; + struct bd_pool *uadk_pool; + struct zip_async_tag *tag; + struct wd_comp_req creq; + handle_t h_sess; + int try_cnt = 0; + u32 out_len = 0; + u32 count = 0; + int ret, i = 0; + + if (pdata->td_id > g_thread_num) + return NULL; + + uadk_pool = &g_zip_pool.pool[pdata->td_id]; + memset(&comp_setup, 0, sizeof(comp_setup)); + memset(&creq, 0, sizeof(creq)); + + comp_setup.alg_type = pdata->alg; + comp_setup.op_type = pdata->optype; + comp_setup.comp_lv = WD_COMP_L8; + comp_setup.win_sz = WD_COMP_WS_8K; + h_sess = wd_comp_alloc_sess(&comp_setup); + if (!h_sess) + return NULL; + + creq.op_type = pdata->optype; + creq.src_len = g_pktlen; + out_len = uadk_pool->bds[0].dst_len; + + creq.cb = zip_async_cb; + creq.data_fmt = 0; + creq.priv = 0; + creq.status = 0; + + tag = malloc(sizeof(*tag) * MAX_POOL_LENTH); + if (!tag) { + ZIP_TST_PRT("failed to malloc zip tag!\n"); + wd_comp_free_sess(h_sess); + return NULL; + } + + while(1) { + if (get_run_state() == 0) + break; + + try_cnt = 0; + i = count % MAX_POOL_LENTH; + creq.src = uadk_pool->bds[i].src; + creq.dst = uadk_pool->bds[i].dst; + creq.src_len = uadk_pool->bds[i].src_len; + creq.dst_len = out_len; + + tag[i].td_id = pdata->td_id; + tag[i].bd_idx = i; + creq.cb_param = &tag[i]; + + ret = wd_do_comp_async(h_sess, &creq); + if (ret == -WD_EBUSY) { + usleep(SEND_USLEEP * try_cnt); + try_cnt++; + if (try_cnt > MAX_TRY_CNT) { + ZIP_TST_PRT("Test compress send fail %d times!\n", MAX_TRY_CNT); + try_cnt = 0; + } + continue; + } else if (ret || creq.status) { + break; + } + count++; + } + + while (1) { + if (get_recv_time() > 0) // wait Async mode finish recv + break; + usleep(SEND_USLEEP); + } + + free(tag); + wd_comp_free_sess(h_sess); + + // ZIP_TST_PRT("valid pool len: %u, send count BD: %u, output len: %u!\n", + // MAX_POOL_LENTH, count, creq.dst_len); + + add_send_complete(); + + return NULL; +} + +static int zip_uadk_sync_threads(struct acc_option *options) +{ + typedef void *(*zip_sync_run)(void *arg); + zip_sync_run uadk_zip_sync_run = NULL; + thread_data threads_args[THREADS_NUM]; + thread_data threads_option; + pthread_t tdid[THREADS_NUM]; + int i, ret; + + /* alg param parse and set to thread data */ + ret = zip_uadk_param_parse(&threads_option, options); + if (ret) + return ret; + + if (threads_option.mode == 1) {// stream mode + if (threads_option.alg == LZ77_ZSTD) + uadk_zip_sync_run = zip_uadk_stm_lz77_sync_run; + else + uadk_zip_sync_run = zip_uadk_stm_sync_run; + } else { + if (threads_option.alg == LZ77_ZSTD) + uadk_zip_sync_run = zip_uadk_blk_lz77_sync_run; + else + uadk_zip_sync_run = zip_uadk_blk_sync_run; + } + for (i = 0; i < g_thread_num; i++) { + threads_args[i].alg = threads_option.alg; + threads_args[i].mode = threads_option.mode; + threads_args[i].optype = threads_option.optype; + threads_args[i].td_id = i; + ret = pthread_create(&tdid[i], NULL, uadk_zip_sync_run, &threads_args[i]); + if (ret) { + ZIP_TST_PRT("Create sync thread fail!\n"); + goto sync_error; + } + } + + /* join thread */ + for (i = 0; i < g_thread_num; i++) { + ret = pthread_join(tdid[i], NULL); + if (ret) { + ZIP_TST_PRT("Join sync thread fail!\n"); + goto sync_error; + } + } + +sync_error: + return ret; +} + +static int zip_uadk_async_threads(struct acc_option *options) +{ + typedef void *(*zip_async_run)(void *arg); + zip_async_run uadk_zip_async_run = NULL; + thread_data threads_args[THREADS_NUM]; + thread_data threads_option; + pthread_t tdid[THREADS_NUM]; + pthread_t pollid[THREADS_NUM]; + int i, ret; + + /* alg param parse and set to thread data */ + ret = zip_uadk_param_parse(&threads_option, options); + if (ret) + return ret; + + if (threads_option.mode == STREAM_MODE) {// stream mode + ZIP_TST_PRT("Stream mode can't support async mode!\n"); + return 0; + } + + if (threads_option.alg == LZ77_ZSTD) + uadk_zip_async_run = zip_uadk_blk_lz77_async_run; + else + uadk_zip_async_run = zip_uadk_blk_async_run; + + for (i = 0; i < g_ctxnum; i++) { + threads_args[i].td_id = i; + /* poll thread */ + ret = pthread_create(&pollid[i], NULL, zip_uadk_poll, &threads_args[i]); + if (ret) { + ZIP_TST_PRT("Create poll thread fail!\n"); + goto async_error; + } + } + + for (i = 0; i < g_thread_num; i++) { + threads_args[i].alg = threads_option.alg; + threads_args[i].mode = threads_option.mode; + threads_args[i].optype = threads_option.optype; + threads_args[i].td_id = i; + ret = pthread_create(&tdid[i], NULL, uadk_zip_async_run, &threads_args[i]); + if (ret) { + ZIP_TST_PRT("Create async thread fail!\n"); + goto async_error; + } + } + + /* join thread */ + for (i = 0; i < g_thread_num; i++) { + ret = pthread_join(tdid[i], NULL); + if (ret) { + ZIP_TST_PRT("Join async thread fail!\n"); + goto async_error; + } + } + + for (i = 0; i < g_ctxnum; i++) { + ret = pthread_join(pollid[i], NULL); + if (ret) { + ZIP_TST_PRT("Join poll thread fail!\n"); + goto async_error; + } + } + +async_error: + return ret; +} + +int zip_uadk_benchmark(struct acc_option *options) +{ + u32 ptime; + int ret; + + g_thread_num = options->threads; + g_pktlen = options->pktlen; + g_ctxnum = options->ctxnums; + g_prefetch = options->prefetch; + + if (options->optype >= WD_DIR_MAX * 2) { + ZIP_TST_PRT("ZIP optype error: %u\n", options->optype); + return -EINVAL; + } + + ret = init_ctx_config(options->algclass, options->syncmode, options->optype); + if (ret) + return ret; + + ret = init_uadk_bd_pool(options->optype); + if (ret) + return ret; + + ret = load_file_data(options->algname, options->pktlen, options->optype); + if (ret) + return ret; + + get_pid_cpu_time(&ptime); + time_start(options->times); + if (options->syncmode) + ret = zip_uadk_async_threads(options); + else + ret = zip_uadk_sync_threads(options); + cal_perfermance_data(options, ptime); + if (ret) + return ret; + + ret = save_file_data(options->algname, options->pktlen, options->optype); + if (ret) + return ret; + + free_uadk_bd_pool(); + uninit_ctx_config(); + + return 0; +} diff --git a/uadk/uadk_tool/benchmark/zip_uadk_benchmark.h b/uadk/uadk_tool/benchmark/zip_uadk_benchmark.h new file mode 100644 index 0000000..a3cfbc0 --- /dev/null +++ b/uadk/uadk_tool/benchmark/zip_uadk_benchmark.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +#ifndef ZIP_UADK_BENCHMARK_H +#define ZIP_UADK_BENCHMARK_H + +extern int zip_uadk_benchmark(struct acc_option *options); +#endif /* ZIP_UADK_BENCHMARK_H */ diff --git a/uadk/uadk_tool/benchmark/zip_wd_benchmark.c b/uadk/uadk_tool/benchmark/zip_wd_benchmark.c new file mode 100644 index 0000000..0df78cd --- /dev/null +++ b/uadk/uadk_tool/benchmark/zip_wd_benchmark.c @@ -0,0 +1,1257 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include "uadk_benchmark.h" + +#include "zip_wd_benchmark.h" +#include "v1/wd_comp.h" +#include "v1/wd.h" +#include "v1/wd_bmm.h" +#include "v1/wd_util.h" +#include "include/fse.h" + +#define ZIP_TST_PRT printf +#define PATH_SIZE 64 +#define ZIP_FILE "./zip" +#define WCRYPTO_DIR_MAX (WCRYPTO_INFLATE + 1) +#define ALIGN_SIZE 64 + +#define COMP_LEN_RATE 2 +#define DECOMP_LEN_RATE 2 + +#define __ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask)) +#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1) + +struct wd_bd { + u8 *src; + u8 *dst; + u32 src_len; + u32 dst_len; +}; + +struct thread_bd_res { + struct wd_queue *queue; + void *pool; + struct wd_bd *bds; +}; + +struct thread_queue_res { + struct thread_bd_res *bd_res; +}; + +static struct thread_queue_res g_thread_queue; + +enum ZIP_OP_MODE { + BLOCK_MODE, + STREAM_MODE +}; + +struct zip_async_tag { + void *ctx; + u32 td_id; + u32 bd_idx; + u32 cm_len; + void *priv; + ZSTD_CCtx *cctx; +}; + +typedef struct uadk_thread_res { + u32 alg; + u32 mode; // block/stream + u32 optype; + u32 td_id; +} thread_data; + +struct zip_file_head { + u32 file_size; + u32 block_num; + u32 blk_sz[MAX_POOL_LENTH]; +}; + +static unsigned int g_thread_num; +static unsigned int g_pktlen; + +#ifndef ZLIB_FSE +static ZSTD_CCtx* zstd_soft_fse_init(unsigned int level) +{ + return NULL; +} + +static int zstd_soft_fse(void *Ftuple, ZSTD_inBuffer *input, ZSTD_outBuffer *output, ZSTD_CCtx * cctx, ZSTD_EndDirective cmode) +{ + return input->size; +} +#endif + +static int save_file_data(const char *alg, u32 pkg_len, u32 optype) +{ + struct zip_file_head *fhead = NULL; + char file_path[PATH_SIZE]; + u32 total_file_size = 0; + double comp_rate = 0.0; + u32 full_size; + ssize_t size; + int j, fd; + int ret = 0; + + optype = optype % WCRYPTO_DIR_MAX; + if (optype != WCRYPTO_DEFLATE) //compress + return 0; + + ret = snprintf(file_path, PATH_SIZE, "%s_%u.%s", ZIP_FILE, pkg_len, alg); + if (ret < 0) + return -EINVAL; + + ret = access(file_path, F_OK); + if (!ret) { + ZIP_TST_PRT("compress data file: %s has exist!\n", file_path); + return 0; + } + + fd = open(file_path, O_WRONLY|O_CREAT, 0777); + if (fd < 0) { + ZIP_TST_PRT("compress data file open %s failed (%d)!\n", file_path, -errno); + return -ENODEV; + } + + fhead = malloc(sizeof(*fhead)); + if (!fhead) { + ZIP_TST_PRT("failed to alloc file head memory\n"); + ret = -ENOMEM; + goto fd_error; + } + + // init file head informations + for (j = 0; j < MAX_POOL_LENTH; j++) { + fhead->blk_sz[j] = g_thread_queue.bd_res[0].bds[j].dst_len; + total_file_size += fhead->blk_sz[j]; + } + fhead->block_num = MAX_POOL_LENTH; + fhead->file_size = total_file_size; + size = write(fd, fhead, sizeof(*fhead)); + if (size < 0) { + ZIP_TST_PRT("compress write file head failed: %lu!\n", size); + ret = -ENODEV; + goto write_error; + } + + // write data for one buffer one buffer to file line. + for (j = 0; j < MAX_POOL_LENTH; j++) { + size = write(fd, g_thread_queue.bd_res[0].bds[j].dst, + fhead->blk_sz[j]); + if (size < 0) { + ZIP_TST_PRT("compress write data error size: %lu!\n", size); + ret = -ENODEV; + break; + } + } + +write_error: + free(fhead); +fd_error: + close(fd); + + full_size = g_pktlen * MAX_POOL_LENTH; + comp_rate = (double) total_file_size / full_size; + ZIP_TST_PRT("compress data rate: %.1f%%!\n", comp_rate * 100); + + return ret; +} + +static int load_file_data(const char *alg, u32 pkg_len, u32 optype) +{ + struct zip_file_head *fhead = NULL; + char file_path[PATH_SIZE]; + ssize_t size = 0xff; + int i, j, fd; + int ret; + + optype = optype % WCRYPTO_DIR_MAX; + if (optype != WCRYPTO_INFLATE) //decompress + return 0; + + ret = snprintf(file_path, PATH_SIZE, "%s_%u.%s", ZIP_FILE, pkg_len, alg); + if (ret < 0) + return -EINVAL; + + ret = access(file_path, F_OK); + if (ret) { + ZIP_TST_PRT("Decompress data file: %s not exist!\n", file_path); + return -EINVAL; + } + + // read data from file + fd = open(file_path, O_RDONLY, 0); + if (fd < 0) { + ZIP_TST_PRT("Decompress data file open %s fail (%d)!\n", file_path, -errno); + return -ENODEV; + } + + fhead = malloc(sizeof(*fhead)); + if (!fhead) { + ZIP_TST_PRT("failed to alloc file head memory\n"); + ret = -ENOMEM; + goto fd_err; + } + size = read(fd, fhead, sizeof(*fhead)); + if (size < 0 || fhead->block_num != MAX_POOL_LENTH) { + ZIP_TST_PRT("failed to read file head\n"); + ret = -EINVAL; + goto read_err; + } + + // read data for one buffer one buffer from file line + for (j = 0; j < MAX_POOL_LENTH; j++) { + memset(g_thread_queue.bd_res[0].bds[j].src, 0x0, + g_thread_queue.bd_res[0].bds[j].src_len); + if (size != 0) { // zero size buffer no need to read; + size = read(fd, g_thread_queue.bd_res[0].bds[j].src, + fhead->blk_sz[j]); + if (size < 0) { + ZIP_TST_PRT("Decompress read data error size: %lu!\n", size); + ret = -EINVAL; + goto read_err; + } else if (size == 0) { + ZIP_TST_PRT("Read file to the end!"); + } + } + g_thread_queue.bd_res[0].bds[j].src_len = size; + } + + for (i = 1; i < g_thread_num; i++) { + for (j = 0; j < MAX_POOL_LENTH; j++) { + if (g_thread_queue.bd_res[0].bds[j].src_len) + memcpy(g_thread_queue.bd_res[i].bds[j].src, + g_thread_queue.bd_res[0].bds[j].src, + g_thread_queue.bd_res[0].bds[j].src_len); + g_thread_queue.bd_res[i].bds[j].src_len = + g_thread_queue.bd_res[0].bds[j].src_len; + } + } + +read_err: + free(fhead); +fd_err: + close(fd); + + return ret; +} + +static int zip_wd_param_parse(thread_data *tddata, struct acc_option *options) +{ + u32 algtype = options->algtype; + u32 optype = options->optype; + u8 mode = BLOCK_MODE; + u8 alg; + + if (optype >= WCRYPTO_DIR_MAX << 1) { + ZIP_TST_PRT("Fail to get zip optype!\n"); + return -EINVAL; + } else if (optype > WCRYPTO_INFLATE) { + mode = STREAM_MODE; + } + + optype = optype % WCRYPTO_DIR_MAX; + + switch(algtype) { + case ZLIB: + alg = WCRYPTO_ZLIB; + break; + case GZIP: + alg = WCRYPTO_GZIP; + break; + case DEFLATE: + alg = WCRYPTO_RAW_DEFLATE; + break; + case LZ77_ZSTD: + alg = WCRYPTO_LZ77_ZSTD; + if (optype == WCRYPTO_INFLATE) + ZIP_TST_PRT("Zip LZ77_ZSTD just support compress!\n"); + optype = WCRYPTO_DEFLATE; + break; + default: + ZIP_TST_PRT("Fail to set zip alg\n"); + return -EINVAL; + } + + tddata->alg = alg; + tddata->mode = mode; + tddata->optype = optype; + + return 0; +} + +static int init_zip_wd_queue(struct acc_option *options) +{ + struct wd_blkpool_setup blksetup; + struct wd_bd *bds = NULL; + void *pool = NULL; + u32 outsize; + u32 insize; + u8 op_type; + int i, j; + int ret = 0; + + op_type = options->optype % WCRYPTO_DIR_MAX; + if (op_type == WCRYPTO_DEFLATE) {//compress + insize = g_pktlen; + outsize = g_pktlen * COMP_LEN_RATE; + } else { // decompress + insize = g_pktlen; + outsize = g_pktlen * DECOMP_LEN_RATE; + } + + g_thread_queue.bd_res = malloc(g_thread_num * sizeof(struct thread_bd_res)); + if (!g_thread_queue.bd_res) { + ZIP_TST_PRT("malloc thread res memory fail!\n"); + return -ENOMEM; + } + + for (i = 0; i < g_thread_num; i++) { + g_thread_queue.bd_res[i].queue = malloc(sizeof(struct wd_queue)); + g_thread_queue.bd_res[i].queue->capa.alg = options->algclass; + // 0 is compress, 1 is decompress + g_thread_queue.bd_res[i].queue->capa.priv.direction = op_type; + /* nodemask need to be clean */ + g_thread_queue.bd_res[i].queue->node_mask = 0x0; + memset(g_thread_queue.bd_res[i].queue->dev_path, 0x0, PATH_STR_SIZE); + + ret = wd_request_queue(g_thread_queue.bd_res[i].queue); + if (ret) { + ZIP_TST_PRT("request queue %d fail!\n", i); + ret = -EINVAL; + goto queue_out; + } + } + + // use no-sva pbuffer, MAX_BLOCK_NM at least 4 times of MAX_POOL_LENTH + memset(&blksetup, 0, sizeof(blksetup)); + outsize = ALIGN(outsize, ALIGN_SIZE); + blksetup.block_size = outsize; + blksetup.block_num = MAX_BLOCK_NM; + blksetup.align_size = ALIGN_SIZE; + // ZIP_TST_PRT("create pool memory: %d KB\n", (MAX_BLOCK_NM * blksetup.block_size) >> 10); + + for (j = 0; j < g_thread_num; j++) { + g_thread_queue.bd_res[j].pool = wd_blkpool_create(g_thread_queue.bd_res[j].queue, &blksetup); + if (!g_thread_queue.bd_res[j].pool) { + ZIP_TST_PRT("create %dth pool fail!\n", j); + ret = -ENOMEM; + goto pool_err; + } + pool = g_thread_queue.bd_res[j].pool; + + g_thread_queue.bd_res[j].bds = malloc(sizeof(struct wd_bd) * MAX_POOL_LENTH); + if (!g_thread_queue.bd_res[j].bds) + goto bds_error; + bds = g_thread_queue.bd_res[j].bds; + + for (i = 0; i < MAX_POOL_LENTH; i++) { + bds[i].src = wd_alloc_blk(pool); + if (!bds[i].src) { + ret = -ENOMEM; + goto blk_error2; + } + bds[i].src_len = insize; + + bds[i].dst = wd_alloc_blk(pool); + if (!bds[i].dst) { + ret = -ENOMEM; + goto blk_error3; + } + bds[i].dst_len = outsize; + + get_rand_data(bds[i].src, insize); + } + + } + + return 0; + +blk_error3: + wd_free_blk(pool, bds[i].src); +blk_error2: + for (i--; i >= 0; i--) { + wd_free_blk(pool, bds[i].src); + wd_free_blk(pool, bds[i].dst); + } +bds_error: + wd_blkpool_destroy(g_thread_queue.bd_res[j].pool); +pool_err: + for (j--; j >= 0; j--) { + pool = g_thread_queue.bd_res[j].pool; + bds = g_thread_queue.bd_res[j].bds; + for (i = 0; i < MAX_POOL_LENTH; i++) { + wd_free_blk(pool, bds[i].src); + wd_free_blk(pool, bds[i].dst); + } + free(bds); + wd_blkpool_destroy(pool); + } +queue_out: + for (i--; i >= 0; i--) { + wd_release_queue(g_thread_queue.bd_res[i].queue); + free(g_thread_queue.bd_res[i].queue); + } + free(g_thread_queue.bd_res); + return ret; +} + +static void uninit_zip_wd_queue(void) +{ + struct wd_bd *bds = NULL; + void *pool = NULL; + int j, i; + + for (j = 0; j < g_thread_num; j++) { + pool = g_thread_queue.bd_res[j].pool; + bds = g_thread_queue.bd_res[j].bds; + for (i = 0; i < MAX_POOL_LENTH; i++) { + wd_free_blk(pool, bds[i].src); + wd_free_blk(pool, bds[i].dst); + } + + free(bds); + wd_blkpool_destroy(pool); + wd_release_queue(g_thread_queue.bd_res[j].queue); + } + + free(g_thread_queue.bd_res); +} + +/*-------------------------------uadk benchmark main code-------------------------------------*/ +static void zip_lz77_async_cb(const void *message, void *data) +{ + const struct wcrypto_comp_msg *cbmsg = message; + struct zip_async_tag *tag = data; + ZSTD_CCtx *cctx = tag->cctx; + ZSTD_inBuffer zstd_input; + ZSTD_outBuffer zstd_output; + struct wd_bd *bd_pool; + int td_id = tag->td_id; + int idx = tag->bd_idx; + size_t fse_size; + + bd_pool = g_thread_queue.bd_res[td_id].bds; + bd_pool[idx].dst_len = cbmsg->produced; + + zstd_input.src = cbmsg->src; + zstd_input.size = cbmsg->in_size; + zstd_input.pos = 0; + zstd_output.dst = bd_pool[idx].dst; + zstd_output.size = tag->cm_len; + zstd_output.pos = 0; + fse_size = zstd_soft_fse(tag->priv, &zstd_input, &zstd_output, cctx, ZSTD_e_end); + + bd_pool[idx].dst_len = fse_size; +} + +static void zip_async_cb(const void *message, void *data) +{ + const struct wcrypto_comp_msg *cbmsg = message; + struct zip_async_tag *tag = data; + struct wd_bd *bd_pool; + int td_id = tag->td_id; + int idx = tag->bd_idx; + + bd_pool = g_thread_queue.bd_res[td_id].bds; + bd_pool[idx].dst_len = cbmsg->produced; +} + +static void *zip_wd_poll(void *data) +{ + thread_data *pdata = (thread_data *)data; + u32 expt = ACC_QUEUE_SIZE * g_thread_num; + struct wd_queue *queue; + u32 id = pdata->td_id; + u32 last_time = 2; // poll need one more recv time + u32 count = 0; + int recv = 0; + + if (id > g_thread_num) + return NULL; + + queue = g_thread_queue.bd_res[id].queue; + while (last_time) { + recv = wcrypto_comp_poll(queue, expt); + if (unlikely(recv != -WD_EAGAIN && recv < 0)) { + ZIP_TST_PRT("poll ret: %u!\n", recv); + goto recv_error; + } + + count += recv; + recv = 0; + + if (get_run_state() == 0) + last_time--; + } + +recv_error: + add_recv_data(count, g_pktlen); + + return NULL; +} + +static void *zip_wd_blk_lz77_sync_run(void *arg) +{ + thread_data *pdata = (thread_data *)arg; + ZSTD_CCtx *cctx = zstd_soft_fse_init(15); + ZSTD_inBuffer zstd_input = {0}; + ZSTD_outBuffer zstd_output = {0}; + COMP_TUPLE_TAG *ftuple = NULL; + struct wcrypto_comp_ctx_setup comp_setup; + struct wcrypto_comp_op_data opdata; + struct wcrypto_comp_ctx *ctx; + struct wd_queue *queue; + struct wd_bd *bd_pool; + u8 *hw_buff_out = NULL; + size_t fse_size; + u32 first_len = 0; + u32 out_len = 0; + u32 count = 0; + int ret, i = 0; + + if (pdata->td_id > g_thread_num) + return NULL; + + bd_pool = g_thread_queue.bd_res[pdata->td_id].bds; + queue = g_thread_queue.bd_res[pdata->td_id].queue; + memset(&comp_setup, 0, sizeof(comp_setup)); + memset(&opdata, 0, sizeof(opdata)); + + comp_setup.br.alloc = (void *)wd_alloc_blk; + comp_setup.br.free = (void *)wd_free_blk; + comp_setup.br.iova_map = (void *)wd_blk_iova_map; + comp_setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + comp_setup.br.get_bufsize = (void *)wd_blksize; + comp_setup.br.usr = g_thread_queue.bd_res[pdata->td_id].pool; + + comp_setup.alg_type = pdata->alg; + comp_setup.op_type = pdata->optype; + comp_setup.comp_lv = WCRYPTO_COMP_L8; + comp_setup.win_size = WCRYPTO_COMP_WS_8K; + comp_setup.stream_mode = WCRYPTO_COMP_STATELESS; + + ctx = wcrypto_create_comp_ctx(queue, &comp_setup); + if (!ctx) + return NULL; + + opdata.stream_pos = WCRYPTO_COMP_STREAM_NEW; + opdata.alg_type = pdata->alg; + opdata.priv = NULL; + opdata.status = 0; + if (pdata->optype == WCRYPTO_INFLATE) + opdata.flush = WCRYPTO_SYNC_FLUSH; + else + opdata.flush = WCRYPTO_FINISH; + + out_len = bd_pool[0].dst_len; + + ftuple = malloc(sizeof(COMP_TUPLE_TAG) * MAX_POOL_LENTH); + if (!ftuple) + goto fse_err; + + hw_buff_out = malloc(out_len * MAX_POOL_LENTH); + if (!hw_buff_out) + goto hw_buff_err; + memset(hw_buff_out, 0x0, out_len * MAX_POOL_LENTH); + + while(1) { + i = count % MAX_POOL_LENTH; + opdata.in = bd_pool[i].src; + opdata.out = &hw_buff_out[i]; //temp out + opdata.in_len = bd_pool[i].src_len; + opdata.avail_out = out_len; + opdata.priv = &ftuple[i]; + + ret = wcrypto_do_comp(ctx, &opdata, NULL); + if (ret || opdata.status == WCRYPTO_DECOMP_END_NOSPACE || + opdata.status == WD_IN_EPARA || opdata.status == WD_VERIFY_ERR) + break; + + count++; + zstd_input.src = opdata.in; + zstd_input.size = opdata.in_len; + zstd_input.pos = 0; + zstd_output.dst = bd_pool[i].dst; + zstd_output.size = out_len; + zstd_output.pos = 0; + fse_size = zstd_soft_fse(opdata.priv, &zstd_input, &zstd_output, cctx, ZSTD_e_end); + + bd_pool[i].dst_len = fse_size; + if (unlikely(i == 0)) + first_len = fse_size; + if (get_run_state() == 0) + break; + } + +hw_buff_err: + free(hw_buff_out); +fse_err: + free(ftuple); + wcrypto_del_comp_ctx(ctx); + + // ZIP_TST_PRT("valid pool len: %u, send count BD: %u, output len: %u!\n", + // MAX_POOL_LENTH, count, opdata.produced); + if (pdata->optype == WCRYPTO_DEFLATE) + add_recv_data(count, opdata.in_len); + else + add_recv_data(count, first_len); + + return NULL; +} + +static void *zip_wd_stm_lz77_sync_run(void *arg) +{ + thread_data *pdata = (thread_data *)arg; + ZSTD_CCtx *cctx = zstd_soft_fse_init(15); + ZSTD_inBuffer zstd_input = {0}; + ZSTD_outBuffer zstd_output = {0}; + COMP_TUPLE_TAG *ftuple = NULL; + struct wcrypto_comp_ctx_setup comp_setup; + struct wcrypto_comp_op_data opdata; + struct wcrypto_comp_ctx *ctx; + struct wd_queue *queue; + struct wd_bd *bd_pool; + u8 *hw_buff_out = NULL; + size_t fse_size; + u32 first_len = 0; + u32 out_len = 0; + u32 count = 0; + int ret, i = 0; + + if (pdata->td_id > g_thread_num) + return NULL; + + bd_pool = g_thread_queue.bd_res[pdata->td_id].bds; + queue = g_thread_queue.bd_res[pdata->td_id].queue; + memset(&comp_setup, 0, sizeof(comp_setup)); + memset(&opdata, 0, sizeof(opdata)); + + comp_setup.br.alloc = (void *)wd_alloc_blk; + comp_setup.br.free = (void *)wd_free_blk; + comp_setup.br.iova_map = (void *)wd_blk_iova_map; + comp_setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + comp_setup.br.get_bufsize = (void *)wd_blksize; + comp_setup.br.usr = g_thread_queue.bd_res[pdata->td_id].pool; + + comp_setup.alg_type = pdata->alg; + comp_setup.op_type = pdata->optype; + comp_setup.comp_lv = WCRYPTO_COMP_L8; + comp_setup.win_size = WCRYPTO_COMP_WS_8K; + comp_setup.stream_mode = WCRYPTO_COMP_STATEFUL; + + ctx = wcrypto_create_comp_ctx(queue, &comp_setup); + if (!ctx) + return NULL; + + opdata.stream_pos = WCRYPTO_COMP_STREAM_NEW; + opdata.alg_type = pdata->alg; + opdata.priv = NULL; + opdata.status = 0; + if (pdata->optype == WCRYPTO_INFLATE) + opdata.flush = WCRYPTO_SYNC_FLUSH; + else + opdata.flush = WCRYPTO_FINISH; + + out_len = bd_pool[0].dst_len; + + ftuple = malloc(sizeof(COMP_TUPLE_TAG) * MAX_POOL_LENTH); + if (!ftuple) + goto fse_err; + + hw_buff_out = malloc(out_len * MAX_POOL_LENTH); + if (!hw_buff_out) + goto hw_buff_err; + memset(hw_buff_out, 0x0, out_len * MAX_POOL_LENTH); + + while(1) { + i = count % MAX_POOL_LENTH; + opdata.in = bd_pool[i].src; + opdata.out = &hw_buff_out[i]; //temp out + opdata.in_len = bd_pool[i].src_len; + opdata.avail_out = out_len; + opdata.priv = &ftuple[i]; + + ret = wcrypto_do_comp(ctx, &opdata, NULL); + if (ret || opdata.status == WCRYPTO_DECOMP_END_NOSPACE || + opdata.status == WD_IN_EPARA || opdata.status == WD_VERIFY_ERR) { + ZIP_TST_PRT("wd comp, invalid or incomplete data! " + "ret(%d), req.status(%u)\n", ret, opdata.status); + break; + } + + count++; + zstd_input.src = opdata.in; + zstd_input.size = opdata.in_len; + zstd_input.pos = 0; + zstd_output.dst = opdata.out; + zstd_output.size = out_len; + zstd_output.pos = 0; + fse_size = zstd_soft_fse(opdata.priv, &zstd_input, &zstd_output, cctx, ZSTD_e_end); + + bd_pool[i].dst_len = fse_size; + if (unlikely(i == 0)) + first_len = fse_size; + if (get_run_state() == 0) + break; + } + +hw_buff_err: + free(hw_buff_out); +fse_err: + free(ftuple); + wcrypto_del_comp_ctx(ctx); + + // ZIP_TST_PRT("valid pool len: %u, send count BD: %u, output len: %u!\n", + // MAX_POOL_LENTH, count, opdata.produced); + if (pdata->optype == WCRYPTO_DEFLATE) + add_recv_data(count, opdata.in_len); + else + add_recv_data(count, first_len); + + return NULL; +} + +static void *zip_wd_blk_lz77_async_run(void *arg) +{ + thread_data *pdata = (thread_data *)arg; + ZSTD_CCtx *cctx = zstd_soft_fse_init(15); + COMP_TUPLE_TAG *ftuple = NULL; + struct wcrypto_comp_ctx_setup comp_setup; + struct wcrypto_comp_op_data opdata; + struct wcrypto_comp_ctx *ctx; + struct zip_async_tag *tag; + u8 *hw_buff_out = NULL; + struct wd_queue *queue; + struct wd_bd *bd_pool; + u32 out_len = 0; + u32 count = 0; + u32 try_cnt = 0; + int ret, i = 0; + + if (pdata->td_id > g_thread_num) + return NULL; + + bd_pool = g_thread_queue.bd_res[pdata->td_id].bds; + queue = g_thread_queue.bd_res[pdata->td_id].queue; + memset(&comp_setup, 0, sizeof(comp_setup)); + memset(&opdata, 0, sizeof(opdata)); + + comp_setup.br.alloc = (void *)wd_alloc_blk; + comp_setup.br.free = (void *)wd_free_blk; + comp_setup.br.iova_map = (void *)wd_blk_iova_map; + comp_setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + comp_setup.br.get_bufsize = (void *)wd_blksize; + comp_setup.br.usr = g_thread_queue.bd_res[pdata->td_id].pool; + + comp_setup.alg_type = pdata->alg; + comp_setup.op_type = pdata->optype; + comp_setup.comp_lv = WCRYPTO_COMP_L8; + comp_setup.win_size = WCRYPTO_COMP_WS_8K; + comp_setup.stream_mode = WCRYPTO_COMP_STATELESS; + comp_setup.cb = zip_lz77_async_cb; + + ctx = wcrypto_create_comp_ctx(queue, &comp_setup); + if (!ctx) + return NULL; + + opdata.stream_pos = WCRYPTO_COMP_STREAM_NEW; + opdata.alg_type = pdata->alg; + opdata.priv = NULL; + opdata.status = 0; + if (pdata->optype == WCRYPTO_INFLATE) + opdata.flush = WCRYPTO_SYNC_FLUSH; + else + opdata.flush = WCRYPTO_FINISH; + + out_len = bd_pool[0].dst_len; + + ftuple = malloc(sizeof(COMP_TUPLE_TAG) * MAX_POOL_LENTH); + if (!ftuple) + goto fse_err; + + hw_buff_out = malloc(out_len * MAX_POOL_LENTH); + if (!hw_buff_out) + goto hw_buff_err; + memset(hw_buff_out, 0x0, out_len * MAX_POOL_LENTH); + + tag = malloc(sizeof(*tag) * MAX_POOL_LENTH); + if (!tag) { + ZIP_TST_PRT("failed to malloc zip tag!\n"); + goto tag_err; + } + + while(1) { + if (get_run_state() == 0) + break; + + try_cnt = 0; + i = count % MAX_POOL_LENTH; + opdata.in = bd_pool[i].src; + opdata.out = &hw_buff_out[i]; //temp out + opdata.in_len = bd_pool[i].src_len; + opdata.avail_out = out_len; + opdata.priv = &ftuple[i]; + + tag[i].td_id = pdata->td_id; + tag[i].ctx = ctx; + tag[i].td_id = pdata->td_id; + tag[i].cm_len = out_len; + tag[i].cctx = cctx; + tag[i].priv = opdata.priv; + + ret = wcrypto_do_comp(ctx, &opdata, &tag[i]); + if (ret == -WD_EBUSY) { + usleep(SEND_USLEEP * try_cnt); + try_cnt++; + if (try_cnt > MAX_TRY_CNT) { + ZIP_TST_PRT("Test LZ77 compress send fail %d times!\n", MAX_TRY_CNT); + try_cnt = 0; + } + continue; + } else if (ret || opdata.status == WCRYPTO_DECOMP_END_NOSPACE || + opdata.status == WD_IN_EPARA || opdata.status == WD_VERIFY_ERR) { + break; + } + count++; + } + + while (1) { + if (get_recv_time() > 0) // wait Async mode finish recv + break; + usleep(SEND_USLEEP); + } + +tag_err: + free(tag); +hw_buff_err: + free(hw_buff_out); +fse_err: + free(ftuple); + wcrypto_del_comp_ctx(ctx); + + // ZIP_TST_PRT("LZ77 valid pool len: %u, send count BD: %u, output len: %u!\n", + // MAX_POOL_LENTH, count, opdata.produced); + + add_send_complete(); + + return NULL; +} + +static void *zip_wd_blk_sync_run(void *arg) +{ + thread_data *pdata = (thread_data *)arg; + struct wcrypto_comp_ctx_setup comp_setup; + struct wcrypto_comp_op_data opdata; + struct wcrypto_comp_ctx *ctx; + struct wd_queue *queue; + struct wd_bd *bd_pool; + u32 out_len = 0; + u32 count = 0; + int ret, i = 0; + + if (pdata->td_id > g_thread_num) + return NULL; + + bd_pool = g_thread_queue.bd_res[pdata->td_id].bds; + queue = g_thread_queue.bd_res[pdata->td_id].queue; + memset(&comp_setup, 0, sizeof(comp_setup)); + memset(&opdata, 0, sizeof(opdata)); + + comp_setup.br.alloc = (void *)wd_alloc_blk; + comp_setup.br.free = (void *)wd_free_blk; + comp_setup.br.iova_map = (void *)wd_blk_iova_map; + comp_setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + comp_setup.br.get_bufsize = (void *)wd_blksize; + comp_setup.br.usr = g_thread_queue.bd_res[pdata->td_id].pool; + + comp_setup.alg_type = pdata->alg; + comp_setup.op_type = pdata->optype; + comp_setup.comp_lv = WCRYPTO_COMP_L8; + comp_setup.win_size = WCRYPTO_COMP_WS_8K; + comp_setup.stream_mode = WCRYPTO_COMP_STATELESS; + + ctx = wcrypto_create_comp_ctx(queue, &comp_setup); + if (!ctx) + return NULL; + + opdata.stream_pos = WCRYPTO_COMP_STREAM_NEW; + opdata.alg_type = pdata->alg; + opdata.priv = NULL; + opdata.status = 0; + if (pdata->optype == WCRYPTO_INFLATE) + opdata.flush = WCRYPTO_SYNC_FLUSH; + else + opdata.flush = WCRYPTO_FINISH; + + out_len = bd_pool[0].dst_len; + + while(1) { + i = count % MAX_POOL_LENTH; + opdata.in = bd_pool[i].src; + opdata.out = bd_pool[i].dst; + opdata.in_len = bd_pool[i].src_len; + opdata.avail_out = out_len; + + ret = wcrypto_do_comp(ctx, &opdata, NULL); + if (ret || opdata.status == WCRYPTO_DECOMP_END_NOSPACE || + opdata.status == WD_IN_EPARA || opdata.status == WD_VERIFY_ERR) + break; + + count++; + bd_pool[i].dst_len = opdata.produced; + if (get_run_state() == 0) + break; + } + wcrypto_del_comp_ctx(ctx); + + // ZIP_TST_PRT("valid pool len: %u, send count BD: %u, output len: %u!\n", + // MAX_POOL_LENTH, count, opdata.produced); + add_recv_data(count, g_pktlen); + + return NULL; +} + +static void *zip_wd_stm_sync_run(void *arg) +{ + thread_data *pdata = (thread_data *)arg; + struct wcrypto_comp_ctx_setup comp_setup; + struct wcrypto_comp_op_data opdata; + struct wcrypto_comp_ctx *ctx; + struct wd_queue *queue; + struct wd_bd *bd_pool; + u32 out_len = 0; + u32 count = 0; + int ret, i = 0; + + if (pdata->td_id > g_thread_num) + return NULL; + + bd_pool = g_thread_queue.bd_res[pdata->td_id].bds; + queue = g_thread_queue.bd_res[pdata->td_id].queue; + memset(&comp_setup, 0, sizeof(comp_setup)); + memset(&opdata, 0, sizeof(opdata)); + + comp_setup.br.alloc = (void *)wd_alloc_blk; + comp_setup.br.free = (void *)wd_free_blk; + comp_setup.br.iova_map = (void *)wd_blk_iova_map; + comp_setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + comp_setup.br.get_bufsize = (void *)wd_blksize; + comp_setup.br.usr = g_thread_queue.bd_res[pdata->td_id].pool; + + comp_setup.alg_type = pdata->alg; + comp_setup.op_type = pdata->optype; + comp_setup.comp_lv = WCRYPTO_COMP_L8; + comp_setup.win_size = WCRYPTO_COMP_WS_8K; + comp_setup.stream_mode = WCRYPTO_COMP_STATEFUL; + + ctx = wcrypto_create_comp_ctx(queue, &comp_setup); + if (!ctx) + return NULL; + + opdata.stream_pos = WCRYPTO_COMP_STREAM_NEW; + opdata.alg_type = pdata->alg; + opdata.priv = NULL; + opdata.status = 0; + if (pdata->optype == WCRYPTO_INFLATE) + opdata.flush = WCRYPTO_SYNC_FLUSH; + else + opdata.flush = WCRYPTO_FINISH; + + out_len = bd_pool[0].dst_len; + + while(1) { + i = count % MAX_POOL_LENTH; + opdata.in = bd_pool[i].src; + opdata.out = bd_pool[i].dst; + opdata.in_len = bd_pool[i].src_len; + opdata.avail_out = out_len; + + ret = wcrypto_do_comp(ctx, &opdata, NULL); + if (ret || opdata.status == WCRYPTO_DECOMP_END_NOSPACE || + opdata.status == WD_IN_EPARA || opdata.status == WD_VERIFY_ERR) { + ZIP_TST_PRT("wd comp, invalid or incomplete data! " + "ret(%d), req.status(%u)\n", ret, opdata.status); + break; + } + + count++; + bd_pool[i].dst_len = opdata.produced; + if (get_run_state() == 0) + break; + } + wcrypto_del_comp_ctx(ctx); + + // ZIP_TST_PRT("valid pool len: %u, send count BD: %u, output len: %u!\n", + // MAX_POOL_LENTH, count, opdata.produced); + add_recv_data(count, g_pktlen); + + return NULL; + +} + +static void *zip_wd_blk_async_run(void *arg) +{ + thread_data *pdata = (thread_data *)arg; + struct wcrypto_comp_ctx_setup comp_setup; + struct wcrypto_comp_op_data opdata; + struct wcrypto_comp_ctx *ctx; + struct zip_async_tag *tag; + struct wd_queue *queue; + struct wd_bd *bd_pool; + int try_cnt = 0; + u32 out_len = 0; + u32 count = 0; + int ret, i = 0; + + if (pdata->td_id > g_thread_num) + return NULL; + + bd_pool = g_thread_queue.bd_res[pdata->td_id].bds; + queue = g_thread_queue.bd_res[pdata->td_id].queue; + memset(&comp_setup, 0, sizeof(comp_setup)); + memset(&opdata, 0, sizeof(opdata)); + + comp_setup.br.alloc = (void *)wd_alloc_blk; + comp_setup.br.free = (void *)wd_free_blk; + comp_setup.br.iova_map = (void *)wd_blk_iova_map; + comp_setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + comp_setup.br.get_bufsize = (void *)wd_blksize; + comp_setup.br.usr = g_thread_queue.bd_res[pdata->td_id].pool; + + comp_setup.alg_type = pdata->alg; + comp_setup.op_type = pdata->optype; + comp_setup.comp_lv = WCRYPTO_COMP_L8; + comp_setup.win_size = WCRYPTO_COMP_WS_8K; + comp_setup.stream_mode = WCRYPTO_COMP_STATELESS; + comp_setup.cb = zip_async_cb; + + ctx = wcrypto_create_comp_ctx(queue, &comp_setup); + if (!ctx) + return NULL; + + opdata.stream_pos = WCRYPTO_COMP_STREAM_NEW; + opdata.alg_type = pdata->alg; + opdata.priv = NULL; + opdata.status = 0; + if (pdata->optype == WCRYPTO_INFLATE) + opdata.flush = WCRYPTO_SYNC_FLUSH; + else + opdata.flush = WCRYPTO_FINISH; + + out_len = bd_pool[0].dst_len; + tag = malloc(sizeof(*tag) * MAX_POOL_LENTH); + if (!tag) { + ZIP_TST_PRT("failed to malloc zip tag!\n"); + goto tag_release; + } + + while(1) { + if (get_run_state() == 0) + break; + + i = count % MAX_POOL_LENTH; + opdata.in = bd_pool[i].src; + opdata.out = bd_pool[i].dst; + opdata.in_len = bd_pool[i].src_len; + opdata.avail_out = out_len; + + try_cnt = 0; + tag[i].ctx = ctx; + tag[i].td_id = pdata->td_id; + tag[i].bd_idx = i; + + ret = wcrypto_do_comp(ctx, &opdata, &tag[i]); + if (ret == -WD_EBUSY) { + usleep(SEND_USLEEP * try_cnt); + try_cnt++; + if (try_cnt > MAX_TRY_CNT) { + ZIP_TST_PRT("Test compress send fail %d times!\n", MAX_TRY_CNT); + try_cnt = 0; + } + continue; + } else if (ret || opdata.status == WCRYPTO_DECOMP_END_NOSPACE || + opdata.status == WD_IN_EPARA || opdata.status == WD_VERIFY_ERR) { + break; + } + + count++; + } + + while (1) { + if (get_recv_time() > 0) // wait Async mode finish recv + break; + usleep(SEND_USLEEP); + } + +tag_release: + free(tag); + wcrypto_del_comp_ctx(ctx); + + // ZIP_TST_PRT("valid pool len: %u, send count BD: %u, output len: %u!\n", + // MAX_POOL_LENTH, count, opdata.produced); + + add_send_complete(); + + return NULL; +} + +static int zip_wd_sync_threads(struct acc_option *options) +{ + typedef void *(*zip_sync_run)(void *arg); + zip_sync_run wd_zip_sync_run = NULL; + thread_data threads_args[THREADS_NUM]; + thread_data threads_option; + pthread_t tdid[THREADS_NUM]; + int i, ret; + + /* alg param parse and set to thread data */ + ret = zip_wd_param_parse(&threads_option, options); + if (ret) + return ret; + + if (threads_option.mode == 1) {// stream mode + if (threads_option.alg == LZ77_ZSTD) + wd_zip_sync_run = zip_wd_stm_lz77_sync_run; + else + wd_zip_sync_run = zip_wd_stm_sync_run; + } else { + if (threads_option.alg == LZ77_ZSTD) + wd_zip_sync_run = zip_wd_blk_lz77_sync_run; + else + wd_zip_sync_run = zip_wd_blk_sync_run; + } + + for (i = 0; i < g_thread_num; i++) { + threads_args[i].alg = threads_option.alg; + threads_args[i].mode = threads_option.mode; + threads_args[i].optype = threads_option.optype; + threads_args[i].td_id = i; + ret = pthread_create(&tdid[i], NULL, wd_zip_sync_run, &threads_args[i]); + if (ret) { + ZIP_TST_PRT("Create sync thread fail!\n"); + goto sync_error; + } + } + + /* join thread */ + for (i = 0; i < g_thread_num; i++) { + ret = pthread_join(tdid[i], NULL); + if (ret) { + ZIP_TST_PRT("Join sync thread fail!\n"); + goto sync_error; + } + } + +sync_error: + return ret; +} + +static int zip_wd_async_threads(struct acc_option *options) +{ + typedef void *(*zip_async_run)(void *arg); + zip_async_run wd_zip_async_run = NULL; + thread_data threads_args[THREADS_NUM]; + thread_data threads_option; + pthread_t tdid[THREADS_NUM]; + pthread_t pollid[THREADS_NUM]; + int i, ret; + + /* alg param parse and set to thread data */ + ret = zip_wd_param_parse(&threads_option, options); + if (ret) + return ret; + + if (threads_option.mode == STREAM_MODE) {// stream mode + ZIP_TST_PRT("Stream mode can't support async mode!\n"); + return 0; + } + + if (threads_option.alg == LZ77_ZSTD) + wd_zip_async_run = zip_wd_blk_lz77_async_run; + else + wd_zip_async_run = zip_wd_blk_async_run; + + for (i = 0; i < g_thread_num; i++) { + threads_args[i].td_id = i; + /* poll thread */ + ret = pthread_create(&pollid[i], NULL, zip_wd_poll, &threads_args[i]); + if (ret) { + ZIP_TST_PRT("Create poll thread fail!\n"); + goto async_error; + } + } + + for (i = 0; i < g_thread_num; i++) { + threads_args[i].alg = threads_option.alg; + threads_args[i].mode = threads_option.mode; + threads_args[i].optype = threads_option.optype; + threads_args[i].td_id = i; + ret = pthread_create(&tdid[i], NULL, wd_zip_async_run, &threads_args[i]); + if (ret) { + ZIP_TST_PRT("Create async thread fail!\n"); + goto async_error; + } + } + + /* join thread */ + for (i = 0; i < g_thread_num; i++) { + ret = pthread_join(tdid[i], NULL); + if (ret) { + ZIP_TST_PRT("Join async thread fail!\n"); + goto async_error; + } + } + + for (i = 0; i < g_thread_num; i++) { + ret = pthread_join(pollid[i], NULL); + if (ret) { + ZIP_TST_PRT("Join poll thread fail!\n"); + goto async_error; + } + } + +async_error: + return ret; +} + +int zip_wd_benchmark(struct acc_option *options) +{ + u32 ptime; + int ret; + + g_thread_num = options->threads; + g_pktlen = options->pktlen; + + if (options->optype >= WCRYPTO_DIR_MAX * 2) { + ZIP_TST_PRT("ZIP optype error: %u\n", options->optype); + return -EINVAL; + } + + ret = init_zip_wd_queue(options); + if (ret) + return ret; + + ret = load_file_data(options->algname, options->pktlen, options->optype); + if (ret) + return ret; + + get_pid_cpu_time(&ptime); + time_start(options->times); + if (options->syncmode) + ret = zip_wd_async_threads(options); + else + ret = zip_wd_sync_threads(options); + cal_perfermance_data(options, ptime); + if (ret) + return ret; + + ret = save_file_data(options->algname, options->pktlen, options->optype); + if (ret) + return ret; + + uninit_zip_wd_queue(); + + return 0; +} diff --git a/uadk/uadk_tool/benchmark/zip_wd_benchmark.h b/uadk/uadk_tool/benchmark/zip_wd_benchmark.h new file mode 100644 index 0000000..86ef497 --- /dev/null +++ b/uadk/uadk_tool/benchmark/zip_wd_benchmark.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +#ifndef ZIP_WD_BENCHMARK_H +#define ZIP_WD_BENCHMARK_H + +extern int zip_wd_benchmark(struct acc_option *options); +#endif /* ZIP_WD_BENCHMARK_H */ diff --git a/uadk/uadk_tool/dfx/uadk_dfx.c b/uadk/uadk_tool/dfx/uadk_dfx.c new file mode 100644 index 0000000..796135a --- /dev/null +++ b/uadk/uadk_tool/dfx/uadk_dfx.c @@ -0,0 +1,253 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "include/wd.h" +#include "uadk_dfx.h" + +#define uadk_build_date() printf("built on: %s %s\n", __DATE__, __TIME__) +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#define PRIVILEGE_FLAG 666 + +struct uadk_env_var { + const char *module; + const char *alg; + const char *ctx_num_var; + const char *epoll_en_var; +}; + +struct uadk_env_table { + int sync_ctx_num; + int sync_numa; + int async_ctx_num; + int async_numa; + int poll_en; +}; + +enum dfx_op_type { + DISPLAY_VERSION = 2, + DISPLAY_DATE, + DISPLAY_DIR, + DISPLAY_ENV, + DISPLAY_COUNT, + DISPLAY_HELP, +}; + +const char *uadk_modules[] = {"sec", "hpre", "zip"}; + +const struct uadk_env_var env_vars[] = { + {.module = "sec", .alg = "CIPHER", .ctx_num_var = "WD_CIPHER_CTX_NUM", + .epoll_en_var = "WD_CIPHER_EPOLL_EN"}, + {.module = "sec", .alg = "AEAD", .ctx_num_var = "WD_AEAD_CTX_NUM", + .epoll_en_var = "WD_AEAD_EPOLL_EN"}, + {.module = "sec", .alg = "DIGEST", .ctx_num_var = "WD_DIGEST_CTX_NUM", + .epoll_en_var = "WD_DIGEST_EPOLL_EN"}, + {.module = "hpre", .alg = "DH", .ctx_num_var = "WD_DH_CTX_NUM", + .epoll_en_var = "WD_DH_EPOLL_EN"}, + {.module = "hpre", .alg = "RSA", .ctx_num_var = "WD_RSA_CTX_NUM", + .epoll_en_var = "WD_RSA_EPOLL_EN"}, + {.module = "hpre", .alg = "ECC", .ctx_num_var = "WD_ECC_CTX_NUM", + .epoll_en_var = "WD_ECC_EPOLL_EN"}, + {.module = "zip", .alg = "COMP", .ctx_num_var = "WD_COMP_CTX_NUM", + .epoll_en_var = "WD_COMP_EPOLL_EN"}, +}; + +static void dump_ctx_count(unsigned long *count) +{ + __u32 idx = 0; + int i; + + if (!count) + return; + + printf("displays the ctx counter value...\n"); + for (i = 0; i < WD_CTX_CNT_NUM; i++) { + if (count[i]) { + printf("ctx-[%d]:%lu \t", i, count[i]); + idx++; + } else { + continue; + } + + if ((idx & 0x3) == 0) + printf("\n"); + } + printf("\n"); +} + +static int get_shared_id(void) +{ + int shm; + + shm = shmget(WD_IPC_KEY, sizeof(unsigned long) * WD_CTX_CNT_NUM, + IPC_CREAT | PRIVILEGE_FLAG); + if (shm < 0) { + printf("failed to get the shared memory id.\n"); + return -EINVAL; + } + + return shm; +} + +static int uadk_shared_read(void) +{ + unsigned long *shared; + void *ptr; + int shm; + + shm = get_shared_id(); + if (shm < 0) + return -EINVAL; + + ptr = (int *)shmat(shm, NULL, 0); + if (ptr < 0) { + printf("failed to get the shared memory addr.\n"); + return -EINVAL; + } + + shared = (unsigned long *)ptr; + + printf("get the shared memory addr successful.\n"); + dump_ctx_count(shared); + + shmdt(ptr); + + return 0; +} + +bool uadk_check_module(const char *module) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(uadk_modules); i++) { + if (!strncmp(module, uadk_modules[i], strlen(module))) + return true; + } + + return false; +} + +static void uadk_ctx_env_config(const char *s) +{ + char *env_setion; + + if (!s) { + printf("input ctx env config is NULL.\n"); + return; + } + + env_setion = getenv(s); + if (!env_setion) { + printf("not found the %s env config!\n", s); + return; + } + + printf("%s=%s\n", s, env_setion); +} + +static void uadk_parse_env_config(const char *module) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(env_vars); i++) { + if (!strncmp(module, env_vars[i].module, strlen(module))) { + uadk_ctx_env_config(env_vars[i].ctx_num_var); + uadk_ctx_env_config(env_vars[i].epoll_en_var); + } + } +} + +static void uadk_exe_path(void) +{ + char dir[PATH_MAX] = {0}; + int n; + + n = readlink("/proc/self/exe", dir, PATH_MAX); + if (n < 0 || n >= PATH_MAX) + printf("uadk tool failed to get the exe path.\n"); + + dir[PATH_MAX - 1] = '\0'; + printf("exe path: %s\n", dir); +} + +void print_dfx_help(void) +{ + printf("NAME\n"); + printf(" uadk_tool dfx : uadk library dfx function, etc\n"); + printf("USAGE\n"); + printf(" uadk_tool dfx [--version] = Show library version\n"); + printf(" uadk_tool dfx [--date] = Show build date\n"); + printf(" uadk_tool dfx [--dir] = Show library dir\n"); + printf(" uadk_tool dfx [--env] = Show environment variables\n"); + printf(" uadk_tool dfx [--count] = Show the ctx message count\n"); + printf(" uadk_tool dfx [--help] = usage\n"); + printf("Example\n"); + printf(" uadk_tool dfx --version\n"); + printf(" uadk_tool dfx --env sec\n"); + printf(" uadk_tool dfx --count\n"); +} + +void dfx_cmd_parse(int argc, char *argv[]) +{ + bool check_module = false; + char *input_module = NULL; + int option_index = 0; + int opt; + + static struct option long_options[] = { + {"version", no_argument, 0, 2}, + {"date", no_argument, 0, 3}, + {"dir", no_argument, 0, 4}, + {"env", required_argument, 0, 5}, + {"count", no_argument, 0, 6}, + {"help", no_argument, 0, 7}, + {0, 0, 0, 0} + }; + + while (1) { + opt = getopt_long(argc, argv, "", long_options, &option_index); + if (opt == -1) + break; + + switch (opt) { + case DISPLAY_VERSION: + wd_get_version(); + break; + case DISPLAY_DATE: + uadk_build_date(); + break; + case DISPLAY_DIR: + uadk_exe_path(); + break; + case DISPLAY_ENV: + input_module = optarg; + check_module = uadk_check_module(input_module); + if (check_module) { + uadk_parse_env_config(input_module); + } else { + print_dfx_help(); + printf("failed to parse module parameter!\n"); + } + break; + case DISPLAY_COUNT: + uadk_shared_read(); + break; + case DISPLAY_HELP: + print_dfx_help(); + break; + default: + printf("bad input parameter, exit!\n"); + print_dfx_help(); + break; + } + } +} diff --git a/uadk/uadk_tool/dfx/uadk_dfx.h b/uadk/uadk_tool/dfx/uadk_dfx.h new file mode 100644 index 0000000..8dc1da1 --- /dev/null +++ b/uadk/uadk_tool/dfx/uadk_dfx.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +#ifndef UADK_DFX_H +#define UADK_DFX_H + +void print_dfx_help(void); +void dfx_cmd_parse(int argc, char *argv[]); +#endif diff --git a/uadk/uadk_tool/uadk_tool.c b/uadk/uadk_tool/uadk_tool.c new file mode 100644 index 0000000..ce83d7a --- /dev/null +++ b/uadk/uadk_tool/uadk_tool.c @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include +#include "dfx/uadk_dfx.h" +#include "benchmark/uadk_benchmark.h" + +static void print_tool_help(void) +{ + printf("NAME\n"); + printf("uadk_tool dfx : Show some information for library.\n"); + printf("uadk_tool benchmark : Test UADK acc performance.\n"); +} + +int main(int argc, char **argv) +{ + struct acc_option option = {0}; + int index = 1; + int ret; + + if (argc > index) { + if (!strcmp("dfx", argv[index])) { + dfx_cmd_parse(argc, argv); + } else if (!strcmp("benchmark", argv[index])) { + printf("start UADK benchmark test.\n"); + if (!argv[++index]) + acc_default_case(&option); + + ret = acc_cmd_parse(argc, argv, &option); + if (ret) + return ret; + + ret = acc_option_convert(&option); + if (ret) + return ret; + (void)acc_benchmark_run(&option); + } else { + print_tool_help(); + } + } else { + print_tool_help(); + } + + return 0; +} diff --git a/uadk/v1/LICENSE b/uadk/v1/LICENSE new file mode 100644 index 0000000..aeb43d2 --- /dev/null +++ b/uadk/v1/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + https://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. \ No newline at end of file diff --git a/uadk/v1/drv/dummy_drv.c b/uadk/v1/drv/dummy_drv.c new file mode 100644 index 0000000..b1c1968 --- /dev/null +++ b/uadk/v1/drv/dummy_drv.c @@ -0,0 +1,174 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "v1/wd_util.h" +#include "dummy_drv.h" + +#define QM_VERSION_V1 1 +#define QM_VERSION_V2 2 + +struct dummy_q_priv { + int ver; + int head; /* queue head */ + int resp_tail; /* resp tail in the queue */ + /* so in the user side: when add to queue, head++ but don't exceed resp_tail. + * when get back from the queue, resp_tail++ but don't exceed tail. + * in the kernel side: when get from queue, tail++ but don't exceed head-1 */ + + struct dummy_hw_queue_reg *reg; + uint64_t *db; +}; + +int dummy_set_queue_dio(struct wd_queue *q) +{ + int ret = 0; + struct dummy_q_priv *priv; + struct q_info *qinfo = q->qinfo; + + priv = calloc(1, sizeof(*priv)); + if (!priv) { + DUMMY_ERR("No memory for dummy queue!\n"); + ret = -ENOMEM; + goto out; + } + + qinfo->priv = priv; + priv->ver = qinfo->qfrs_offset[WD_UACCE_QFRT_DUS] == + WD_UACCE_QFRT_INVALID ? + QM_VERSION_V1 : QM_VERSION_V2; + + if (priv->ver == QM_VERSION_V2) { + priv->db = wd_drv_mmap_qfr(q, WD_UACCE_QFRT_MMIO, 0); + if (priv->db == MAP_FAILED) { + DUMMY_ERR("mmap db fail (%d)\n", errno); + goto out_with_priv; + } + } + + priv->reg = wd_drv_mmap_qfr(q, priv->ver == QM_VERSION_V1 ? + WD_UACCE_QFRT_MMIO : WD_UACCE_QFRT_DUS, 0); + if (priv->reg == MAP_FAILED) { + DUMMY_ERR("mmap bd fail (%d)\n", errno); + goto out_with_db_map; + } + + /* detect hardware for v1 (v2 can be detected only after start) */ + if (priv->ver == QM_VERSION_V1 && + memcmp(priv->reg->hw_tag, DUMMY_HW_TAG, DUMMY_HW_TAG_SZ)) { + DUMMY_ERR("hw detection fail\n"); + goto out_with_bd_map; + } + + return 0; + +out_with_bd_map: + if (priv->ver == QM_VERSION_V1) + wd_drv_unmmap_qfr(q, priv->reg, WD_UACCE_QFRT_MMIO, 0); + else + wd_drv_unmmap_qfr(q, priv->reg, WD_UACCE_QFRT_DUS, 0); +out_with_db_map: + if (priv->ver == QM_VERSION_V2) + wd_drv_unmmap_qfr(q, priv->db, WD_UACCE_QFRT_MMIO, 0); +out_with_priv: + free(priv); + qinfo->priv = NULL; +out: + if (errno) + ret = errno; + else + ret = -EIO; + return ret; +} + +void dummy_unset_queue_dio(struct wd_queue *q) +{ + struct q_info *qinfo = q->qinfo; + struct dummy_q_priv *priv = (struct dummy_q_priv *)qinfo->priv; + + ASSERT(priv); + + munmap(priv->reg, sizeof(struct dummy_hw_queue_reg)); + free(priv); + qinfo->priv = NULL; +} + +int dummy_add_to_dio_q(struct wd_queue *q, void **req, __u32 num) +{ + struct q_info *qinfo = q->qinfo; + struct dummy_q_priv *priv = (struct dummy_q_priv *)qinfo->priv; + int bd_num; + + ASSERT(priv); + + bd_num = priv->reg->ring_bd_num; + + if ((priv->head + 1) % bd_num == priv->resp_tail) + return -EBUSY; /* the queue is full */ + else { + priv->reg->ring[priv->head] = *((struct ring_bd *)(req[0])); + priv->reg->ring[priv->head].ptr = req[0]; + priv->head = (priv->head + 1) % bd_num; + wd_reg_write(&priv->reg->head, priv->head); + printf("add to queue, new head=%d, %d\n", priv->head, priv->reg->head); + + if (priv->ver == QM_VERSION_V2) + wd_reg_write(priv->db, 1); + } + + return 0; +} + +int dummy_get_from_dio_q(struct wd_queue *q, void **resp, __u32 num) +{ + struct q_info *qinfo = q->qinfo; + struct dummy_q_priv *priv = (struct dummy_q_priv *)qinfo->priv; + int bd_num = priv->reg->ring_bd_num; + int ret; + int tail; + + ASSERT(priv); + + tail = wd_reg_read(&priv->reg->tail); + printf("get queue tail=%d,%d\n", tail, priv->resp_tail); + if (priv->resp_tail == tail) { + return -EBUSY; + } else { + ret = priv->reg->ring[priv->resp_tail].ret; + *resp = priv->reg->ring[priv->resp_tail].ptr; + priv->resp_tail = (priv->resp_tail + 1) % bd_num; + printf("get resp %d, %d\n", ret, priv->resp_tail); + return ret; + } +} + +void dummy_flush(struct wd_queue *q) +{ + struct q_info *qinfo = q->qinfo; + struct dummy_q_priv *priv = (struct dummy_q_priv *)qinfo->priv; + + if (priv->ver == QM_VERSION_V1) + ioctl(qinfo->fd, DUMMY_CMD_FLUSH); + else + wd_reg_write(priv->db, 1); +} diff --git a/uadk/v1/drv/dummy_drv.h b/uadk/v1/drv/dummy_drv.h new file mode 100644 index 0000000..392a47e --- /dev/null +++ b/uadk/v1/drv/dummy_drv.h @@ -0,0 +1,35 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#ifndef __DUMMY_DRV_H__ +#define __DUMMY_DRV_H__ + +#include "v1/internal/wd_dummy_usr_if.h" +#include "v1/internal/dummy_hw_usr_if.h" +#include "v1/wd.h" + +#ifndef DUMMY_ERR +#define DUMMY_ERR(format, args...) printf(format, ##args) +#endif + +int dummy_set_queue_dio(struct wd_queue *q); +void dummy_unset_queue_dio(struct wd_queue *q); +int dummy_add_to_dio_q(struct wd_queue *q, void **req, __u32 num); +int dummy_get_from_dio_q(struct wd_queue *q, void **resp, __u32 num); +void dummy_flush(struct wd_queue *q); +void *dummy_reserve_mem(struct wd_queue *q, size_t size); + +#endif diff --git a/uadk/v1/drv/hisi_hpre_udrv.c b/uadk/v1/drv/hisi_hpre_udrv.c new file mode 100644 index 0000000..4a97917 --- /dev/null +++ b/uadk/v1/drv/hisi_hpre_udrv.c @@ -0,0 +1,2483 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "config.h" +#include "v1/wd_util.h" +#include "hisi_hpre_udrv.h" + +#define MAX_WAIT_CNT 10000000 +#define SM2_KEY_SIZE 32 +#define MAX_HASH_LENS BITS_TO_BYTES(521) +#define HW_PLAINTEXT_BYTES_MAX BITS_TO_BYTES(4096) + +/* realize with hardware ecc multiplication, avoid conflict with wd_ecc.h */ +#define HPRE_SM2_ENC 0xE +#define HPRE_SM2_DEC 0xF + +#define SM2_SQE_NUM 2 + +static bool is_hpre_bin_fmt(const char *data, int dsz, int bsz) +{ + const char *temp = data + dsz; + int lens = bsz - dsz; + int i = 0; + + while (i < lens) { + if (temp[i] && !data[i]) + return true; + i++; + } + + return false; +} + +static int qm_crypto_bin_to_hpre_bin(char *dst, const char *src, + int b_size, int d_size, const char *p_name) +{ + int i = d_size - 1; + bool is_hpre_bin; + int j; + + if (unlikely(!dst || !src || b_size <= 0 || d_size <= 0)) { + WD_ERR("%s trans to hpre bin: parameters err!\n", p_name); + return -WD_EINVAL; + } + + if (unlikely(b_size < d_size)) { + WD_ERR("%s trans to hpre bin: parameter data is too long!\n", p_name); + return -WD_EINVAL; + } + + is_hpre_bin = is_hpre_bin_fmt(src, d_size, b_size); + if (b_size == d_size || (dst == src && is_hpre_bin)) + return WD_SUCCESS; + + for (j = b_size - 1; j >= 0; j--, i--) { + if (i >= 0) + dst[j] = src[i]; + else + dst[j] = 0; + } + return WD_SUCCESS; +} + +static int qm_hpre_bin_to_crypto_bin(char *dst, const char *src, int b_size, + const char *p_name) +{ + int i, cnt; + int j = 0; + int k = 0; + + if (unlikely(!dst || !src || b_size <= 0)) { + WD_ERR("%s trans to crypto bin: parameters err!\n", p_name); + return 0; + } + + while (!src[j] && k < b_size - 1) + k = ++j; + + if (!j && src == dst) + return b_size; + + for (i = 0, cnt = j; i < b_size; j++, i++) { + if (i < b_size - cnt) + dst[i] = src[j]; + else + dst[i] = 0; + } + + return b_size - k; +} + +static int qm_fill_rsa_crt_prikey2(struct wcrypto_rsa_prikey *prikey, + void **data) +{ + struct wd_dtb *wd_qinv = NULL; + struct wd_dtb *wd_dq = NULL; + struct wd_dtb *wd_dp = NULL; + struct wd_dtb *wd_q = NULL; + struct wd_dtb *wd_p = NULL; + int ret; + + wcrypto_get_rsa_crt_prikey_params(prikey, &wd_dq, &wd_dp, + &wd_qinv, &wd_q, &wd_p); + if (unlikely(!wd_dq || !wd_dp || !wd_qinv || !wd_q || !wd_p)) { + WD_ERR("failed to get rsa crt prikey params!\n"); + return -WD_EINVAL; + } + + ret = qm_crypto_bin_to_hpre_bin(wd_dq->data, (const char *)wd_dq->data, + wd_dq->bsize, wd_dq->dsize, "rsa crt dq"); + if (unlikely(ret)) + return ret; + + ret = qm_crypto_bin_to_hpre_bin(wd_dp->data, (const char *)wd_dp->data, + wd_dp->bsize, wd_dp->dsize, "rsa crt dp"); + if (unlikely(ret)) + return ret; + + ret = qm_crypto_bin_to_hpre_bin(wd_q->data, (const char *)wd_q->data, + wd_q->bsize, wd_q->dsize, "rsa crt q"); + if (unlikely(ret)) + return ret; + + ret = qm_crypto_bin_to_hpre_bin(wd_p->data, + (const char *)wd_p->data, wd_p->bsize, wd_p->dsize, "rsa crt p"); + if (unlikely(ret)) + return ret; + + ret = qm_crypto_bin_to_hpre_bin(wd_qinv->data, + (const char *)wd_qinv->data, wd_qinv->bsize, + wd_qinv->dsize, "rsa crt qinv"); + if (unlikely(ret)) + return ret; + + *data = wd_dq->data; + return (int)(wd_dq->bsize + wd_qinv->bsize + wd_p->bsize + + wd_q->bsize + wd_dp->bsize); +} + +static int qm_fill_rsa_prikey1(struct wcrypto_rsa_prikey *prikey, void **data) +{ + struct wd_dtb *wd_d = NULL; + struct wd_dtb *wd_n = NULL; + int ret; + + wcrypto_get_rsa_prikey_params(prikey, &wd_d, &wd_n); + if (unlikely(!wd_d || !wd_n)) { + WD_ERR("failed to get rsa prikey params!\n"); + return -WD_EINVAL; + } + + ret = qm_crypto_bin_to_hpre_bin(wd_d->data, (const char *)wd_d->data, + wd_d->bsize, wd_d->dsize, "rsa prikey1 d"); + if (unlikely(ret)) + return ret; + + ret = qm_crypto_bin_to_hpre_bin(wd_n->data, (const char *)wd_n->data, + wd_n->bsize, wd_n->dsize, "rsa prikey1 n"); + if (unlikely(ret)) + return ret; + + *data = wd_d->data; + return (int)(wd_n->bsize + wd_d->bsize); +} + +static int qm_fill_rsa_pubkey(struct wcrypto_rsa_pubkey *pubkey, void **data) +{ + struct wd_dtb *wd_e = NULL; + struct wd_dtb *wd_n = NULL; + int ret; + + wcrypto_get_rsa_pubkey_params(pubkey, &wd_e, &wd_n); + ret = qm_crypto_bin_to_hpre_bin(wd_e->data, (const char *)wd_e->data, + wd_e->bsize, wd_e->dsize, "rsa pubkey e"); + if (unlikely(ret)) + return ret; + + ret = qm_crypto_bin_to_hpre_bin(wd_n->data, (const char *)wd_n->data, + wd_n->bsize, wd_n->dsize, "rsa pubkey n"); + if (unlikely(ret)) + return ret; + + *data = wd_e->data; + return (int)(wd_n->bsize + wd_e->bsize); +} + +static int qm_fill_rsa_genkey_in(struct wcrypto_rsa_kg_in *genkey) +{ + struct wd_dtb e = {0}; + struct wd_dtb q = {0}; + struct wd_dtb p = {0}; + int ret; + + wcrypto_get_rsa_kg_in_params(genkey, &e, &q, &p); + ret = qm_crypto_bin_to_hpre_bin(e.data, (const char *)e.data, + e.bsize, e.dsize, "rsa kg e"); + if (unlikely(ret)) + return ret; + + ret = qm_crypto_bin_to_hpre_bin(q.data, (const char *)q.data, + q.bsize, q.dsize, "rsa kg q"); + if (unlikely(ret)) + return ret; + + ret = qm_crypto_bin_to_hpre_bin(p.data, (const char *)p.data, + p.bsize, p.dsize, "rsa kg p"); + if (unlikely(ret)) + return ret; + + return WD_SUCCESS; +} + +static int qm_tri_bin_transfer(struct wd_dtb *bin0, struct wd_dtb *bin1, + struct wd_dtb *bin2, const char *p_name) +{ + int ret; + + ret = qm_hpre_bin_to_crypto_bin(bin0->data, (const char *)bin0->data, + bin0->bsize, p_name); + if (unlikely(!ret)) + return -WD_EINVAL; + + bin0->dsize = ret; + + if (bin1) { + ret = qm_hpre_bin_to_crypto_bin(bin1->data, + (const char *)bin1->data, bin1->bsize, p_name); + if (unlikely(!ret)) + return -WD_EINVAL; + + bin1->dsize = ret; + } + + if (bin2) { + ret = qm_hpre_bin_to_crypto_bin(bin2->data, + (const char *)bin2->data, bin2->bsize, p_name); + if (unlikely(!ret)) + return -WD_EINVAL; + + bin2->dsize = ret; + } + + return WD_SUCCESS; +} + +static int qm_rsa_out_transfer(struct wcrypto_rsa_msg *msg, + struct hisi_hpre_sqe *hw_msg, + size_t *in_len, + size_t *out_len) +{ + struct wcrypto_rsa_kg_out *key = (void *)msg->out; + __u16 kbytes = msg->key_bytes; + struct wd_dtb qinv = {0}; + struct wd_dtb dq = {0}; + struct wd_dtb dp = {0}; + struct wd_dtb d = {0}; + struct wd_dtb n = {0}; + int ret; + + msg->result = WD_SUCCESS; + if (hw_msg->alg == HPRE_ALG_KG_CRT) { + msg->out_bytes = CRT_GEN_PARAMS_SZ(kbytes); + *in_len = GEN_PARAMS_SZ(kbytes); + *out_len = msg->out_bytes; + wcrypto_get_rsa_kg_out_crt_params(key, &qinv, &dq, &dp); + ret = qm_tri_bin_transfer(&qinv, &dq, &dp, "rsa kg qinv&dp&dq"); + if (unlikely(ret)) + return ret; + + wcrypto_set_rsa_kg_out_crt_psz(key, qinv.dsize, + dq.dsize, dp.dsize); + } else if (hw_msg->alg == HPRE_ALG_KG_STD) { + msg->out_bytes = GEN_PARAMS_SZ(kbytes); + *out_len = msg->out_bytes; + *in_len = GEN_PARAMS_SZ(kbytes); + + wcrypto_get_rsa_kg_out_params(key, &d, &n); + ret = qm_tri_bin_transfer(&d, &n, NULL, "rsa kg d & n"); + if (unlikely(ret)) + return ret; + + wcrypto_set_rsa_kg_out_psz(key, d.dsize, n.dsize); + } else { + *in_len = kbytes; + msg->out_bytes = kbytes; + *out_len = msg->out_bytes; + } + return WD_SUCCESS; +} + +static void rsa_key_unmap(struct wcrypto_rsa_msg *msg, struct wd_queue *q, + struct hisi_hpre_sqe *hw_msg, + const void *va, int size) +{ + struct wcrypto_rsa_kg_out *key = (void *)msg->key; + uintptr_t phy; + + phy = DMA_ADDR(hw_msg->low_key, hw_msg->hi_key); + phy -= (uintptr_t)va - (uintptr_t)key; + + drv_iova_unmap(q, msg->key, (void *)phy, size); +} + +static int rsa_prepare_sign_key(struct wcrypto_rsa_msg *msg, struct wd_queue *q, + struct hisi_hpre_sqe *hw_msg, void **va) +{ + void *data = NULL; + int ret; + + if (hw_msg->alg == HPRE_ALG_NC_CRT) { + ret = qm_fill_rsa_crt_prikey2((void *)msg->key, &data); + if (unlikely(ret <= 0)) + return 0; + } else { + ret = qm_fill_rsa_prikey1((void *)msg->key, &data); + if (unlikely(ret <= 0)) + return 0; + hw_msg->alg = HPRE_ALG_NC_NCRT; + } + + *va = data; + + return ret; +} + +static int rsa_prepare_kg_key(struct wcrypto_rsa_msg *msg, struct wd_queue *q, + struct hisi_hpre_sqe *hw_msg, void **va) +{ + void *data = NULL; + int ret; + + ret = qm_fill_rsa_genkey_in((void *)msg->key); + if (unlikely(ret)) + return 0; + + ret = wcrypto_rsa_kg_in_data((void *)msg->key, (char **)&data); + if (unlikely(ret <= 0)) { + WD_ERR("Get rsa gen key data in fail!\n"); + return 0; + } + if (hw_msg->alg == HPRE_ALG_NC_CRT) + hw_msg->alg = HPRE_ALG_KG_CRT; + else + hw_msg->alg = HPRE_ALG_KG_STD; + + *va = data; + + return ret; +} + +static int qm_rsa_prepare_key(struct wcrypto_rsa_msg *msg, struct wd_queue *q, + struct hisi_hpre_sqe *hw_msg, + void **va, int *size) +{ + void *data = NULL; + uintptr_t phy; + int ret; + + if (msg->op_type == WCRYPTO_RSA_SIGN) { + ret = rsa_prepare_sign_key(msg, q, hw_msg, &data); + if (unlikely(ret <= 0)) + return -WD_EINVAL; + } else if (msg->op_type == WCRYPTO_RSA_VERIFY) { + ret = qm_fill_rsa_pubkey((void *)msg->key, &data); + if (unlikely(ret <= 0)) + return -WD_EINVAL; + hw_msg->alg = HPRE_ALG_NC_NCRT; + } else if (msg->op_type == WCRYPTO_RSA_GENKEY) { + ret = rsa_prepare_kg_key(msg, q, hw_msg, &data); + if (unlikely(ret <= 0)) + return -WD_EINVAL; + } else { + WD_ERR("Invalid rsa operation type!\n"); + return -WD_EINVAL; + } + + phy = (uintptr_t)drv_iova_map(q, msg->key, ret); + if (unlikely(!phy)) { + WD_ERR("Dma map rsa key fail!\n"); + return -WD_ENOMEM; + } + + phy += (uintptr_t)data - (uintptr_t)msg->key; + + hw_msg->low_key = (__u32)(phy & QM_L32BITS_MASK); + hw_msg->hi_key = HI_U32(phy); + *va = data; + *size = ret; + + return WD_SUCCESS; +} + +static int qm_rsa_prepare_iot(struct wcrypto_rsa_msg *msg, struct wd_queue *q, + struct hisi_hpre_sqe *hw_msg) +{ + struct wcrypto_rsa_kg_out *kout = (void *)msg->out; + uintptr_t phy; + void *out; + int ret; + + if (msg->op_type != WCRYPTO_RSA_GENKEY) { + phy = (uintptr_t)drv_iova_map(q, msg->in, msg->key_bytes); + if (!phy) { + WD_ERR("Get rsa in buf dma address fail!\n"); + return -WD_ENOMEM; + } + hw_msg->low_in = (__u32)(phy & QM_L32BITS_MASK); + hw_msg->hi_in = HI_U32(phy); + phy = (uintptr_t)drv_iova_map(q, msg->out, msg->key_bytes); + if (unlikely(!phy)) { + WD_ERR("Get rsa out key dma address fail!\n"); + phy = DMA_ADDR(hw_msg->hi_in, hw_msg->low_in); + drv_iova_unmap(q, msg->in, (void *)phy, msg->key_bytes); + return -WD_ENOMEM; + } + } else { + hw_msg->low_in = 0; + hw_msg->hi_in = 0; + ret = wcrypto_rsa_kg_out_data(kout, (char **)&out); + if (unlikely(ret <= 0)) + return -WD_EINVAL; + phy = (uintptr_t)drv_iova_map(q, kout, ret); + if (!phy) { + WD_ERR("Get rsa out buf dma address fail!\n"); + return -WD_ENOMEM; + } + phy += (uintptr_t)out - (uintptr_t)kout; + } + hw_msg->low_out = (__u32)(phy & QM_L32BITS_MASK); + hw_msg->hi_out = HI_U32(phy); + return WD_SUCCESS; +} + +int qm_fill_rsa_sqe(void *message, struct qm_queue_info *info, __u16 i) +{ + struct hisi_hpre_sqe *hw_msg; + struct wcrypto_rsa_msg *msg = message; + struct wcrypto_cb_tag *tag = (void *)(uintptr_t)msg->usr_data; + struct wd_queue *q = info->q; + void *va = NULL; + uintptr_t sqe; + int size = 0; + int ret; + + sqe = (uintptr_t)info->sq_base + i * info->sqe_size; + hw_msg = (struct hisi_hpre_sqe *)sqe; + + memset(hw_msg, 0, sizeof(struct hisi_hpre_sqe)); + + if (msg->key_type == WCRYPTO_RSA_PRIKEY1 || + msg->key_type == WCRYPTO_RSA_PUBKEY) + hw_msg->alg = HPRE_ALG_NC_NCRT; + else if (msg->key_type == WCRYPTO_RSA_PRIKEY2) + hw_msg->alg = HPRE_ALG_NC_CRT; + else + return -WD_EINVAL; + hw_msg->task_len1 = msg->key_bytes / BYTE_BITS - 0x1; + + /* prepare rsa key */ + ret = qm_rsa_prepare_key(msg, q, hw_msg, &va, &size); + if (unlikely(ret)) + return ret; + + /* prepare in/out put */ + ret = qm_rsa_prepare_iot(msg, q, hw_msg); + if (unlikely(ret)) { + rsa_key_unmap(msg, q, hw_msg, va, size); + return ret; + } + + /* This need more processing logic. */ + if (tag) + hw_msg->low_tag = tag->ctx_id; + hw_msg->done = 0x1; + hw_msg->etype = 0x0; + info->req_cache[i] = msg; + + return WD_SUCCESS; +} + +int qm_parse_rsa_sqe(void *msg, const struct qm_queue_info *info, + __u16 i, __u16 usr) +{ + struct wcrypto_rsa_msg *rsa_msg = info->req_cache[i]; + struct hisi_hpre_sqe *hw_msg = msg; + struct wd_queue *q = info->q; + __u64 dma_out, dma_in; + size_t ilen = 0; + size_t olen = 0; + __u16 kbytes; + int ret; + + if (unlikely(!rsa_msg)) { + WD_ERR("info->req_cache is null at index:%hu\n", i); + return 0; + } + + /* if this hardware message not belong to me, then try again */ + if (usr && LOW_U16(hw_msg->low_tag) != usr) + return 0; + kbytes = rsa_msg->key_bytes; + if (hw_msg->done != HPRE_HW_TASK_DONE || hw_msg->etype) { + WD_ERR("HPRE do %s fail!done=0x%x, etype=0x%x\n", "rsa", + hw_msg->done, hw_msg->etype); + if (hw_msg->done == HPRE_HW_TASK_INIT) { + rsa_msg->result = WD_EINVAL; + } else { /* Need to identify which hw err happened */ + rsa_msg->result = WD_IN_EPARA; + } + + if (hw_msg->alg == HPRE_ALG_KG_CRT) { + olen = CRT_GEN_PARAMS_SZ(kbytes); + ilen = GEN_PARAMS_SZ(kbytes); + } else if (hw_msg->alg == HPRE_ALG_KG_STD) { + olen = GEN_PARAMS_SZ(kbytes); + ilen = GEN_PARAMS_SZ(kbytes); + } else { + olen = kbytes; + ilen = kbytes; + } + } else { + ret = qm_rsa_out_transfer(rsa_msg, hw_msg, &ilen, &olen); + if (unlikely(ret)) { + WD_ERR("qm rsa out transfer fail!\n"); + rsa_msg->result = WD_OUT_EPARA; + } else { + rsa_msg->result = WD_SUCCESS; + } + } + + dma_out = DMA_ADDR(hw_msg->hi_out, hw_msg->low_out); + dma_in = DMA_ADDR(hw_msg->hi_key, hw_msg->low_key); + drv_iova_unmap(q, rsa_msg->out, (void *)(uintptr_t)dma_out, olen); + drv_iova_unmap(q, NULL, (void *)(uintptr_t)dma_in, ilen); + return 1; +} + +static int fill_dh_g_param(struct wd_queue *q, struct wcrypto_dh_msg *msg, + struct hisi_hpre_sqe *hw_msg) +{ + uintptr_t phy; + int ret; + + ret = qm_crypto_bin_to_hpre_bin((char *)msg->g, + (const char *)msg->g, msg->key_bytes, + msg->gbytes, "dh g"); + if (unlikely(ret)) + return ret; + + phy = (uintptr_t)drv_iova_map(q, (void *)msg->g, + msg->key_bytes); + if (unlikely(!phy)) { + WD_ERR("Get dh g parameter dma address fail!\n"); + return -WD_ENOMEM; + } + hw_msg->low_in = (__u32)(phy & QM_L32BITS_MASK); + hw_msg->hi_in = HI_U32(phy); + + return 0; +} + +static void dh_g_unmap(struct wcrypto_dh_msg *msg, struct wd_queue *q, + struct hisi_hpre_sqe *hw_msg) +{ + uintptr_t phy = DMA_ADDR(hw_msg->low_in, hw_msg->hi_in); + if (phy) + drv_iova_unmap(q, msg->g, (void *)phy, msg->key_bytes); +} + +static void dh_xp_unmap(struct wcrypto_dh_msg *msg, struct wd_queue *q, + struct hisi_hpre_sqe *hw_msg) +{ + uintptr_t phy = DMA_ADDR(hw_msg->low_key, hw_msg->hi_key); + + drv_iova_unmap(q, msg->x_p, (void *)phy, GEN_PARAMS_SZ(msg->key_bytes)); +} + +static int qm_fill_dh_xp_params(struct wd_queue *q, struct wcrypto_dh_msg *msg, + struct hisi_hpre_sqe *hw_msg) +{ + uintptr_t phy; + void *x, *p; + int ret; + + x = msg->x_p; + p = msg->x_p + msg->key_bytes; + ret = qm_crypto_bin_to_hpre_bin(x, (const char *)x, + msg->key_bytes, msg->xbytes, "dh x"); + if (unlikely(ret)) + return ret; + + ret = qm_crypto_bin_to_hpre_bin(p, (const char *)p, + msg->key_bytes, msg->pbytes, "dh p"); + if (unlikely(ret)) + return ret; + + phy = (uintptr_t)drv_iova_map(q, (void *)x, + GEN_PARAMS_SZ(msg->key_bytes)); + if (unlikely(!phy)) { + WD_ERR("get dh xp parameter dma address fail!\n"); + return -WD_ENOMEM; + } + hw_msg->low_key = (__u32)(phy & QM_L32BITS_MASK); + hw_msg->hi_key = HI_U32(phy); + + return WD_SUCCESS; +} + +static int qm_final_fill_dh_sqe(struct wd_queue *q, struct wcrypto_dh_msg *msg, + struct hisi_hpre_sqe *hw_msg) +{ + struct wcrypto_cb_tag *tag = (void *)(uintptr_t)msg->usr_data; + uintptr_t phy; + + phy = (uintptr_t)drv_iova_map(q, msg->out, msg->key_bytes); + if (unlikely(!phy)) { + WD_ERR("Get dh out buffer dma address fail!\n"); + return -WD_ENOMEM; + } + hw_msg->low_out = (__u32)(phy & QM_L32BITS_MASK); + hw_msg->hi_out = HI_U32(phy); + + /* This need more processing logic. */ + if (tag) + hw_msg->low_tag = tag->ctx_id; + hw_msg->done = 0x1; + hw_msg->etype = 0x0; + + return WD_SUCCESS; +} + +static int qm_dh_out_transfer(struct wcrypto_dh_msg *msg) +{ + int ret; + + ret = qm_hpre_bin_to_crypto_bin((char *)msg->out, + (const char *)msg->out, msg->key_bytes, "dh out"); + if (unlikely(!ret)) + return -WD_EINVAL; + + msg->out_bytes = ret; + + return WD_SUCCESS; +} + +int qm_fill_dh_sqe(void *message, struct qm_queue_info *info, __u16 i) +{ + struct wcrypto_dh_msg *msg = message; + struct hisi_hpre_sqe *hw_msg; + struct wd_queue *q = info->q; + uintptr_t sqe; + int ret; + + sqe = (uintptr_t)info->sq_base + i * info->sqe_size; + hw_msg = (struct hisi_hpre_sqe *)sqe; + + memset(hw_msg, 0, sizeof(struct hisi_hpre_sqe)); + + if (msg->is_g2 && msg->op_type != WCRYPTO_DH_PHASE2) + hw_msg->alg = HPRE_ALG_DH_G2; + else + hw_msg->alg = HPRE_ALG_DH; + hw_msg->task_len1 = msg->key_bytes / BYTE_BITS - 0x1; + if (msg->op_type == WCRYPTO_DH_PHASE1 || + msg->op_type == WCRYPTO_DH_PHASE2) { + if (msg->is_g2 && msg->op_type == WCRYPTO_DH_PHASE1) { + hw_msg->low_in = 0; + hw_msg->hi_in = 0; + } else { + ret = fill_dh_g_param(q, msg, hw_msg); + if (unlikely(ret)) + return ret; + } + + ret = qm_fill_dh_xp_params(q, msg, hw_msg); + if (unlikely(ret)) + goto map_xp_fail; + } + info->req_cache[i] = msg; + + ret = qm_final_fill_dh_sqe(q, msg, hw_msg); + if (unlikely(ret)) + goto map_out_fail; + + return 0; + +map_out_fail: + dh_xp_unmap(msg, q, hw_msg); +map_xp_fail: + dh_g_unmap(msg, q, hw_msg); + + return ret; +} + +int qm_parse_dh_sqe(void *msg, const struct qm_queue_info *info, + __u16 i, __u16 usr) +{ + struct wcrypto_dh_msg *dh_msg = info->req_cache[i]; + struct hisi_hpre_sqe *hw_msg = msg; + __u64 dma_out, dma_in, dma_key; + struct wd_queue *q = info->q; + int ret; + + if (unlikely(!dh_msg)) { + WD_ERR("info->req_cache is null at index:%hu\n", i); + return 0; + } + + if (usr && LOW_U16(hw_msg->low_tag) != usr) + return 0; + if (hw_msg->done != HPRE_HW_TASK_DONE || hw_msg->etype) { + WD_ERR("HPRE do %s fail!done=0x%x, etype=0x%x\n", "dh", + hw_msg->done, hw_msg->etype); + if (hw_msg->done == HPRE_HW_TASK_INIT) { + dh_msg->result = WD_EINVAL; + ret = -WD_EINVAL; + } else { /* Need to identify which hw err happened */ + dh_msg->result = WD_IN_EPARA; + ret = -WD_IN_EPARA; + } + } else { + ret = qm_dh_out_transfer(dh_msg); + if (unlikely(ret)) { + dh_msg->result = WD_OUT_EPARA; + WD_ERR("parse dh format fail!\n"); + } else { + dh_msg->result = WD_SUCCESS; + } + } + + dma_out = DMA_ADDR(hw_msg->hi_out, hw_msg->low_out); + dma_key = DMA_ADDR(hw_msg->hi_key, hw_msg->low_key); + dma_in = DMA_ADDR(hw_msg->hi_in, hw_msg->hi_in); + drv_iova_unmap(q, dh_msg->out, (void *)(uintptr_t)dma_out, + dh_msg->key_bytes); + drv_iova_unmap(q, NULL, (void *)(uintptr_t)dma_in, + GEN_PARAMS_SZ(dh_msg->key_bytes)); + drv_iova_unmap(q, NULL, (void *)(uintptr_t)dma_key, dh_msg->key_bytes); + return 1; +} + +static int qm_ecc_prepare_alg(struct hisi_hpre_sqe *hw_msg, + struct wcrypto_ecc_msg *msg) +{ + switch (msg->op_type) { + case WCRYPTO_ECXDH_GEN_KEY: + case WCRYPTO_ECXDH_COMPUTE_KEY: + if (msg->alg_type == WCRYPTO_X448 || + msg->alg_type == WCRYPTO_X25519) + hw_msg->alg = HPRE_ALG_X_DH_MULTIPLY; + else if (msg->alg_type == WCRYPTO_ECDH) + hw_msg->alg = HPRE_ALG_ECDH_MULTIPLY; + break; + case HPRE_SM2_ENC: /* fall through */ + case HPRE_SM2_DEC: /* fall through */ + hw_msg->alg = HPRE_ALG_ECDH_MULTIPLY; + break; + case WCRYPTO_ECDSA_SIGN: + hw_msg->alg = HPRE_ALG_ECDSA_SIGN; + break; + case WCRYPTO_ECDSA_VERIFY: + hw_msg->alg = HPRE_ALG_ECDSA_VERF; + break; + case WCRYPTO_SM2_ENCRYPT: + hw_msg->alg = HPRE_ALG_SM2_ENC; + break; + case WCRYPTO_SM2_DECRYPT: + hw_msg->alg = HPRE_ALG_SM2_DEC; + break; + case WCRYPTO_SM2_SIGN: + hw_msg->alg = HPRE_ALG_SM2_SIGN; + break; + case WCRYPTO_SM2_VERIFY: + hw_msg->alg = HPRE_ALG_SM2_VERF; + break; + case WCRYPTO_SM2_KG: + hw_msg->alg = HPRE_ALG_SM2_KEY_GEN; + break; + default: + return -WD_EINVAL; + } + + return 0; +} + +static int trans_cv_param_to_hpre_bin(struct wd_dtb *p, struct wd_dtb *a, + struct wd_dtb *b, struct wd_dtb *n, + struct wcrypto_ecc_point *g) +{ + int ret; + + ret = qm_crypto_bin_to_hpre_bin(p->data, (const char *)p->data, + p->bsize, p->dsize, "cv p"); + if (unlikely(ret)) + return ret; + + ret = qm_crypto_bin_to_hpre_bin(a->data, (const char *)a->data, + a->bsize, a->dsize, "cv a"); + if (unlikely(ret)) + return ret; + + ret = qm_crypto_bin_to_hpre_bin(b->data, (const char *)b->data, + b->bsize, b->dsize, "cv b"); + if (unlikely(ret)) + return ret; + + ret = qm_crypto_bin_to_hpre_bin(n->data, (const char *)n->data, + n->bsize, n->dsize, "cv n"); + if (unlikely(ret)) + return ret; + + ret = qm_crypto_bin_to_hpre_bin(g->x.data, (const char *)g->x.data, + g->x.bsize, g->x.dsize, "cv gx"); + if (unlikely(ret)) + return ret; + + ret = qm_crypto_bin_to_hpre_bin(g->y.data, (const char *)g->y.data, + g->y.bsize, g->y.dsize, "cv gy"); + if (unlikely(ret)) + return ret; + + return 0; +} + +static int trans_d_to_hpre_bin(struct wd_dtb *d) +{ + int ret; + + ret = qm_crypto_bin_to_hpre_bin(d->data, (const char *)d->data, + d->bsize, d->dsize, "ecc d"); + if (unlikely(ret)) + return ret; + + return 0; +} + +static bool less_than_latter(struct wd_dtb *d, struct wd_dtb *n) +{ + int ret, shift; + + if (d->dsize > n->dsize) + return false; + else if (d->dsize < n->dsize) + return true; + + shift = n->bsize - n->dsize; + ret = memcmp(d->data + shift, n->data + shift, n->dsize); + if (ret < 0) + return true; + else + return false; +} + +static int ecc_prepare_prikey(struct wcrypto_ecc_key *key, void **data, int id) +{ + struct wcrypto_ecc_point *g = NULL; + struct wd_dtb *p = NULL; + struct wd_dtb *a = NULL; + struct wd_dtb *b = NULL; + struct wd_dtb *n = NULL; + struct wd_dtb *d = NULL; + char bsize, dsize; + char *dat; + int ret; + + wcrypto_get_ecc_prikey_params((void *)key, &p, &a, &b, &n, &g, &d); + + ret = trans_cv_param_to_hpre_bin(p, a, b, n, g); + if (unlikely(ret)) + return ret; + + ret = trans_d_to_hpre_bin(d); + if (unlikely(ret)) + return ret; + + dat = d->data; + bsize = d->bsize; + dsize = d->dsize; + + /* + * This is a pretreatment of X25519/X448, as described in RFC 7748: + * For X25519, in order to decode 32 random bytes as an integer + * scaler, set the three LSB of the first byte and MSB of the last + * to zero, set the second MSB of the last byte to 1. + * For X448, set the two LSB of the first byte to 0, and MSB of the + * last byte to 1. Decode in little-endian mode. + * HPRE hardware module uses big-endian mode, so the bytes to be + * set are reversed compared to RFC 7748: + * For example, dat[0] of X25519 in RFC 7748 is reversed to dat[31] + * in HPRE specification, so does X448. + */ + if (id == WCRYPTO_X25519) { + dat[31] &= 248; + dat[0] &= 127; + dat[0] |= 64; + } else if (id == WCRYPTO_X448) { + dat[55 + bsize - dsize] &= 252; + dat[0 + bsize - dsize] |= 128; + } + + if (id != WCRYPTO_X25519 && id != WCRYPTO_X448 && + !less_than_latter(d, n)) { + WD_ERR("failed to prepare ecc prikey: d >= n!\n"); + return -WD_EINVAL; + } + + *data = p->data; + + return 0; +} + +static int trans_pub_to_hpre_bin(struct wcrypto_ecc_point *pub) +{ + struct wd_dtb *temp; + int ret; + + temp = &pub->x; + ret = qm_crypto_bin_to_hpre_bin(temp->data, (const char *)temp->data, + temp->bsize, temp->dsize, "ecc pub x"); + if (unlikely(ret)) + return ret; + + temp = &pub->y; + ret = qm_crypto_bin_to_hpre_bin(temp->data, (const char *)temp->data, + temp->bsize, temp->dsize, "ecc pub y"); + if (unlikely(ret)) + return ret; + + return 0; +} + +static int ecc_prepare_pubkey(struct wcrypto_ecc_key *key, void **data) +{ + struct wcrypto_ecc_point *pub = NULL; + struct wcrypto_ecc_point *g = NULL; + struct wd_dtb *p = NULL; + struct wd_dtb *a = NULL; + struct wd_dtb *b = NULL; + struct wd_dtb *n = NULL; + int ret; + + wcrypto_get_ecc_pubkey_params((void *)key, &p, &a, &b, &n, &g, &pub); + + ret = trans_cv_param_to_hpre_bin(p, a, b, n, g); + if (unlikely(ret)) + return ret; + + ret = trans_pub_to_hpre_bin(pub); + if (unlikely(ret)) + return ret; + + *data = p->data; + + return 0; +} + +static __u32 ecc_get_prikey_size(struct wcrypto_ecc_msg *msg) +{ + if (msg->op_type == WCRYPTO_SM2_SIGN || + msg->op_type == WCRYPTO_ECDSA_SIGN || + msg->op_type == WCRYPTO_SM2_DECRYPT) + return ECC_PRIKEY_SZ(msg->key_bytes); + else if (msg->alg_type == WCRYPTO_X25519 || + msg->alg_type == WCRYPTO_X448) + return X_DH_HW_KEY_SZ(msg->key_bytes); + else + return ECDH_HW_KEY_SZ(msg->key_bytes); +} + +static void ecc_key_unmap(struct wcrypto_ecc_msg *msg, struct wd_queue *q, + struct hisi_hpre_sqe *hw_msg, + void *va, int size) +{ + uintptr_t phy; + + phy = DMA_ADDR(hw_msg->low_key, hw_msg->hi_key); + drv_iova_unmap(q, va, (void *)phy, size); +} + +static bool is_prikey_used(__u8 op_type) +{ + return op_type == WCRYPTO_ECXDH_GEN_KEY || + op_type == WCRYPTO_ECXDH_COMPUTE_KEY || + op_type == WCRYPTO_ECDSA_SIGN || + op_type == WCRYPTO_SM2_DECRYPT || + op_type == WCRYPTO_SM2_SIGN || + op_type == HPRE_SM2_ENC || + op_type == HPRE_SM2_DEC; +} + +static int qm_ecc_prepare_key(struct wcrypto_ecc_msg *msg, struct wd_queue *q, + struct hisi_hpre_sqe *hw_msg, + void **va, int *size) +{ + __u8 op_type = msg->op_type; + void *data = NULL; + uintptr_t phy; + size_t ksz; + int ret; + + if (unlikely(!op_type || (op_type >= WCRYPTO_EC_OP_MAX && + op_type != HPRE_SM2_ENC && op_type != HPRE_SM2_DEC))) { + WD_ERR("op_type = %u error!\n", op_type); + return -WD_EINVAL; + } + + if (is_prikey_used(msg->op_type)) { + ksz = ecc_get_prikey_size(msg); + ret = ecc_prepare_prikey((void *)msg->key, &data, + msg->alg_type); + if (unlikely(ret)) + return ret; + } else { + ksz = ECC_PUBKEY_SZ(msg->key_bytes); + ret = ecc_prepare_pubkey((void *)msg->key, &data); + if (unlikely(ret)) + return ret; + } + + phy = (uintptr_t)drv_iova_map(q, data, ksz); + if (unlikely(!phy)) { + WD_ERR("Dma map ecc key fail!\n"); + return -WD_ENOMEM; + } + + hw_msg->low_key = (__u32)(phy & QM_L32BITS_MASK); + hw_msg->hi_key = HI_U32(phy); + *va = data; + *size = ksz; + + return 0; +} + +static void qm_ecc_get_io_len(__u32 atype, __u32 hsz, size_t *ilen, + size_t *olen) +{ + if (atype == HPRE_ALG_ECDH_MULTIPLY) { + *olen = ECDH_OUT_PARAMS_SZ(hsz); + *ilen = *olen; + } else if (atype == HPRE_ALG_X_DH_MULTIPLY) { + *olen = X_DH_OUT_PARAMS_SZ(hsz); + *ilen = *olen; + } else if (atype == HPRE_ALG_ECDSA_SIGN) { + *olen = ECC_SIGN_OUT_PARAMS_SZ(hsz); + *ilen = ECC_SIGN_IN_PARAMS_SZ(hsz); + } else if (atype == HPRE_ALG_ECDSA_VERF) { + *olen = ECC_VERF_OUT_PARAMS_SZ; + *ilen = ECC_VERF_IN_PARAMS_SZ(hsz); + } else { + *olen = hsz; + *ilen = hsz; + } +} + +static int ecc_prepare_dh_compute_in(struct wcrypto_ecc_in *in, void **data) +{ + struct wcrypto_ecc_point *pbk = NULL; + int ret; + + wcrypto_get_ecxdh_in_params(in, &pbk); + if (unlikely(!pbk)) { + WD_ERR("failed to get ecxdh in param!\n"); + return -WD_EINVAL; + } + + ret = qm_crypto_bin_to_hpre_bin(pbk->x.data, (const char *)pbk->x.data, + pbk->x.bsize, pbk->x.dsize, "ecdh pbk x"); + if (unlikely(ret)) + return ret; + + ret = qm_crypto_bin_to_hpre_bin(pbk->y.data, (const char *)pbk->y.data, + pbk->y.bsize, pbk->y.dsize, "ecdh pbk y"); + if (unlikely(ret)) + return ret; + + *data = pbk->x.data; + + return 0; +} + +static void correct_random(struct wd_dtb *k) +{ + int lens = k->bsize - k->dsize; + + k->data[lens] = 0; +} + +static bool is_all_zero(struct wd_dtb *e, struct wcrypto_ecc_msg *msg, + const char *p_name) +{ + int i; + + for (i = 0; i < e->dsize && i < msg->key_bytes; i++) { + if (e->data[i]) + return false; + } + + WD_ERR("error: %s all zero!\n", p_name); + + return true; +} + +static int ecc_prepare_sign_in(struct wcrypto_ecc_msg *msg, + struct hisi_hpre_sqe *hw_msg, void **data) +{ + struct wcrypto_ecc_sign_in *in = (void *)msg->in; + struct wd_dtb *n = NULL; + struct wd_dtb *e = NULL; + struct wd_dtb *k = NULL; + int ret; + + if (!in->dgst_set) { + WD_ERR("hash not set!\n"); + return -WD_EINVAL; + } + + k = &in->k; + e = &in->dgst; + if (!in->k_set) { + if (msg->op_type != WCRYPTO_SM2_SIGN) { + WD_ERR("random k not set!\n"); + return -WD_EINVAL; + } + hw_msg->sm2_ksel = 1; + } else if (is_all_zero(k, msg, "ecc sgn k")) { + return -WD_EINVAL; + } + + if (is_all_zero(e, msg, "ecc sgn e")) + return -WD_EINVAL; + + ret = qm_crypto_bin_to_hpre_bin(e->data, (const char *)e->data, + e->bsize, e->dsize, "ecc sgn e"); + if (unlikely(ret)) + return ret; + + ret = qm_crypto_bin_to_hpre_bin(k->data, (const char *)k->data, + k->bsize, k->dsize, "ecc sgn k"); + if (unlikely(ret)) + return ret; + + wcrypto_get_ecc_prikey_params((void *)msg->key, NULL, NULL, NULL, + &n, NULL, NULL); + if (!less_than_latter(k, n)) + correct_random(k); + + *data = e->data; + + return 0; +} + +static int ecc_prepare_verf_in(struct wcrypto_ecc_msg *msg, void **data) +{ + struct wcrypto_ecc_verf_in *vin = (void *)msg->in; + struct wd_dtb *e = NULL; + struct wd_dtb *s = NULL; + struct wd_dtb *r = NULL; + int ret; + + if (!vin->dgst_set) { + WD_ERR("hash not set!\n"); + return -WD_EINVAL; + } + + e = &vin->dgst; + s = &vin->s; + r = &vin->r; + + if (is_all_zero(e, msg, "ecc vrf e")) + return -WD_EINVAL; + + ret = qm_crypto_bin_to_hpre_bin(e->data, (const char *)e->data, + e->bsize, e->dsize, "ecc vrf e"); + if (unlikely(ret)) + return ret; + + ret = qm_crypto_bin_to_hpre_bin(s->data, (const char *)s->data, + s->bsize, s->dsize, "ecc vrf s"); + if (unlikely(ret)) + return ret; + + ret = qm_crypto_bin_to_hpre_bin(r->data, (const char *)r->data, + r->bsize, r->dsize, "ecc vrf r"); + if (unlikely(ret)) + return ret; + + *data = e->data; + + return 0; +} + +static int ecc_prepare_dh_gen_in(void *input, void **data) +{ + struct wcrypto_ecc_point *in = input; + int ret; + + ret = qm_crypto_bin_to_hpre_bin(in->x.data, (const char *)in->x.data, + in->x.bsize, in->x.dsize, "ecdh gen x"); + if (unlikely(ret)) + return ret; + + ret = qm_crypto_bin_to_hpre_bin(in->y.data, (const char *)in->y.data, + in->y.bsize, in->y.dsize, "ecdh gen y"); + if (unlikely(ret)) + return ret; + + *data = in->x.data; + + return 0; +} + +static int u_is_in_p(struct wcrypto_ecc_msg *msg) +{ + struct wcrypto_ecc_in *in = (struct wcrypto_ecc_in *)msg->in; + struct wcrypto_ecc_point *pbk = NULL; + struct wd_dtb *p = NULL; + + wcrypto_get_ecc_prikey_params((void *)msg->key, &p, NULL, NULL, + NULL, NULL, NULL); + + wcrypto_get_ecxdh_in_params(in, &pbk); + if (unlikely(!pbk)) { + WD_ERR("failed to get ecxdh in param!\n"); + return -WD_EINVAL; + } + + /* + * In big-endian order, when receiving u-array, implementations of X25519 + * should mask the most significant bit in the 1st byte. + * See RFC 7748 for details; + */ + if (msg->alg_type == WCRYPTO_X25519) + pbk->x.data[0] &= 0x7f; + + if (!less_than_latter(&pbk->x, p)) { + WD_ERR("ux is out of p!\n"); + return -WD_EINVAL; + } + + return 0; +} + +static int ecc_prepare_sm2_enc_in(struct wcrypto_ecc_msg *msg, + struct hisi_hpre_sqe *hw_msg, void **data) +{ + struct wcrypto_sm2_enc_in *ein = (void *)msg->in; + struct wd_dtb *k = &ein->k; + int ret; + + if (ein->k_set) { + if (is_all_zero(k, msg, "sm2 enc k")) + return -WD_EINVAL; + + ret = qm_crypto_bin_to_hpre_bin(k->data, (const char *)k->data, + k->bsize, k->dsize, "sm2 enc k"); + if (unlikely(ret)) + return ret; + } else { + hw_msg->sm2_ksel = 1; + } + + hw_msg->sm2_mlen = ein->plaintext.dsize - 1; + *data = k->data; + + return 0; +} + +static int ecc_prepare_sm2_dec_in(struct wcrypto_ecc_msg *msg, + struct hisi_hpre_sqe *hw_msg, void **data) +{ + struct wcrypto_sm2_dec_in *din = (void *)msg->in; + struct wcrypto_ecc_point *c1 = &din->c1; + int ret; + + ret = qm_crypto_bin_to_hpre_bin(c1->x.data, (const char *)c1->x.data, + c1->x.bsize, c1->x.dsize, "sm2 dec c1 x"); + if (unlikely(ret)) + return ret; + + ret = qm_crypto_bin_to_hpre_bin(c1->y.data, (const char *)c1->y.data, + c1->y.bsize, c1->y.dsize, "sm2 dec c1 y"); + if (unlikely(ret)) + return ret; + + hw_msg->sm2_mlen = din->c2.dsize - 1; + *data = c1->x.data; + + return 0; +} + +static int qm_ecc_prepare_in(struct wcrypto_ecc_msg *msg, + struct hisi_hpre_sqe *hw_msg, void **data) +{ + struct wcrypto_ecc_in *in = (struct wcrypto_ecc_in *)msg->in; + int ret = -WD_EINVAL; + + switch (msg->op_type) { + case HPRE_SM2_ENC: /* fall through */ + case HPRE_SM2_DEC: /* fall through */ + hw_msg->bd_rsv2 = 1; /* fall through */ + case WCRYPTO_ECXDH_GEN_KEY: /* fall through */ + case WCRYPTO_SM2_KG: + ret = ecc_prepare_dh_gen_in((void *)in, + data); + break; + case WCRYPTO_ECXDH_COMPUTE_KEY: + /* + * when compute x25519/x448, we should guarantee u < p, + * or it is invalid. + */ + ret = ecc_prepare_dh_compute_in(in, data); + if (ret == 0 && (msg->alg_type == WCRYPTO_X25519 || + msg->alg_type == WCRYPTO_X448)) + ret = u_is_in_p(msg); + break; + case WCRYPTO_ECDSA_SIGN: + case WCRYPTO_SM2_SIGN: + ret = ecc_prepare_sign_in(msg, hw_msg, data); + break; + case WCRYPTO_ECDSA_VERIFY: + case WCRYPTO_SM2_VERIFY: + ret = ecc_prepare_verf_in(msg, data); + break; + case WCRYPTO_SM2_ENCRYPT: + ret = ecc_prepare_sm2_enc_in(msg, hw_msg, data); + break; + case WCRYPTO_SM2_DECRYPT: + ret = ecc_prepare_sm2_dec_in(msg, hw_msg, data); + break; + default: + break; + } + + return ret; +} + +static int ecc_prepare_dh_out(struct wcrypto_ecc_out *out, void **data) +{ + struct wcrypto_ecc_point *dh_out = NULL; + + wcrypto_get_ecxdh_out_params(out, &dh_out); + if (unlikely(!dh_out)) { + WD_ERR("failed to get ecxdh out param!\n"); + return -WD_EINVAL; + } + + *data = dh_out->x.data; + + return 0; +} + +static int ecc_prepare_sign_out(struct wcrypto_ecc_out *out, void **data) +{ + struct wd_dtb *r = NULL; + struct wd_dtb *s = NULL; + + wcrypto_get_ecdsa_sign_out_params(out, &r, &s); + if (unlikely(!r || !s)) { + WD_ERR("failed to get ecdsa sign out param!\n"); + return -WD_EINVAL; + } + + *data = r->data; + + return 0; +} + +static int ecc_prepare_sm2_enc_out(struct wcrypto_ecc_out *out, void **data) +{ + struct wcrypto_ecc_point *c1 = NULL; + + wcrypto_get_sm2_enc_out_params(out, &c1, NULL, NULL); + if (unlikely(!c1)) { + WD_ERR("failed to get sm2 enc out param!\n"); + return -WD_EINVAL; + } + + *data = c1->x.data; + + return 0; +} + +static int ecc_prepare_sm2_dec_out(struct wcrypto_ecc_out *out, void **data) +{ + struct wd_dtb *m = NULL; + + wcrypto_get_sm2_dec_out_params(out, &m); + if (unlikely(!m)) { + WD_ERR("failed to get sm2 dec out param!\n"); + return -WD_EINVAL; + } + + *data = m->data; + + return 0; +} + +static int ecc_prepare_sm2_kg_out(struct wcrypto_ecc_out *out, void **data) +{ + struct wcrypto_ecc_point *pub = NULL; + + wcrypto_get_sm2_kg_out_params(out, NULL, &pub); + if (unlikely(!pub)) { + WD_ERR("failed to get sm2 kg out param!\n"); + return -WD_EINVAL; + } + + *data = pub->x.data; + + return 0; +} +static int qm_ecc_prepare_out(struct wcrypto_ecc_msg *msg, void **data) +{ + struct wcrypto_ecc_out *out = (struct wcrypto_ecc_out *)msg->out; + int ret = 0; + + switch (msg->op_type) { + case WCRYPTO_ECXDH_GEN_KEY: + case WCRYPTO_ECXDH_COMPUTE_KEY: + case HPRE_SM2_ENC: /* fall through */ + case HPRE_SM2_DEC: /* fall through */ + if (msg->op_type == HPRE_SM2_ENC || + msg->op_type == HPRE_SM2_DEC) + *data = out; + else + ret = ecc_prepare_dh_out(out, data); + break; + case WCRYPTO_ECDSA_SIGN: + case WCRYPTO_SM2_SIGN: + ret = ecc_prepare_sign_out(out, data); + break; + case WCRYPTO_ECDSA_VERIFY: + case WCRYPTO_SM2_VERIFY: + break; + case WCRYPTO_SM2_ENCRYPT: + ret = ecc_prepare_sm2_enc_out(out, data); + break; + case WCRYPTO_SM2_DECRYPT: + ret = ecc_prepare_sm2_dec_out(out, data); + break; + case WCRYPTO_SM2_KG: + ret = ecc_prepare_sm2_kg_out(out, data); + break; + default: + break; + } + + return ret; +} + +/* prepare in/out hardware message */ +static int qm_ecc_prepare_iot(struct wcrypto_ecc_msg *msg, struct wd_queue *q, + struct hisi_hpre_sqe *hw_msg) +{ + void *data = NULL; + size_t i_sz = 0; + size_t o_sz = 0; + uintptr_t phy; + __u16 kbytes; + void *va; + int ret; + + kbytes = msg->key_bytes; + qm_ecc_get_io_len(hw_msg->alg, kbytes, &i_sz, &o_sz); + ret = qm_ecc_prepare_in(msg, hw_msg, &data); + if (unlikely(ret)) { + WD_ERR("qm_ecc_prepare_in fail!\n"); + return ret; + } + + va = data; + phy = (uintptr_t)drv_iova_map(q, va, i_sz); + if (unlikely(!phy)) { + WD_ERR("Get ecc in buf dma address fail!\n"); + return -WD_ENOMEM; + } + hw_msg->low_in = (__u32)(phy & QM_L32BITS_MASK); + hw_msg->hi_in = HI_U32(phy); + + ret = qm_ecc_prepare_out(msg, &data); + if (unlikely(ret)) { + WD_ERR("qm_ecc_prepare_out fail!\n"); + goto map_fail; + } + + if (!data) + return 0; + + phy = (uintptr_t)drv_iova_map(q, data, o_sz); + if (unlikely(!phy)) { + WD_ERR("Get ecc out key dma address fail!\n"); + ret = -WD_ENOMEM; + goto map_fail; + } + hw_msg->low_out = (__u32)(phy & QM_L32BITS_MASK); + hw_msg->hi_out = HI_U32(phy); + + return 0; + +map_fail: + phy = DMA_ADDR(hw_msg->hi_in, hw_msg->low_in); + drv_iova_unmap(q, va, (void *)phy, i_sz); + + return ret; +} + +static int ecdh_out_transfer(struct wcrypto_ecc_msg *msg, + struct hisi_hpre_sqe *hw_msg) +{ + struct wcrypto_ecc_out *out = (void *)msg->out; + struct wcrypto_ecc_point *key = NULL; + struct wd_dtb *y = NULL; + + if (msg->op_type == HPRE_SM2_DEC || msg->op_type == HPRE_SM2_ENC) + return WD_SUCCESS; + + wcrypto_get_ecxdh_out_params(out, &key); + if (unlikely(!key)) { + WD_ERR("failed to get ecxdh out param!\n"); + return -WD_EINVAL; + } + + if (hw_msg->alg == HPRE_ALG_ECDH_MULTIPLY) + y = &key->y; + + return qm_tri_bin_transfer(&key->x, y, NULL, "ecdh out x & y"); +} + +static int ecc_sign_out_transfer(struct wcrypto_ecc_msg *msg, + struct hisi_hpre_sqe *hw_msg) +{ + struct wcrypto_ecc_out *out = (void *)msg->out; + struct wd_dtb *r = NULL; + struct wd_dtb *s = NULL; + + wcrypto_get_ecdsa_sign_out_params(out, &r, &s); + if (unlikely(!r || !s)) { + WD_ERR("failed to get ecdsa sign out param!\n"); + return -WD_EINVAL; + } + + return qm_tri_bin_transfer(r, s, NULL, "ecc sign r&s"); +} + +static int ecc_verf_out_transfer(struct wcrypto_ecc_msg *msg, + struct hisi_hpre_sqe *hw_msg) +{ + __u32 result = hw_msg->low_out; + + result >>= 1; + result &= 1; + if (!result) + msg->result = WD_VERIFY_ERR; + + return WD_SUCCESS; +} + +static int sm2_kg_out_transfer(struct wcrypto_ecc_msg *msg, + struct hisi_hpre_sqe *hw_msg) +{ + struct wcrypto_ecc_out *out = (void *)msg->out; + struct wcrypto_ecc_point *pubkey = NULL; + struct wd_dtb *prk = NULL; + + wcrypto_get_sm2_kg_out_params(out, &prk, &pubkey); + if (unlikely(!prk || !pubkey)) { + WD_ERR("failed to get sm2 kg out param!\n"); + return -WD_EINVAL; + } + + return qm_tri_bin_transfer(prk, &pubkey->x, &pubkey->y, "sm2 kg out"); +} + +static int sm2_enc_out_transfer(struct wcrypto_ecc_msg *msg, + struct hisi_hpre_sqe *hw_msg) +{ + struct wcrypto_ecc_out *out = (void *)msg->out; + struct wcrypto_ecc_point *c1 = NULL; + + wcrypto_get_sm2_enc_out_params(out, &c1, NULL, NULL); + if (unlikely(!c1)) { + WD_ERR("failed to get sm2 enc out param!\n"); + return -WD_EINVAL; + } + + return qm_tri_bin_transfer(&c1->x, &c1->y, NULL, "sm2 enc out"); +} + +static int qm_ecc_out_transfer(struct wcrypto_ecc_msg *msg, + struct hisi_hpre_sqe *hw_msg) +{ + int ret = -WD_EINVAL; + + if (hw_msg->alg == HPRE_ALG_ECDH_MULTIPLY || + hw_msg->alg == HPRE_ALG_X_DH_MULTIPLY) + ret = ecdh_out_transfer(msg, hw_msg); + else if (hw_msg->alg == HPRE_ALG_ECDSA_SIGN || + hw_msg->alg == HPRE_ALG_SM2_SIGN) + ret = ecc_sign_out_transfer(msg, hw_msg); + else if (hw_msg->alg == HPRE_ALG_ECDSA_VERF || + hw_msg->alg == HPRE_ALG_SM2_VERF) + ret = ecc_verf_out_transfer(msg, hw_msg); + else if (hw_msg->alg == HPRE_ALG_SM2_ENC) + ret = sm2_enc_out_transfer(msg, hw_msg); + else if (hw_msg->alg == HPRE_ALG_SM2_DEC) + ret = 0; + else if (hw_msg->alg == HPRE_ALG_SM2_KEY_GEN) + ret = sm2_kg_out_transfer(msg, hw_msg); + else + WD_ERR("ecc out trans fail alg %u error!\n", hw_msg->alg); + + return ret; +} + +static int qm_fill_ecc_sqe_general(void *message, struct qm_queue_info *info, + __u16 i) +{ + struct wcrypto_ecc_msg *msg = message; + struct wcrypto_cb_tag *tag = (void *)(uintptr_t)msg->usr_data; + struct wd_queue *q = info->q; + struct hisi_hpre_sqe *hw_msg; + void *va = NULL; + uintptr_t sqe; + int size = 0; + int ret; + + sqe = (uintptr_t)info->sq_base + i * info->sqe_size; + hw_msg = (struct hisi_hpre_sqe *)sqe; + + memset(hw_msg, 0, sizeof(struct hisi_hpre_sqe)); + hw_msg->task_len1 = msg->key_bytes / BYTE_BITS - 0x1; + + /* prepare algorithm */ + ret = qm_ecc_prepare_alg(hw_msg, msg); + if (unlikely(ret)) + return ret; + + /* prepare key */ + ret = qm_ecc_prepare_key(msg, q, hw_msg, &va, &size); + if (unlikely(ret)) + return ret; + + /* prepare in/out put */ + ret = qm_ecc_prepare_iot(msg, q, hw_msg); + if (unlikely(ret)) + goto map_key_fail; + + /* This need more processing logic. */ + if (tag) + hw_msg->low_tag = tag->ctx_id; + hw_msg->done = 0x1; + hw_msg->etype = 0x0; + info->req_cache[i] = msg; + + return WD_SUCCESS; + +map_key_fail: + ecc_key_unmap(msg, q, hw_msg, va, size); + + return ret; +} + +static void init_prikey(struct wcrypto_ecc_prikey *prikey, __u32 bsz) +{ + prikey->p.dsize = 0; + prikey->p.bsize = bsz; + prikey->p.data = prikey->data; + prikey->a.dsize = 0; + prikey->a.bsize = bsz; + prikey->a.data = prikey->p.data + bsz; + prikey->d.dsize = 0; + prikey->d.bsize = bsz; + prikey->d.data = prikey->a.data + bsz; + prikey->b.dsize = 0; + prikey->b.bsize = bsz; + prikey->b.data = prikey->d.data + bsz; + prikey->n.dsize = 0; + prikey->n.bsize = bsz; + prikey->n.data = prikey->b.data + bsz; + prikey->g.x.dsize = 0; + prikey->g.x.bsize = bsz; + prikey->g.x.data = prikey->n.data + bsz; + prikey->g.y.dsize = 0; + prikey->g.y.bsize = bsz; + prikey->g.y.data = prikey->g.x.data + bsz; +} + +static int set_param(struct wd_dtb *dst, const struct wd_dtb *src, + const char *p_name) +{ + if (unlikely(!src || !src->data)) { + WD_ERR("%s: src or data NULL!\n", p_name); + return -WD_EINVAL; + } + + if (unlikely(!src->dsize || src->dsize > dst->bsize)) { + WD_ERR("%s: src dsz = %u error, dst bsz = %u!\n", + p_name, src->dsize, dst->bsize); + return -WD_EINVAL; + } + + dst->dsize = src->dsize; + memset(dst->data, 0, dst->bsize); + memcpy(dst->data, src->data, src->dsize); + + return 0; +} + +static int set_prikey(struct wcrypto_ecc_prikey *prikey, + struct wcrypto_ecc_msg *req) +{ + struct wcrypto_ecc_key *key = (struct wcrypto_ecc_key *)req->key; + struct wcrypto_sm2_enc_in *ein = (void *)req->in; + struct wcrypto_ecc_pubkey *pubkey = key->pubkey; + int ret; + + ret = set_param(&prikey->p, &pubkey->p, "p"); + if (unlikely(ret)) + return ret; + + ret = set_param(&prikey->a, &pubkey->a, "a"); + if (unlikely(ret)) + return ret; + + ret = set_param(&prikey->d, &ein->k, "k"); + if (unlikely(ret)) + return ret; + + ret = set_param(&prikey->b, &pubkey->b, "b"); + if (unlikely(ret)) + return ret; + + ret = set_param(&prikey->n, &pubkey->n, "n"); + if (unlikely(ret)) + return ret; + + ret = set_param(&prikey->g.x, &pubkey->g.x, "gx"); + if (unlikely(ret)) + return ret; + + return set_param(&prikey->g.y, &pubkey->g.y, "gy"); +} + +static int init_req(struct wcrypto_ecc_msg *dst, struct wcrypto_ecc_msg *src, + struct wcrypto_ecc_key *key, struct qm_queue_info *info, + __u8 req_idx) +{ + struct wcrypto_ecc_key *ecc_key = (struct wcrypto_ecc_key *)src->key; + struct wcrypto_ecc_pubkey *pubkey = ecc_key->pubkey; + struct q_info *qinfo = info->q->qinfo; + struct wd_mm_br *br = &qinfo->br; + __u32 ksz = src->key_bytes; + + memcpy(dst, src, sizeof(*dst)); + dst->key = (void *)key; + dst->op_type = HPRE_SM2_ENC; + *(struct wcrypto_ecc_msg **)(dst + 1) = src; + + dst->out = br->alloc(br->usr, ECDH_OUT_PARAMS_SZ(ksz)); + if (unlikely(!dst->out)) + return -WD_ENOMEM; + + if (!req_idx) + dst->in = (void *)&pubkey->g; + else + dst->in = (void *)&pubkey->pub; + + return 0; +} + +static struct wcrypto_ecc_msg *create_req(struct wcrypto_ecc_msg *src, + struct qm_queue_info *info, + __u8 req_idx) +{ + struct q_info *qinfo = info->q->qinfo; + struct wcrypto_ecc_prikey *prikey; + struct wd_mm_br *br = &qinfo->br; + struct wcrypto_ecc_key *ecc_key; + struct wcrypto_ecc_msg *dst; + int ret; + + /* dst last store point "struct wcrypto_ecc_msg *" */ + dst = malloc(sizeof(*dst) + sizeof(struct wcrypto_ecc_msg *)); + if (unlikely(!dst)) + return NULL; + + ecc_key = malloc(sizeof(*ecc_key) + sizeof(*prikey)); + if (unlikely(!ecc_key)) + goto fail_alloc_key; + + prikey = (struct wcrypto_ecc_prikey *)(ecc_key + 1); + ecc_key->prikey = prikey; + prikey->data = br->alloc(br->usr, ECC_PRIKEY_SZ(src->key_bytes)); + if (unlikely(!prikey->data)) { + WD_ERR("failed to br alloc\n"); + goto fail_alloc_key_data; + } + init_prikey(prikey, src->key_bytes); + ret = set_prikey(prikey, src); + if (unlikely(ret)) + goto fail_set_prikey; + + ret = init_req(dst, src, ecc_key, info, req_idx); + if (unlikely(ret)) { + WD_ERR("failed to init req, ret = %d\n", ret); + goto fail_set_prikey; + } + + return dst; + +fail_set_prikey: + br->free(br->usr, prikey->data); +fail_alloc_key_data: + free(ecc_key); +fail_alloc_key: + free(dst); + + return NULL; +} + +static void free_req(struct qm_queue_info *info, struct wcrypto_ecc_msg *req) +{ + struct wcrypto_ecc_key *key = (void *)req->key; + struct q_info *qinfo = info->q->qinfo; + struct wd_mm_br *br = &qinfo->br; + + br->free(br->usr, key->prikey->data); + free(req->key); + br->free(br->usr, req->out); + free(req); +} + +static int split_req(struct qm_queue_info *info, + struct wcrypto_ecc_msg *src, struct wcrypto_ecc_msg **dst) +{ + /* k * G */ + dst[0] = create_req(src, info, 0); + if (unlikely(!dst[0])) + return -WD_ENOMEM; + + /* k * pub */ + dst[1] = create_req(src, info, 1); + if (unlikely(!dst[1])) { + free_req(info, dst[0]); + return -WD_ENOMEM; + } + + return 0; +} + +static int fill_sm2_enc_sqe(void *msg, struct qm_queue_info *info, __u16 idx) +{ + struct wcrypto_hash_mt *hash = &((struct q_info *)info->q->qinfo)->hash; + struct wcrypto_ecc_msg *req_src = msg; + struct wcrypto_sm2_enc_in *ein = (void *)req_src->in; + struct wcrypto_ecc_msg *req_dst[2] = {NULL}; + struct wd_dtb *plaintext = &ein->plaintext; + __u16 i = idx; + int ret; + + if (plaintext->dsize <= HW_PLAINTEXT_BYTES_MAX && + req_src->hash_type == WCRYPTO_HASH_SM3) + return qm_fill_ecc_sqe_general(req_src, info, i); + + if (unlikely(!ein->k_set)) { + WD_ERR("error: k not set\n"); + return -WD_EINVAL; + } + + if (unlikely(!hash->cb || hash->type >= WCRYPTO_HASH_MAX)) { + WD_ERR("hash parameter error, type = %u\n", hash->type); + return -WD_EINVAL; + } + + if (unlikely(__atomic_load_n(&info->used, __ATOMIC_RELAXED) > + QM_Q_DEPTH - SM2_SQE_NUM - 1)) { + WD_ERR("fill sm2 enc sqe: queue is full!\n"); + return -WD_EBUSY; + } + + /* split message into two inner request msg + * firest msg used to compute k * g + * second msg used to compute k * pb + */ + ret = split_req(info, req_src, req_dst); + if (unlikely(ret)) { + WD_ERR("failed to split req, ret = %d\n", ret); + return ret; + } + + ret = qm_fill_ecc_sqe_general(req_dst[0], info, i); + if (unlikely(ret)) { + WD_ERR("failed to fill 1th sqe, ret = %d\n", ret); + goto fail_fill_sqe; + } + + i = (i + 1) % QM_Q_DEPTH; + ret = qm_fill_ecc_sqe_general(req_dst[1], info, i); + if (unlikely(ret)) { + WD_ERR("failed to fill 2th sqe, ret = %d\n", ret); + goto fail_fill_sqe; + } + + /* make sure the request is all in memory before doorbell */ + mb(); + info->sq_tail_index = i; + qm_tx_update(info, 1); + + return ret; + +fail_fill_sqe: + free_req(info, req_dst[0]); + free_req(info, req_dst[1]); + + return ret; +} + +static int fill_sm2_dec_sqe(void *message, struct qm_queue_info *info, __u16 i) +{ + struct wcrypto_hash_mt *hash = &((struct q_info *)info->q->qinfo)->hash; + struct wcrypto_ecc_msg *req_src = message; + struct wcrypto_sm2_dec_in *din = (void *)req_src->in; + struct q_info *qinfo = info->q->qinfo; + struct wd_mm_br *br = &qinfo->br; + __u32 ksz = req_src->key_bytes; + struct wcrypto_ecc_msg *dst; + int ret; + + /* c2 data lens <= 4096 bit */ + if (din->c2.dsize <= BITS_TO_BYTES(4096) && + req_src->hash_type == WCRYPTO_HASH_SM3) + return qm_fill_ecc_sqe_general(req_src, info, i); + + if (unlikely(!hash->cb || hash->type >= WCRYPTO_HASH_MAX)) { + WD_ERR("hash parameter error, type = %u\n", hash->type); + return -WD_EINVAL; + } + + /* dst last store point "struct wcrypto_ecc_msg *" */ + dst = malloc(sizeof(*dst) + sizeof(struct wcrypto_ecc_msg *)); + if (unlikely(!dst)) + return -WD_ENOMEM; + + /* compute d * c1 */ + memcpy(dst, req_src, sizeof(*dst)); + + dst->op_type = HPRE_SM2_DEC; + *(struct wcrypto_ecc_msg **)(dst + 1) = req_src; + dst->in = (void *)&din->c1; + dst->out = br->alloc(br->usr, ECDH_OUT_PARAMS_SZ(ksz)); + if (unlikely(!dst->out)) { + ret = -WD_ENOMEM; + goto free_dst; + } + + ret = qm_fill_ecc_sqe_general(dst, info, i); + if (unlikely(ret)) + goto free_out; + + return ret; + +free_out: + br->free(br->usr, dst->out); +free_dst: + free(dst); + return ret; +} + +int qm_fill_ecc_sqe(void *message, struct qm_queue_info *info, __u16 i) +{ + struct wcrypto_ecc_msg *msg = message; + + if (msg->op_type == WCRYPTO_SM2_ENCRYPT) + return fill_sm2_enc_sqe(message, info, i); + else if (msg->op_type == WCRYPTO_SM2_DECRYPT) + return fill_sm2_dec_sqe(message, info, i); + else + return qm_fill_ecc_sqe_general(message, info, i); +} + +static int qm_parse_ecc_sqe_general(void *msg, const struct qm_queue_info *info, + __u16 i, __u16 usr) +{ + struct wcrypto_ecc_msg *ecc_msg = info->req_cache[i]; + struct hisi_hpre_sqe *hw_msg = msg; + __u64 dma_out, dma_in, dma_key; + struct wd_queue *q = info->q; + size_t ilen = 0; + size_t olen = 0; + __u16 kbytes; + int ret; + + if (unlikely(!ecc_msg)) { + WD_ERR("info->req_cache is null at index:%hu\n", i); + return 0; + } + + /* if this hw msg not belong to me, then try again */ + if (usr && LOW_U16(hw_msg->low_tag) != usr) + return 0; + + kbytes = ecc_msg->key_bytes; + qm_ecc_get_io_len(hw_msg->alg, kbytes, &ilen, &olen); + if (hw_msg->done != HPRE_HW_TASK_DONE || + hw_msg->etype || hw_msg->etype1) { + WD_ERR("HPRE do ecc fail!done=0x%x, etype=0x%x, etype1=0x%x\n", + hw_msg->done, hw_msg->etype, hw_msg->etype1); + + if (hw_msg->done == HPRE_HW_TASK_INIT) + ecc_msg->result = WD_EINVAL; + else /* Need to indentify which hw err happened */ + ecc_msg->result = WD_IN_EPARA; + } else { + ecc_msg->result = WD_SUCCESS; + ret = qm_ecc_out_transfer(ecc_msg, hw_msg); + if (unlikely(ret)) { + WD_ERR("qm ecc out transfer fail!\n"); + ecc_msg->result = WD_OUT_EPARA; + } + } + + dma_out = DMA_ADDR(hw_msg->hi_out, hw_msg->low_out); + dma_key = DMA_ADDR(hw_msg->hi_key, hw_msg->low_key); + dma_in = DMA_ADDR(hw_msg->hi_in, hw_msg->hi_in); + drv_iova_unmap(q, NULL, (void *)(uintptr_t)dma_in, olen); + drv_iova_unmap(q, NULL, (void *)(uintptr_t)dma_out, olen); + drv_iova_unmap(q, NULL, (void *)(uintptr_t)dma_key, kbytes); + + return 1; +} + +static int parse_first_sqe(void *hw_msg, struct qm_queue_info *info, __u16 idx, + __u16 usr) +{ + struct wcrypto_ecc_msg *msg = info->req_cache[idx]; + struct wcrypto_ecc_msg *msg_src; + __u16 i = idx; + int ret; + + ret = qm_parse_ecc_sqe_general(hw_msg, info, i, usr); + if (!ret) + return ret; + + msg_src = *(struct wcrypto_ecc_msg **)(msg + 1); + msg_src->result = msg->result; + info->req_cache[i] = NULL; + if (i == QM_Q_DEPTH - 1) { + info->cqc_phase = !(info->cqc_phase); + i = 0; + } else { + i++; + } + + if (msg->result != WD_SUCCESS) + WD_ERR("first BD error = %u\n", msg->result); + + info->cq_head_index = i; + qm_rx_update(info, 1); + + return 1; +} + +static int parse_second_sqe(void *hw_msg, struct qm_queue_info *info, __u16 i, + __u16 usr, struct wcrypto_ecc_msg *msg_src) +{ + struct wcrypto_ecc_msg *msg; + int ret = -WD_EIO; + void *sqe = NULL; + struct cqe *cqe; + int cnt = 0; + void *resp; + __u16 j; + + while (1) { + /* continue recv second cqe */ + cqe = info->cq_base + i * sizeof(struct cqe); + if (info->cqc_phase == CQE_PHASE(cqe)) { + /* make sure the request is all in memory before doorbell */ + mb(); + j = CQE_SQ_HEAD_INDEX(cqe); + if (j >= QM_Q_DEPTH) { + WD_ERR("2th CQE_SQ_HEAD_INDEX(%u) error\n", j); + return ret; + } + + msg = info->req_cache[i]; + sqe = (void *)((uintptr_t)info->sq_base + + j * info->sqe_size); + ret = qm_parse_ecc_sqe_general(sqe, info, i, usr); + if (unlikely(!ret)) + return ret; + break; + } + + if (unlikely(wd_reg_read(info->ds_rx_base) == 1)) { + qm_rx_from_cache(info, &resp, 1); + return -WD_HW_EACCESS; + } + + if (cnt++ > MAX_WAIT_CNT) + return 0; + usleep(1); + } + + if (msg->result) { + WD_ERR("second BD error = %u\n", msg->result); + msg_src->result = WD_OUT_EPARA; + } + + return ret; +} + +static __u32 get_hash_bytes(__u8 type) +{ + __u32 val = 0; + + switch (type) { + case WCRYPTO_HASH_SHA1: + val = BITS_TO_BYTES(160); + break; + case WCRYPTO_HASH_SHA256: + case WCRYPTO_HASH_SM3: + val = BITS_TO_BYTES(256); + break; + case WCRYPTO_HASH_MD4: + case WCRYPTO_HASH_MD5: + val = BITS_TO_BYTES(128); + break; + case WCRYPTO_HASH_SHA224: + val = BITS_TO_BYTES(224); + break; + case WCRYPTO_HASH_SHA384: + val = BITS_TO_BYTES(384); + break; + case WCRYPTO_HASH_SHA512: + val = BITS_TO_BYTES(512); + break; + default: + WD_ERR("get hash bytes: type %u error!\n", type); + break; + } + + return val; +} + +static void msg_pack(char *dst, __u64 *out_len, + const void *src, __u32 src_len) +{ + if (unlikely(!src || !src_len)) + return; + + memcpy(dst + *out_len, src, src_len); + *out_len += src_len; +} + +static int sm2_kdf(struct wd_dtb *out, struct wcrypto_ecc_point *x2y2, + __u64 hash_mt_len, struct q_info *q_info) +{ + struct wcrypto_hash_mt *hash = &q_info->hash; + char p_out[MAX_HASH_LENS] = {0}; + __u64 m_len = hash_mt_len; + __u32 h_bytes, x2y2_len; + char *tmp = out->data; + __u64 in_len, lens; + char *p_in, *t_out; + __u8 ctr[4]; + __u32 i = 1; + int ret; + + h_bytes = get_hash_bytes(hash->type); + if (unlikely(!h_bytes)) + return -WD_EINVAL; + + x2y2_len = x2y2->x.dsize + x2y2->y.dsize; + lens = x2y2_len + sizeof(ctr); + p_in = malloc(lens); + if (unlikely(!p_in)) + return -WD_ENOMEM; + + out->dsize = m_len; + + /* + * Use big-endian mode to store the value of counter i in ctr, + * i >> 8/16/24 for intercepts 8-bits whole-byte data. + */ + while (1) { + ctr[3] = i & 0xFF; + ctr[2] = (i >> 8) & 0xFF; + ctr[1] = (i >> 16) & 0xFF; + ctr[0] = (i >> 24) & 0xFF; + in_len = 0; + msg_pack(p_in, &in_len, x2y2->x.data, x2y2_len); + msg_pack(p_in, &in_len, ctr, sizeof(ctr)); + + t_out = m_len >= h_bytes ? tmp : p_out; + ret = hash->cb(p_in, in_len, t_out, h_bytes, hash->usr); + if (ret) { + WD_ERR("failed to hash cb, ret = %d!\n", ret); + break; + } + + if (m_len >= h_bytes) { + tmp += h_bytes; + m_len -= h_bytes; + if (!m_len) + break; + } else { + memcpy(tmp, p_out, m_len); + break; + } + + i++; + } + + free(p_in); + + return ret; +} + +static void sm2_xor(struct wd_dtb *val1, struct wd_dtb *val2) +{ + int i; + + for (i = 0; i < val1->dsize; ++i) + val1->data[i] = (char)((__u8)val1->data[i] ^ + (__u8)val2->data[i]); +} + +static int is_equal(struct wd_dtb *src, struct wd_dtb *dst) +{ + if (src->dsize == dst->dsize && + !memcmp(src->data, dst->data, src->dsize)) { + return 0; + } + + return -1; +} + +static int sm2_hash(struct wd_dtb *out, struct wcrypto_ecc_point *x2y2, + struct wd_dtb *msg, struct q_info *q_info) +{ + struct wcrypto_hash_mt *hash = &q_info->hash; + __u64 lens = (__u64)msg->dsize + 2 * (__u64)x2y2->x.dsize; + char hash_out[MAX_HASH_LENS] = {0}; + __u64 in_len = 0; + __u32 h_bytes; + char *p_in; + int ret; + + h_bytes = get_hash_bytes(hash->type); + if (unlikely(!h_bytes)) + return -WD_EINVAL; + + p_in = malloc(lens); + if (unlikely(!p_in)) + return -WD_ENOMEM; + + msg_pack(p_in, &in_len, x2y2->x.data, x2y2->x.dsize); + msg_pack(p_in, &in_len, msg->data, msg->dsize); + msg_pack(p_in, &in_len, x2y2->y.data, x2y2->y.dsize); + ret = hash->cb(p_in, in_len, hash_out, h_bytes, hash->usr); + if (unlikely(ret)) { + WD_ERR("failed to hash cb, ret = %d!\n", ret); + goto fail; + } + + out->dsize = h_bytes; + memcpy(out->data, hash_out, out->dsize); + +fail: + free(p_in); + + return ret; +} + +static int sm2_convert_enc_out(struct wcrypto_ecc_msg *src, + struct wcrypto_ecc_msg *first, + struct wcrypto_ecc_msg *second, void *q_info) +{ + struct wcrypto_ecc_out *out = (void *)src->out; + struct wcrypto_ecc_in *in = (void *)src->in; + struct wcrypto_sm2_enc_out *eout = &out->param.eout; + struct wcrypto_sm2_enc_in *ein = &in->param.ein; + struct wcrypto_ecc_point x2y2; + __u32 ksz = src->key_bytes; + struct wd_dtb *kdf_out; + int ret; + + /* enc origin out data fmt: + * | x1y1(2*256bit) | x2y2(2*256bit) | other | + * final out data fmt: + * | c1(2*256bit) | c2(plaintext size) | c3(256bit) | + */ + x2y2.x.data = (void *)second->out; + x2y2.x.dsize = ksz; + x2y2.y.dsize = ksz; + x2y2.y.data = (void *)(second->out + ksz); + + /* C1 */ + memcpy(eout->c1.x.data, first->out, ksz + ksz); + + /* C3 = hash(x2 || M || y2) */ + ret = sm2_hash(&eout->c3, &x2y2, &ein->plaintext, q_info); + if (unlikely(ret)) { + WD_ERR("failed to sm2 hash, ret = %d!\n", ret); + return ret; + } + + /* t = KDF(x2 || y2, klen) */ + kdf_out = &eout->c2; + ret = sm2_kdf(kdf_out, &x2y2, ein->plaintext.dsize, q_info); + if (unlikely(ret)) { + WD_ERR("failed to sm2 kdf, ret = %d!\n", ret); + return ret; + } + + /* C2 = M XOR t */ + sm2_xor(kdf_out, &ein->plaintext); + + return ret; +} + +static int sm2_convert_dec_out(struct wcrypto_ecc_msg *src, + struct wcrypto_ecc_msg *dst, void *q_info) +{ + struct wcrypto_ecc_out *out = (void *)src->out; + struct wcrypto_sm2_dec_out *dout = &out->param.dout; + struct wcrypto_ecc_in *in = (void *)src->in; + struct wcrypto_sm2_dec_in *din = &in->param.din; + struct wcrypto_ecc_point x2y2; + __u32 ksz = dst->key_bytes; + int ret; + + /* dec origin out data fmt: + * | x2y2(2*256bit) | other | + * final out data fmt: + * | plaintext | + */ + + /* x2y2 :copy x2y2 into din->c1 */ + x2y2.x.data = (void *)dst->out; + x2y2.y.data = (void *)(dst->out + ksz); + x2y2.x.dsize = ksz; + x2y2.y.dsize = ksz; + + /* t = KDF(x2 || y2, klen) */ + ret = sm2_kdf(&dout->plaintext, &x2y2, din->c2.dsize, q_info); + if (unlikely(ret)) { + WD_ERR("failed to sm2 kdf, ret = %d!\n", ret); + return ret; + } + + /* M' = C2 XOR t */ + sm2_xor(&dout->plaintext, &din->c2); + + /* u = hash(x2 || M' || y2), save u to din->c2 */ + ret = sm2_hash(&din->c1.x, &x2y2, &dout->plaintext, q_info); + if (unlikely(ret)) { + WD_ERR("failed to compute c3, ret = %d!\n", ret); + return ret; + } + + /* u == c3 */ + ret = is_equal(&din->c1.x, &din->c3); + if (ret) + WD_ERR("failed to dec sm2, u != C3!\n"); + + return ret; +} + +static int parse_sm2_enc_sqe(void *hw_msg, struct qm_queue_info *info, + __u16 i, __u16 usr) +{ + struct wcrypto_ecc_msg *first = info->req_cache[i]; + struct wcrypto_ecc_msg *src, *second; + int ret; + + ret = parse_first_sqe(hw_msg, info, i, usr); + if (!ret) + return ret; + + src = *(struct wcrypto_ecc_msg **)(first + 1); + second = info->req_cache[info->cq_head_index]; + ret = parse_second_sqe(hw_msg, info, info->cq_head_index, usr, src); + if (unlikely(!ret)) { + WD_ERR("failed to parse second sqe, timeout!\n"); + goto fail; + } else if (unlikely(ret < 0)) { + WD_ERR("failed to parse second sqe, ret = %d!\n", ret); + goto fail; + } + + src->op_type = WCRYPTO_SM2_ENCRYPT; + info->req_cache[info->cq_head_index] = src; + ret = sm2_convert_enc_out(src, first, second, info->q->qinfo); + if (unlikely(ret)) { + WD_ERR("failed to convert sm2 std fmt, ret = %d!\n", ret); + src->result = WD_OUT_EPARA; + } + + ret = 1; +fail: + free_req(info, first); + free_req(info, second); + + return ret; +} + +static int parse_sm2_dec_sqe(void *hw_msg, struct qm_queue_info *info, + __u16 i, __u16 usr) +{ + struct wcrypto_ecc_msg *dst = info->req_cache[i]; + struct q_info *qinfo = info->q->qinfo; + struct wd_mm_br *br = &qinfo->br; + struct wcrypto_ecc_msg *src; + int ret; + + ret = qm_parse_ecc_sqe_general(hw_msg, info, i, usr); + if (!ret) + return ret; + + src = *(struct wcrypto_ecc_msg **)(dst + 1); + src->op_type = WCRYPTO_SM2_DECRYPT; + src->result = dst->result; + info->req_cache[i] = src; + + if (dst->result != WD_SUCCESS) { + WD_ERR("msg result error = %u!\n", dst->result); + src->result = WD_OUT_EPARA; + goto fail; + } + + ret = sm2_convert_dec_out(src, dst, info->q->qinfo); + if (unlikely(ret)) { + WD_ERR("failed to convert sm2 dec out, ret = %d!\n", ret); + src->result = WD_OUT_EPARA; + } + +fail: + br->free(br->usr, dst->out); + free(dst); + + return 1; +} + +int qm_parse_ecc_sqe(void *message, const struct qm_queue_info *info, + __u16 i, __u16 usr) +{ + struct wcrypto_ecc_msg *msg = info->req_cache[i]; + + if (msg->op_type == HPRE_SM2_ENC) + return parse_sm2_enc_sqe(message, (void *)info, i, usr); + else if (msg->op_type == HPRE_SM2_DEC) + return parse_sm2_dec_sqe(message, (void *)info, i, usr); + + return qm_parse_ecc_sqe_general(message, (void *)info, i, usr); +} diff --git a/uadk/v1/drv/hisi_hpre_udrv.h b/uadk/v1/drv/hisi_hpre_udrv.h new file mode 100644 index 0000000..632ad28 --- /dev/null +++ b/uadk/v1/drv/hisi_hpre_udrv.h @@ -0,0 +1,88 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#ifndef HISI_HPRE_UDRV_H +#define HISI_HPRE_UDRV_H + +#include "v1/drv/hisi_qm_udrv.h" + +enum hpre_alg_type { + HPRE_ALG_NC_NCRT = 0x0, + HPRE_ALG_NC_CRT = 0x1, + HPRE_ALG_KG_STD = 0x2, + HPRE_ALG_KG_CRT = 0x3, + HPRE_ALG_DH_G2 = 0x4, + HPRE_ALG_DH = 0x5, + HPRE_ALG_PRIME = 0x6, + HPRE_ALG_MOD = 0x7, + HPRE_ALG_MOD_INV = 0x8, + HPRE_ALG_MUL = 0x9, + HPRE_ALG_COPRIME = 0xA, + HPRE_ALG_ECC_CURVE_TEST = 0xB, + HPRE_ALG_ECDH_PLUS = 0xC, + HPRE_ALG_ECDH_MULTIPLY = 0xD, + HPRE_ALG_ECDSA_SIGN = 0xE, + HPRE_ALG_ECDSA_VERF = 0xF, + HPRE_ALG_X_DH_MULTIPLY = 0x10, + HPRE_ALG_SM2_KEY_GEN = 0x11, + HPRE_ALG_SM2_SIGN = 0x12, + HPRE_ALG_SM2_VERF = 0x13, + HPRE_ALG_SM2_ENC = 0x14, + HPRE_ALG_SM2_DEC = 0x15 +}; + +struct hisi_hpre_sqe { + __u32 alg : 5; + + /* error type */ + __u32 etype : 11; + __u32 etype1 : 14; + __u32 done : 2; + __u32 task_len1 : 8; + __u32 task_len2 : 8; + __u32 mrttest_num : 8; + __u32 uwkey_enb : 1; + __u32 sm2_ksel : 1; + __u32 sva_bypass: 1; + __u32 sva_status: 4; + __u32 bd_rsv2 : 1; + __u32 low_key; + __u32 hi_key; + __u32 low_in; + __u32 hi_in; + __u32 low_out; + __u32 hi_out; + __u32 low_tag; + __u32 hi_tag; + __u32 sm2_mlen :9; + __u32 rsvd1 :7; + __u32 uwkey_sel :4; + __u32 wrap_num :3; + __u32 rsvd2 :9; + __u32 kek_key; + __u32 rsvd3[4]; +}; + +int qm_fill_dh_sqe(void *message, struct qm_queue_info *info, __u16 i); +int qm_parse_dh_sqe(void *msg, const struct qm_queue_info *info, + __u16 i, __u16 usr); +int qm_fill_rsa_sqe(void *message, struct qm_queue_info *info, __u16 i); +int qm_parse_rsa_sqe(void *msg, const struct qm_queue_info *info, + __u16 i, __u16 usr); +int qm_fill_ecc_sqe(void *message, struct qm_queue_info *info, __u16 i); +int qm_parse_ecc_sqe(void *message, const struct qm_queue_info *info, + __u16 i, __u16 usr); +#endif diff --git a/uadk/v1/drv/hisi_qm_udrv.c b/uadk/v1/drv/hisi_qm_udrv.c new file mode 100644 index 0000000..eb29598 --- /dev/null +++ b/uadk/v1/drv/hisi_qm_udrv.c @@ -0,0 +1,819 @@ +/* + * Copyright 2018-2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "v1/drv/hisi_zip_udrv.h" +#include "v1/drv/hisi_hpre_udrv.h" +#include "v1/drv/hisi_sec_udrv.h" +#include "v1/drv/hisi_qm_udrv.h" + +#define HISI_SGL_SGE_NUM_MAX 255 +#define HISI_SGL_ALIGN_SZ 64 +#define HISI_SGL_SGE_ALIGN_SZ 32 + +/* get hisi hardware sgl information, like sge_size, sgl_size, and its align size. + * sgl numbers in a chain : 256 at most; + * sge numbers of a sgl: 1 ~ 255; + * a sge size: 1B ~ 8M; + * data in little-endian in sgl; + */ +int qm_hw_sgl_info(struct hw_sgl_info *sgl_info) +{ + sgl_info->sge_sz = sizeof(struct hisi_sge); + sgl_info->sge_align_sz = HISI_SGL_SGE_ALIGN_SZ; + sgl_info->sgl_sz = sizeof(struct hisi_sgl); + sgl_info->sgl_align_sz = HISI_SGL_ALIGN_SZ; + + return WD_SUCCESS; +} + +/* 'num' starts from 1 */ +static int qm_hw_sgl_sge_init(struct wd_sgl *sgl, struct hisi_sgl *hisi_sgl, + struct wd_mm_br *br, int num, __u32 buf_sz) +{ + void *buf; + + buf = wd_get_sge_buf(sgl, num); + if (!buf) + return -WD_EINVAL; + + hisi_sgl->sge_entries[num - 1].buf = (uintptr_t)br->iova_map(br->usr, + buf, buf_sz); + if (!hisi_sgl->sge_entries[num - 1].buf) { + WD_ERR("failed to map buf!\n"); + return -WD_ENOMEM; + } + + hisi_sgl->sge_entries[num - 1].len = buf_sz; + drv_set_sgl_sge_pri(sgl, num - 1, &hisi_sgl->sge_entries[num - 1]); + + return WD_SUCCESS; +} + +/* 'num' starts from 1 */ +void qm_hw_sgl_sge_uninit(struct wd_sgl *sgl, struct hisi_sgl *hisi_sgl, + int num, struct wd_mm_br *br, __u32 buf_sz) +{ + void *buf; + + buf = wd_get_sge_buf(sgl, num); + if (!buf) + return; + + br->iova_unmap(br->usr, (void *)hisi_sgl->sge_entries[num - 1].buf, + buf, buf_sz); +} + +int qm_hw_sgl_init(void *pool, struct wd_sgl *sgl) +{ + int buf_num = wd_get_sgl_buf_num(sgl); + int sge_num = wd_get_sgl_sge_num(sgl); + struct hisi_sgl *hisi_sgl; + struct wd_mm_br *br; + int i, j, ret; + __u32 buf_sz; + + if (!pool || buf_num < 0 || sge_num < 0) { + WD_ERR("hw_sgl_init init param err!\n"); + return -WD_EINVAL; + } + + ret = wd_get_sgl_bufsize(sgl, &buf_sz); + if (ret) { + WD_ERR("failed to get sgl bufsize!\n"); + return ret; + } + + buf_num = MIN(buf_num, HISI_SGL_SGE_NUM_MAX); + sge_num = MIN(sge_num, HISI_SGL_SGE_NUM_MAX); + br = drv_get_br(pool); + + hisi_sgl = br->alloc(br->usr, sizeof(struct hisi_sgl) + + sizeof(struct hisi_sge) * buf_num); + if (!hisi_sgl) + return -WD_ENOMEM; + + hisi_sgl->entry_sum_in_chain = buf_num; + hisi_sgl->entry_sum_in_sgl = buf_num; + hisi_sgl->entry_length_in_sgl = buf_num; + hisi_sgl->next_dma = 0; + + for (i = 0; i < buf_num; i++) { + ret = qm_hw_sgl_sge_init(sgl, hisi_sgl, br, i + 1, buf_sz); + if (ret) { + WD_ERR("failed to map buf, ret = %d.\n", ret); + goto sgl_sge_init_err; + } + } + + for (i = buf_num; i < sge_num; i++) { + hisi_sgl->sge_entries[i].len = 0; + hisi_sgl->sge_entries[i].buf = 0; + drv_set_sgl_sge_pri(sgl, i, &hisi_sgl->sge_entries[i]); + } + + drv_set_sgl_pri(sgl, hisi_sgl); + return WD_SUCCESS; + +sgl_sge_init_err: + for (j = i - 1; j >= 0; j--) + qm_hw_sgl_sge_uninit(sgl, hisi_sgl, j + 1, br, buf_sz); + + br->free(br->usr, hisi_sgl); + + return ret; +} + +void qm_hw_sgl_uninit(void *pool, struct wd_sgl *sgl) +{ + struct hisi_sgl *hisi_sgl = drv_get_sgl_pri(sgl); + int buf_num = wd_get_sgl_buf_num(sgl); + struct wd_mm_br *br; + __u32 buf_sz; + int i, ret; + void *buf; + + if (!pool || buf_num < 0) { + WD_ERR("hw_sgl_init init param err!\n"); + return; + } + + ret = wd_get_sgl_bufsize(sgl, &buf_sz); + if (ret) + return; + + buf_num = MIN(buf_num, HISI_SGL_SGE_NUM_MAX); + br = drv_get_br(pool); + + for (i = 0; i < buf_num; i++) { + buf = wd_get_sge_buf(sgl, i + 1); + if (!buf) { + WD_ERR("failed to get sge buf i = %d.\n", i); + return; + } + br->iova_unmap(br->usr, (void *)hisi_sgl->sge_entries[i].buf, + buf, buf_sz); + } + br->free(br->usr, hisi_sgl); +} + +int qm_hw_sgl_merge(void *pool, struct wd_sgl *dst_sgl, struct wd_sgl *src_sgl) +{ + struct hisi_sgl *d = drv_get_sgl_pri(dst_sgl); + struct hisi_sgl *s = drv_get_sgl_pri(src_sgl); + size_t size; + int ret; + + ret = wd_get_sgl_mem_size(src_sgl, &size); + if (ret) + return ret; + + d->next_dma = (uintptr_t)wd_sgl_iova_map(pool, src_sgl, size); + if (!d->next_dma) + return -WD_ENOMEM; + + d->entry_sum_in_chain = s->entry_sum_in_sgl + d->entry_sum_in_sgl; + + return WD_SUCCESS; +} + +int qm_db_v1(struct qm_queue_info *q, __u8 cmd, + __u16 idx, __u8 priority) +{ + void *base = q->doorbell_base; + __u16 sqn = q->sqn; + __u64 doorbell; + + doorbell = (__u64)sqn | ((__u64)cmd << QM_DBELL_CMD_SHIFT); + doorbell |= ((__u64)idx | ((__u64)priority << QM_DBELL_CMD_SHIFT)) << + QM_DBELL_HLF_SHIFT; + *((__u64 *)base) = doorbell; + + return 0; +} + +static int qm_db_v2(struct qm_queue_info *q, __u8 cmd, + __u16 idx, __u8 priority) +{ + __u16 sqn = q->sqn & QM_DBELL_SQN_MASK; + void *base = q->doorbell_base; + __u64 doorbell; + + doorbell = (__u64)sqn | ((__u64)(cmd & QM_DBELL_CMD_MASK) << + QM_V2_DBELL_CMD_SHIFT); + doorbell |= ((__u64)idx | ((__u64)priority << QM_DBELL_CMD_SHIFT)) << + QM_DBELL_HLF_SHIFT; + *((__u64 *)base) = doorbell; + + return 0; +} + +static int qm_set_queue_regions(struct wd_queue *q) +{ + struct q_info *qinfo = q->qinfo; + struct qm_queue_info *info = qinfo->priv; + + info->sq_base = wd_drv_mmap_qfr(q, WD_UACCE_QFRT_DUS, 0); + if (info->sq_base == MAP_FAILED) { + info->sq_base = NULL; + WD_ERR("mmap dus fail\n"); + return -ENOMEM; + } + + info->mmio_base = wd_drv_mmap_qfr(q, WD_UACCE_QFRT_MMIO, 0); + if (info->mmio_base == MAP_FAILED) { + wd_drv_unmmap_qfr(q, info->sq_base, WD_UACCE_QFRT_DUS, 0); + info->sq_base = NULL; + info->mmio_base = NULL; + WD_ERR("mmap mmio fail\n"); + return -ENOMEM; + } + + return 0; +} + +static void qm_unset_queue_regions(struct wd_queue *q) +{ + struct q_info *qinfo = q->qinfo; + struct qm_queue_info *info = qinfo->priv; + + wd_drv_unmmap_qfr(q, info->mmio_base, WD_UACCE_QFRT_MMIO, 0); + wd_drv_unmmap_qfr(q, info->sq_base, WD_UACCE_QFRT_DUS, 0); + info->sq_base = NULL; + info->mmio_base = NULL; +} + +static bool hpre_alg_info_init(struct wd_queue *q, const char *alg) +{ + struct wcrypto_paras *priv = &q->capa.priv; + struct q_info *qinfo = q->qinfo; + struct qm_queue_info *info = qinfo->priv; + bool is_found = true; + + /* DH/RSA: qm sqc_type = 0, ECC: qm sqc_type = 1 */ + if (!strcmp(alg, "rsa")) { + qinfo->atype = WCRYPTO_RSA; + info->sqe_size = QM_HPRE_BD_SIZE; + info->sqe_fill[WCRYPTO_RSA] = qm_fill_rsa_sqe; + info->sqe_parse[WCRYPTO_RSA] = qm_parse_rsa_sqe; + priv->direction = 0; + } else if (!strcmp(alg, "dh")) { + qinfo->atype = WCRYPTO_DH; + info->sqe_size = QM_HPRE_BD_SIZE; + info->sqe_fill[WCRYPTO_DH] = qm_fill_dh_sqe; + info->sqe_parse[WCRYPTO_DH] = qm_parse_dh_sqe; + priv->direction = 0; + } else if (!strcmp(alg, "ecdh")) { + qinfo->atype = WCRYPTO_ECDH; + info->sqe_size = QM_HPRE_BD_SIZE; + info->sqe_fill[WCRYPTO_ECDH] = qm_fill_ecc_sqe; + info->sqe_parse[WCRYPTO_ECDH] = qm_parse_ecc_sqe; + priv->direction = 1; + } else if (!strcmp(alg, "x448")) { + qinfo->atype = WCRYPTO_X448; + info->sqe_size = QM_HPRE_BD_SIZE; + info->sqe_fill[WCRYPTO_X448] = qm_fill_ecc_sqe; + info->sqe_parse[WCRYPTO_X448] = qm_parse_ecc_sqe; + priv->direction = 1; + } else if (!strcmp(alg, "x25519")) { + qinfo->atype = WCRYPTO_X25519; + info->sqe_size = QM_HPRE_BD_SIZE; + info->sqe_fill[WCRYPTO_X25519] = qm_fill_ecc_sqe; + info->sqe_parse[WCRYPTO_X25519] = qm_parse_ecc_sqe; + priv->direction = 1; + } else if (!strcmp(alg, "ecdsa")) { + qinfo->atype = WCRYPTO_ECDSA; + info->sqe_size = QM_HPRE_BD_SIZE; + info->sqe_fill[WCRYPTO_ECDSA] = qm_fill_ecc_sqe; + info->sqe_parse[WCRYPTO_ECDSA] = qm_parse_ecc_sqe; + priv->direction = 1; + } else if (!strcmp(alg, "sm2")) { + qinfo->atype = WCRYPTO_SM2; + info->sqe_size = QM_HPRE_BD_SIZE; + info->sqe_fill[WCRYPTO_SM2] = qm_fill_ecc_sqe; + info->sqe_parse[WCRYPTO_SM2] = qm_parse_ecc_sqe; + priv->direction = 1; + } else { + is_found = false; + } + + return is_found; +} + +static bool sec_alg_info_init(struct q_info *qinfo, const char *alg) +{ + struct qm_queue_info *info = qinfo->priv; + bool is_found = true; + + if (!strcmp(alg, "cipher")) { + qinfo->atype = WCRYPTO_CIPHER; + info->sqe_size = QM_SEC_BD_SIZE; + if (strstr(qinfo->hw_type, HISI_QM_API_VER2_BASE)) { + info->sqe_fill[WCRYPTO_CIPHER] = qm_fill_cipher_sqe; + info->sqe_parse[WCRYPTO_CIPHER] = qm_parse_cipher_sqe; + } else if (strstr(qinfo->hw_type, HISI_QM_API_VER3_BASE)) { + info->sqe_fill[WCRYPTO_CIPHER] = qm_fill_cipher_bd3_sqe; + info->sqe_parse[WCRYPTO_CIPHER] = qm_parse_cipher_bd3_sqe; + } + } else if (!strcmp(alg, "digest")) { + qinfo->atype = WCRYPTO_DIGEST; + info->sqe_size = QM_SEC_BD_SIZE; + if (strstr(qinfo->hw_type, HISI_QM_API_VER2_BASE)) { + info->sqe_fill[WCRYPTO_DIGEST] = qm_fill_digest_sqe; + info->sqe_parse[WCRYPTO_DIGEST] = qm_parse_digest_sqe; + } else if (strstr(qinfo->hw_type, HISI_QM_API_VER3_BASE)) { + info->sqe_fill[WCRYPTO_DIGEST] = qm_fill_digest_bd3_sqe; + info->sqe_parse[WCRYPTO_DIGEST] = qm_parse_digest_bd3_sqe; + } + } else if (!strcmp(alg, "aead")) { + qinfo->atype = WCRYPTO_AEAD; + info->sqe_size = QM_SEC_BD_SIZE; + if (strstr(qinfo->hw_type, HISI_QM_API_VER2_BASE)) { + info->sqe_fill[WCRYPTO_AEAD] = qm_fill_aead_sqe; + info->sqe_parse[WCRYPTO_AEAD] = qm_parse_aead_sqe; + } else if (strstr(qinfo->hw_type, HISI_QM_API_VER3_BASE)) { + info->sqe_fill[WCRYPTO_AEAD] = qm_fill_aead_bd3_sqe; + info->sqe_parse[WCRYPTO_AEAD] = qm_parse_aead_bd3_sqe; + } + } else { + is_found = false; + } + + if (is_found) { + info->sgl_info = qm_hw_sgl_info; + info->sgl_init = qm_hw_sgl_init; + info->sgl_uninit = qm_hw_sgl_uninit; + info->sgl_merge = qm_hw_sgl_merge; + } + + return is_found; +} + +static bool zip_alg_info_init(struct q_info *qinfo, const char *alg) +{ + struct qm_queue_info *info = qinfo->priv; + bool is_found = false; + + if (!strcmp(alg, "zlib") || + !strcmp(alg, "gzip") || + !strcmp(alg, "deflate") || + !strcmp(alg, "lz77_zstd")) { + qinfo->atype = WCRYPTO_COMP; + info->sqe_size = QM_ZIP_BD_SIZE; + if (strstr(qinfo->hw_type, HISI_QM_API_VER2_BASE)) { + info->sqe_fill[WCRYPTO_COMP] = qm_fill_zip_sqe; + info->sqe_parse[WCRYPTO_COMP] = qm_parse_zip_sqe; + } else if (strstr(qinfo->hw_type, HISI_QM_API_VER3_BASE)) { + info->sqe_fill[WCRYPTO_COMP] = qm_fill_zip_sqe_v3; + info->sqe_parse[WCRYPTO_COMP] = qm_parse_zip_sqe_v3; + } + info->sgl_info = qm_hw_sgl_info; + info->sgl_init = qm_hw_sgl_init; + info->sgl_uninit = qm_hw_sgl_uninit; + info->sgl_merge = qm_hw_sgl_merge; + is_found = true; + } + + return is_found; +} + +static int qm_set_queue_alg_info(struct wd_queue *q) +{ + const char *alg = q->capa.alg; + struct q_info *qinfo = q->qinfo; + struct qm_queue_info *info = qinfo->priv; + struct wcrypto_paras *priv = &q->capa.priv; + int ret = -WD_EINVAL; + + if (hpre_alg_info_init(q, alg)) { + ret = WD_SUCCESS; + } else if (zip_alg_info_init(qinfo, alg)) { + ret = WD_SUCCESS; + } else if (sec_alg_info_init(qinfo, alg)) { + /* setting the type is 0 for sqc_type */ + priv->direction = 0; + ret = WD_SUCCESS; + } else if (!strcmp(alg, "xts(aes)") || + !strcmp(alg, "xts(sm4)")) { + qinfo->atype = WCRYPTO_CIPHER; + info->sqe_size = QM_ZIP_BD_SIZE; + info->sqe_fill[WCRYPTO_CIPHER] = qm_fill_zip_cipher_sqe; + info->sqe_parse[WCRYPTO_CIPHER] = qm_parse_zip_cipher_sqe; + ret = WD_SUCCESS; + } else { /* To be extended */ + WD_ERR("queue alg err!\n"); + } + + return ret; +} + +static int qm_set_db_info(struct q_info *qinfo) +{ + struct qm_queue_info *info = qinfo->priv; + + if (strstr(qinfo->hw_type, HISI_QM_API_VER2_BASE) || + strstr(qinfo->hw_type, HISI_QM_API_VER3_BASE)) { + info->db = qm_db_v2; + info->doorbell_base = info->mmio_base + QM_V2_DOORBELL_OFFSET; + } else if (strstr(qinfo->hw_type, HISI_QM_API_VER_BASE)) { + info->db = qm_db_v1; + info->doorbell_base = info->mmio_base + QM_DOORBELL_OFFSET; + } else { + WD_ERR("hw version mismatch!\n"); + return -EINVAL; + } + + return 0; +} + +static int qm_init_queue_info(struct wd_queue *q) +{ + struct wcrypto_paras *priv = &q->capa.priv; + struct q_info *qinfo = q->qinfo; + struct qm_queue_info *info = qinfo->priv; + struct hisi_qp_info qp_info; + struct hisi_qp_ctx qp_ctx; + int ret; + + info->sq_tail_index = 0; + info->cq_head_index = 0; + info->cqc_phase = 1; + info->used = 0; + info->is_poll = priv->is_poll; + qp_ctx.qc_type = priv->direction; + qp_ctx.id = 0; + ret = ioctl(qinfo->fd, WD_UACCE_CMD_QM_SET_QP_CTX, &qp_ctx); + if (ret < 0) { + WD_ERR("failed to set qp type!\n"); + return ret; + } + info->sqn = qp_ctx.id; + + ret = ioctl(qinfo->fd, WD_UACCE_CMD_QM_SET_QP_INFO, &qp_info); + if (ret < 0) { + WD_ERR("getting qp information is not supported, use default value!\n"); + + /* The default value of sqe_size has been set in qm_set_queue_alg_info. */ + info->sq_depth = QM_Q_DEPTH; + info->cq_depth = QM_Q_DEPTH; + } else { + info->sq_depth = qp_info.sq_depth; + info->cq_depth = qp_info.cq_depth; + info->sqe_size = qp_info.sqe_size; + } + + return 0; +} + +static int qm_set_queue_info(struct wd_queue *q) +{ + struct q_info *qinfo = q->qinfo; + struct qm_queue_info *info = qinfo->priv; + size_t psize; + int ret; + + ret = qm_init_queue_info(q); + if (ret) + return ret; + + ret = qm_set_queue_regions(q); + if (ret) + return -EINVAL; + if (!info->sqe_size) { + WD_ERR("sqe size =%d err!\n", info->sqe_size); + ret = -EINVAL; + goto err_with_regions; + } + info->cq_base = (void *)((uintptr_t)info->sq_base + + info->sqe_size * info->sq_depth); + + /* Protect the virtual address of CQ to avoid being over written */ + psize = qinfo->qfrs_offset[WD_UACCE_QFRT_DUS] - + info->sqe_size * info->sq_depth; + ret = mprotect(info->cq_base, psize, PROT_READ); + if (ret) { + WD_ERR("cqe mprotect set err!\n"); + ret = -EINVAL; + goto err_with_regions; + } + + /* The last 32 bits of DUS show device or qp statuses */ + info->ds_tx_base = info->sq_base + qinfo->qfrs_offset[WD_UACCE_QFRT_DUS] - + sizeof(uint32_t); + info->ds_rx_base = info->ds_tx_base - sizeof(uint32_t); + ret = qm_set_db_info(qinfo); + if (ret) + goto err_with_regions; + + info->req_cache = calloc(info->sq_depth, sizeof(void *)); + if (!info->req_cache) { + ret = -WD_ENOMEM; + goto err_with_regions; + } + + return 0; + +err_with_regions: + qm_unset_queue_regions(q); + return ret; +} + +int qm_init_queue(struct wd_queue *q) +{ + struct q_info *qinfo = q->qinfo; + struct qm_queue_info *info; + int ret = -ENOMEM; + + info = calloc(1, sizeof(*info)); + if (!info) { + WD_ERR("no mem!\n"); + return ret; + } + info->q = q; + qinfo->priv = info; + ret = qm_set_queue_alg_info(q); + if (ret < 0) + goto err_with_priv; + ret = qm_set_queue_info(q); + if (ret < 0) + goto err_with_priv; + info->sqe_fill_priv = NULL; + info->sqe_parse_priv = NULL; + + return 0; + +err_with_priv: + free(qinfo->priv); + qinfo->priv = NULL; + return ret; +} + +void qm_uninit_queue(struct wd_queue *q) +{ + struct q_info *qinfo = q->qinfo; + struct qm_queue_info *info = qinfo->priv; + + qm_unset_queue_regions(q); + free(info->req_cache); + free(qinfo->priv); + qinfo->priv = NULL; +} + +void qm_tx_update(struct qm_queue_info *info, __u32 num) +{ + info->db(info, DOORBELL_CMD_SQ, info->sq_tail_index, 0); + __atomic_add_fetch(&info->used, num, __ATOMIC_RELAXED); +} + +int qm_send(struct wd_queue *q, void **req, __u32 num) +{ + struct q_info *qinfo = q->qinfo; + struct qm_queue_info *info = qinfo->priv; + int i, ret; + + if (unlikely(wd_reg_read(info->ds_tx_base) == 1)) { + WD_ERR("wd queue hw error happened before qm send!\n"); + return -WD_HW_EACCESS; + } + + wd_spinlock(&info->sd_lock); + if (unlikely(__atomic_load_n(&info->used, __ATOMIC_RELAXED) > + info->sq_depth - num - 1)) { + wd_unspinlock(&info->sd_lock); + WD_ERR("queue is full!\n"); + return -WD_EBUSY; + } + + for (i = 0; i < num; i++) { + ret = info->sqe_fill[qinfo->atype](req[i], qinfo->priv, + info->sq_tail_index); + if (unlikely(ret != WD_SUCCESS)) { + wd_unspinlock(&info->sd_lock); + WD_ERR("sqe fill error, ret %d!\n", ret); + return -WD_EINVAL; + } + + if (info->sq_tail_index == info->sq_depth - 1) + info->sq_tail_index = 0; + else + info->sq_tail_index++; + } + + /* make sure the request is all in memory before doorbell */ + mb(); + qm_tx_update(info, num); + wd_unspinlock(&info->sd_lock); + + return WD_SUCCESS; +} + +void qm_rx_update(struct qm_queue_info *info, __u32 num) +{ + /* set c_flag to enable interrupt when use poll */ + info->db(info, DOORBELL_CMD_CQ, info->cq_head_index, info->is_poll); + __atomic_sub_fetch(&info->used, num, __ATOMIC_RELAXED); +} + +void qm_rx_from_cache(struct qm_queue_info *info, void **resp, __u32 num) +{ + __u16 idx = info->cq_head_index; + int i; + + for (i = 0; i < num; i++) { + resp[i] = info->req_cache[idx]; + info->req_cache[idx] = NULL; + + if (idx == info->cq_depth - 1) { + info->cqc_phase = !(info->cqc_phase); + idx = 0; + } else { + idx++; + } + } + + info->cq_head_index = idx; + __atomic_sub_fetch(&info->used, num, __ATOMIC_RELAXED); +} + +static int check_ds_rx_base(struct qm_queue_info *info, + void **resp, __u32 num, __u8 before) +{ + if (wd_reg_read(info->ds_rx_base) != 1) + return 0; + + if (before) { + wd_spinlock(&info->rc_lock); + qm_rx_from_cache(info, resp, num); + wd_unspinlock(&info->rc_lock); + WD_ERR("wd queue hw error happened before qm receive!\n"); + } else { + WD_ERR("wd queue hw error happened after qm receive!\n"); + } + + return -WD_HW_EACCESS; +} + +int qm_recv(struct wd_queue *q, void **resp, __u32 num) +{ + struct q_info *qinfo = q->qinfo; + struct qm_queue_info *info = qinfo->priv; + struct cqe *cqe; + __u16 sq_head; + int i, ret; + void *sqe; + + ret = check_ds_rx_base(info, resp, num, 1); + if (unlikely(ret)) + return ret; + + wd_spinlock(&info->rc_lock); + for (i = 0; i < num; i++) { + cqe = info->cq_base + info->cq_head_index * sizeof(struct cqe); + if (info->cqc_phase != CQE_PHASE(cqe)) + break; + + mb(); /* make sure the data is all in memory before read */ + sq_head = CQE_SQ_HEAD_INDEX(cqe); + if (unlikely(sq_head >= info->sq_depth)) { + wd_unspinlock(&info->rc_lock); + WD_ERR("CQE_SQ_HEAD_INDEX(%u) error\n", sq_head); + return -WD_EIO; + } + + sqe = (void *)((uintptr_t)info->sq_base + sq_head * info->sqe_size); + ret = info->sqe_parse[qinfo->atype](sqe, + (const struct qm_queue_info *)info, + info->cq_head_index, (__u16)(uintptr_t)resp[i]); + if (!ret) { + break; + } else if (ret < 0) { + wd_unspinlock(&info->rc_lock); + WD_ERR("recv sqe error %u\n", sq_head); + return ret; + } + + resp[i] = info->req_cache[info->cq_head_index]; + info->req_cache[info->cq_head_index] = NULL; + if (info->cq_head_index == info->cq_depth - 1) { + info->cqc_phase = !(info->cqc_phase); + info->cq_head_index = 0; + } else { + info->cq_head_index++; + } + } + + if (i) + qm_rx_update(info, i); + + wd_unspinlock(&info->rc_lock); + ret = check_ds_rx_base(info, resp, num, 0); + if (unlikely(ret)) + return ret; + + return i; +} + +static int hw_type_check(struct wd_queue *q, const char *hw_type) +{ + const char *drv = wd_get_drv(q); + + if (!hw_type || !drv) + return 1; + + return strcmp(drv, hw_type); +} + +int hisi_qm_inject_op_register(struct wd_queue *q, struct hisi_qm_inject_op *op) +{ + struct q_info *qinfo = q->qinfo; + struct qm_queue_info *info = qinfo->priv; + + if (!op || !op->sqe_fill_priv || !op->sqe_parse_priv) { + WD_ERR("inject option is invalid!\n"); + return -WD_EINVAL; + } + + if (hw_type_check(q, op->hw_type)) { + WD_ERR("inject option hw compare error!\n"); + return -WD_EINVAL; + } + + info->sqe_fill_priv = op->sqe_fill_priv; + info->sqe_parse_priv = op->sqe_parse_priv; + + return 0; +} + +int qm_get_hwsgl_info(struct wd_queue *q, struct hw_sgl_info *sgl_info) +{ + struct q_info *qinfo = q->qinfo; + struct qm_queue_info *info = qinfo->priv; + + if (!info->sgl_info) + return -WD_EINVAL; + + return info->sgl_info(sgl_info); +} + +int qm_init_hwsgl_mem(struct wd_queue *q, void *pool, struct wd_sgl *sgl) +{ + struct q_info *qinfo = q->qinfo; + struct qm_queue_info *info = qinfo->priv; + + if (!info->sgl_init) + return -WD_EINVAL; + + return info->sgl_init(pool, sgl); +} + +int qm_uninit_hwsgl_mem(struct wd_queue *q, void *pool, struct wd_sgl *sgl) +{ + struct q_info *qinfo = q->qinfo; + struct qm_queue_info *info = qinfo->priv; + + if (!info->sgl_uninit) + return -WD_EINVAL; + + info->sgl_uninit(pool, sgl); + + return WD_SUCCESS; +} + +int qm_merge_hwsgl(struct wd_queue *q, void *pool, + struct wd_sgl *dst_sgl, struct wd_sgl *src_sgl) +{ + struct q_info *qinfo = q->qinfo; + struct qm_queue_info *info = qinfo->priv; + + if (!info->sgl_merge) + return -WD_EINVAL; + + return info->sgl_merge(pool, dst_sgl, src_sgl); +} diff --git a/uadk/v1/drv/hisi_qm_udrv.h b/uadk/v1/drv/hisi_qm_udrv.h new file mode 100644 index 0000000..cc1aa33 --- /dev/null +++ b/uadk/v1/drv/hisi_qm_udrv.h @@ -0,0 +1,206 @@ +/* + * Copyright 2018-2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#ifndef __HISI_QM_DRV_H__ +#define __HISI_QM_DRV_H__ + +#include +#include +#include "config.h" +#include "v1/wd.h" +#include "v1/wd_ecc.h" +#include "v1/wd_rsa.h" +#include "v1/wd_util.h" +#include "v1/wd_dh.h" +#include "v1/wd_sgl.h" + +/* default queue depth for sq/cq/eq */ +#define QM_Q_DEPTH 1024 + +#define QM_CQE_SIZE 16 + +/* page number for queue file region */ +#define QM_DOORBELL_PAGE_NR 1 +#define QM_DKO_PAGE_NR 4 +#define QM_DUS_PAGE_NR 36 + +#define QM_DOORBELL_PG_START 0 +#define QM_DKO_PAGE_START (QM_DOORBELL_PG_START + QM_DOORBELL_PAGE_NR) +#define QM_DUS_PAGE_START (QM_DKO_PAGE_START + QM_DKO_PAGE_NR) +#define QM_SS_PAGE_START (QM_DUS_PAGE_START + QM_DUS_PAGE_NR) + +#define QM_DOORBELL_OFFSET 0x340 +#define QM_V2_DOORBELL_OFFSET 0x1000 + +#define QM_CQE_SIZE 16 +#define QM_HPRE_BD_SIZE 64 +#define QM_ZIP_BD_SIZE 128 +#define QM_SEC_BD_SIZE 128 +#define QM_RDE_BD_SIZE 64 +#define DOORBELL_CMD_SQ 0 +#define DOORBELL_CMD_CQ 1 +#define HPRE_NO_HW_ERR 0 +#define HPRE_HW_TASK_DONE 3 +#define HPRE_HW_TASK_INIT 1 +#define QM_DBELL_CMD_SHIFT 16 +#define QM_V2_DBELL_CMD_SHIFT 12 +#define QM_DBELL_PRI_SHIFT 16 +#define QM_DBELL_HLF_SHIFT 32 +#define QM_DBELL_SQN_MASK 0x3ff +#define QM_DBELL_CMD_MASK 0xf +#define QM_L32BITS_MASK 0xffffffff +#define QM_L16BITS_MASK 0xffff +#define QM_HADDR_SHIFT 32 +#define HI_U32(pa) ((__u32)(((pa) >> QM_HADDR_SHIFT) & QM_L32BITS_MASK)) +#define DMA_ADDR(hi, lo) ((__u64)(((__u64)(hi) << 32) | (__u64)(lo))) +#define LOW_U16(val) (__u16)((val) & QM_L16BITS_MASK) + + +/* cqe shift */ +#define CQE_PHASE(cq) (__le16_to_cpu((cq)->w7) & 0x1) +#define CQE_SQ_NUM(cq) __le16_to_cpu((cq)->sq_num) +#define CQE_SQ_HEAD_INDEX(cq) (__le16_to_cpu((cq)->sq_head) & 0xffff) + +/* wd sgl len */ +#define WD_SGL_PAD0_LEN 2 +#define WD_SGL_PAD1_LEN 8 +#define WD_SGL_RESERVERD_LEN 24 + +enum hisi_buff_type { + HISI_FLAT_BUF, + HISI_SGL_BUF, +}; + +/* in little-endian */ +struct hisi_sge { + uintptr_t buf; + void *page_ctrl; + __le32 len; + __le32 pad; + __le32 pad0; + __le32 pad1; +}; + +/* use default sgl head size 64B, in little-endian */ +struct hisi_sgl { + /* next sgl point, to make up chain, 64bit */ + uintptr_t next_dma; + /* sum of sge in all sgl chain */ + __le16 entry_sum_in_chain; + /* valid sge num in this sgl */ + __le16 entry_sum_in_sgl; + /* sge num in this sgl */ + __le16 entry_length_in_sgl; + __le16 pad0; + __le64 pad1[6]; + + struct hisi_sge sge_entries[]; +}; + +struct cqe { + __le32 rsvd0; + __le16 cmd_id; + __le16 rsvd1; + __le16 sq_head; + __le16 sq_num; + __le16 rsvd2; + __le16 w7; +}; + +struct hisi_qp_ctx { + __u16 id; + __u16 qc_type; +}; + +struct hisi_qp_info { + __u32 sqe_size; + __u16 sq_depth; + __u16 cq_depth; + __u64 reserved; +}; + +struct qm_queue_info; + +typedef int (*qm_sqe_fill)(void *msg, + struct qm_queue_info *info, __u16 i); +typedef int (*qm_sqe_parse)(void *hw_msg, + const struct qm_queue_info *info, __u16 i, __u16 usr); +typedef int (*hisi_qm_sqe_fill_priv)( + void *hw_msg, enum wcrypto_type atype, void *opdata); +typedef int (*hisi_qm_sqe_parse_priv)( + void *hw_msg, enum wcrypto_type atype, void *opdata); + +struct qm_queue_info { + void *sq_base; + void *cq_base; + void *mmio_base; + void *doorbell_base; + int (*db)(struct qm_queue_info *q, __u8 cmd, + __u16 index, __u8 priority); + void *ds_tx_base; + void *ds_rx_base; + __u16 sq_tail_index; + __u16 cq_head_index; + __u16 sq_depth; + __u16 cq_depth; + __u16 sqn; + __u16 resv; + bool is_poll; + int cqc_phase; + int used; + int sqe_size; + void **req_cache; + qm_sqe_fill sqe_fill[WCRYPTO_MAX_ALG]; + qm_sqe_parse sqe_parse[WCRYPTO_MAX_ALG]; + hisi_qm_sqe_fill_priv sqe_fill_priv; + hisi_qm_sqe_parse_priv sqe_parse_priv; + struct wd_lock sd_lock; + struct wd_lock rc_lock; + struct wd_queue *q; + int (*sgl_info)(struct hw_sgl_info *info); + int (*sgl_init)(void *pool, struct wd_sgl *sgl); + void (*sgl_uninit)(void *pool, struct wd_sgl *sgl); + int (*sgl_merge)(void *pool, struct wd_sgl *dst_sgl, struct wd_sgl *src_sgl); +}; + +struct hisi_qm_inject_op { + const char *hw_type; + hisi_qm_sqe_fill_priv sqe_fill_priv; + hisi_qm_sqe_parse_priv sqe_parse_priv; +}; + +int qm_init_queue(struct wd_queue *q); +void qm_uninit_queue(struct wd_queue *q); +int qm_send(struct wd_queue *q, void **req, __u32 num); +int qm_recv(struct wd_queue *q, void **resp, __u32 num); +int hisi_qm_inject_op_register(struct wd_queue *q, struct hisi_qm_inject_op *op); +int qm_get_hwsgl_info(struct wd_queue *q, struct hw_sgl_info *sgl_info); +int qm_init_hwsgl_mem(struct wd_queue *q, void *pool, struct wd_sgl *sgl); +int qm_uninit_hwsgl_mem(struct wd_queue *q, void *pool, struct wd_sgl *sgl); +int qm_merge_hwsgl(struct wd_queue *q, void *pool, + struct wd_sgl *dst_sgl, struct wd_sgl *src_sgl); +void qm_tx_update(struct qm_queue_info *info, __u32 num); +void qm_rx_update(struct qm_queue_info *info, __u32 num); +void qm_rx_from_cache(struct qm_queue_info *info, void **resp, __u32 num); + +#define HISI_QM_API_VER_BASE "hisi_qm_v1" +#define HISI_QM_API_VER2_BASE "hisi_qm_v2" +#define HISI_QM_API_VER3_BASE "hisi_qm_v3" + +#define WD_UACCE_CMD_QM_SET_QP_CTX _IOWR('H', 10, struct hisi_qp_ctx) +#define WD_UACCE_CMD_QM_SET_QP_INFO _IOWR('H', 11, struct hisi_qp_info) + +#endif diff --git a/uadk/v1/drv/hisi_rng_udrv.c b/uadk/v1/drv/hisi_rng_udrv.c new file mode 100644 index 0000000..b86a948 --- /dev/null +++ b/uadk/v1/drv/hisi_rng_udrv.c @@ -0,0 +1,162 @@ +/* + * Copyright 2018-2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "hisi_rng_udrv.h" + +#define HISI_RNG_BYTES 4 +#define MAX_RETRY_COUNTS 8 +#define RNG_NUM_OFFSET 0x00F0 + +int rng_init_queue(struct wd_queue *q) +{ + struct q_info *qinfo = q->qinfo; + struct rng_queue_info *info; + + info = calloc(1, sizeof(*info)); + if (!info) { + WD_ERR("no mem!\n"); + return -ENOMEM; + } + + qinfo->priv = info; + info->mmio_base = wd_drv_mmap_qfr(q, WD_UACCE_QFRT_MMIO, 0); + if (info->mmio_base == MAP_FAILED) { + info->mmio_base = NULL; + free(qinfo->priv); + qinfo->priv = NULL; + WD_ERR("mmap trng mmio fail\n"); + return -ENOMEM; + } + + return 0; +} + +void rng_uninit_queue(struct wd_queue *q) +{ + struct q_info *qinfo = q->qinfo; + struct rng_queue_info *info = qinfo->priv; + + wd_drv_unmmap_qfr(q, info->mmio_base, WD_UACCE_QFRT_MMIO, 0); + + free(qinfo->priv); + qinfo->priv = NULL; +} + +int rng_send(struct wd_queue *q, void **req, __u32 num) +{ + struct q_info *qinfo = q->qinfo; + struct rng_queue_info *info = qinfo->priv; + + wd_spinlock(&info->lock); + if (!info->req_cache[info->send_idx]) { + info->req_cache[info->send_idx] = req[0]; + info->send_idx++; + wd_unspinlock(&info->lock); + return 0; + } + wd_unspinlock(&info->lock); + + WD_ERR("queue is full!\n"); + return -WD_EBUSY; +} + +static int rng_read(struct rng_queue_info *info, struct wcrypto_rng_msg *msg) +{ + __u32 max = msg->in_bytes; + __u32 currsize = 0; + int recv_count = 0; + int val; + + do { + val = wd_reg_read((void *)((uintptr_t)info->mmio_base + + RNG_NUM_OFFSET)); + if (!val) { + if (++recv_count > MAX_RETRY_COUNTS) { + WD_ERR("read random data timeout\n"); + break; + } + + usleep(1); + continue; + } + + recv_count = 0; + if (max - currsize >= HISI_RNG_BYTES) { + memcpy(msg->out + currsize, &val, HISI_RNG_BYTES); + currsize += HISI_RNG_BYTES; + if (currsize == max) + break; + continue; + } + + memcpy(msg->out + currsize, &val, max - currsize); + currsize = max; + } while (currsize < max); + + return currsize; +} + +int rng_recv(struct wd_queue *q, void **resp, __u32 num) +{ + struct q_info *qinfo = q->qinfo; + struct rng_queue_info *info = qinfo->priv; + __u16 usr = (__u16)(uintptr_t)*resp; + struct wcrypto_rng_msg *msg; + struct wcrypto_cb_tag *tag; + __u32 currsize = 0; + + wd_spinlock(&info->lock); + msg = info->req_cache[info->recv_idx]; + if (!msg) { + wd_unspinlock(&info->lock); + return 0; + } + + info->req_cache[info->recv_idx] = NULL; + info->recv_idx++; + wd_unspinlock(&info->lock); + + tag = (void *)(uintptr_t)msg->usr_tag; + if (usr && tag->ctx_id != usr) + return 0; + + currsize = rng_read(info, msg); + if (!currsize) { + WD_ERR("random data err!\n"); + return -WD_EINVAL; + } + + msg->out_bytes = currsize; + *resp = msg; + + return 1; +} diff --git a/uadk/v1/drv/hisi_rng_udrv.h b/uadk/v1/drv/hisi_rng_udrv.h new file mode 100644 index 0000000..93f2f91 --- /dev/null +++ b/uadk/v1/drv/hisi_rng_udrv.h @@ -0,0 +1,41 @@ +/* + * Copyright 2018-2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#ifndef __HISI_RNG_UDRV_H__ +#define __HISI_RNG_UDRV_H__ + +#include +#include "config.h" +#include "v1/wd.h" +#include "v1/wd_util.h" +#include "v1/wd_rng.h" + +#define TRNG_Q_DEPTH 256 + +struct rng_queue_info { + void *mmio_base; + void *req_cache[TRNG_Q_DEPTH]; + __u8 send_idx; + __u8 recv_idx; + struct wd_lock lock; +}; + +int rng_init_queue(struct wd_queue *q); +void rng_uninit_queue(struct wd_queue *q); +int rng_send(struct wd_queue *q, void **req, __u32 num); +int rng_recv(struct wd_queue *q, void **resp, __u32 num); + +#endif diff --git a/uadk/v1/drv/hisi_sec_udrv.c b/uadk/v1/drv/hisi_sec_udrv.c new file mode 100644 index 0000000..4d5ede5 --- /dev/null +++ b/uadk/v1/drv/hisi_sec_udrv.c @@ -0,0 +1,2735 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "hisi_sec_udrv.h" + +#define DES_KEY_SIZE 8 +#define SEC_3DES_2KEY_SIZE (2 * DES_KEY_SIZE) +#define SEC_3DES_3KEY_SIZE (3 * DES_KEY_SIZE) + +#define SEC_HW_TASK_DONE 1 +#define SEC_HW_ICV_ERR 0x2 +#define SQE_BYTES_NUMS 128 +#define CTR_MODE_LEN_SHIFT 4 +#define WORD_BYTES 4 +#define WORD_ALIGNMENT_MASK 0x3 +#define U64_DATA_BYTES 8 +#define U64_DATA_SHIFT 3 +#define CTR_128BIT_COUNTER 16 +#define CTR_128BIT_FLIP 0x2 +#define DIF_VERIFY_FAIL 2 +#define AES_BLOCK_SIZE 16 +#define WCRYPTO_CIPHER_THEN_DIGEST 0 +#define WCRYPTO_DIGEST_THEN_CIPHER 1 +#define CBC_3DES_BLOCK_SIZE 8 +#define CBC_AES_BLOCK_SIZE 16 +#define AEAD_IV_MAX_BYTES 64 +#define MAX_CCM_AAD_LEN 65279 + +static int g_digest_a_alg[WCRYPTO_MAX_DIGEST_TYPE] = { + A_ALG_SM3, A_ALG_MD5, A_ALG_SHA1, A_ALG_SHA256, A_ALG_SHA224, + A_ALG_SHA384, A_ALG_SHA512, A_ALG_SHA512_224, A_ALG_SHA512_256 +}; +static int g_hmac_a_alg[WCRYPTO_MAX_DIGEST_TYPE] = { + A_ALG_HMAC_SM3, A_ALG_HMAC_MD5, A_ALG_HMAC_SHA1, + A_ALG_HMAC_SHA256, A_ALG_HMAC_SHA224, A_ALG_HMAC_SHA384, + A_ALG_HMAC_SHA512, A_ALG_HMAC_SHA512_224, A_ALG_HMAC_SHA512_256 +}; + +#ifdef DEBUG_LOG +static void sec_dump_bd(unsigned char *bd, unsigned int len) +{ + unsigned int i; + + for (i = 0; i < len; i++) { + WD_ERR("\\%02x", bd[i]); + if ((i + 1) % WORD_BYTES == 0) + WD_ERR("\n"); + } + WD_ERR("\n"); +} +#endif + +static int get_aes_c_key_len(__u8 mode, __u16 key_bytes, __u8 *c_key_len) +{ + __u16 len; + + len = key_bytes; + if (mode == WCRYPTO_CIPHER_XTS) + len >>= XTS_MODE_KEY_SHIFT; + + if (len == AES_KEYSIZE_128) + *c_key_len = CKEY_LEN_128_BIT; + else if (len == AES_KEYSIZE_192) + *c_key_len = CKEY_LEN_192_BIT; + else if (len == AES_KEYSIZE_256) + *c_key_len = CKEY_LEN_256_BIT; + else { + WD_ERR("Invalid AES key size!\n"); + return -WD_EINVAL; + } + + return WD_SUCCESS; +} + +static int get_3des_c_key_len(struct wcrypto_cipher_msg *msg, __u8 *c_key_len) +{ + if (msg->key_bytes == SEC_3DES_2KEY_SIZE) + *c_key_len = CKEY_LEN_3DES_2KEY; + else if (msg->key_bytes == SEC_3DES_3KEY_SIZE) + *c_key_len = CKEY_LEN_3DES_3KEY; + else { + WD_ERR("Invalid 3DES key size!\n"); + return -WD_EINVAL; + } + + return WD_SUCCESS; +} + +static int fill_cipher_bd2_alg(struct wcrypto_cipher_msg *msg, + struct hisi_sec_sqe *sqe) +{ + int ret = WD_SUCCESS; + __u8 c_key_len = 0; + + switch (msg->alg) { + case WCRYPTO_CIPHER_SM4: + sqe->type2.c_alg = C_ALG_SM4; + sqe->type2.c_key_len = CKEY_LEN_SM4; + break; + case WCRYPTO_CIPHER_AES: + sqe->type2.c_alg = C_ALG_AES; + ret = get_aes_c_key_len(msg->mode, msg->key_bytes, &c_key_len); + sqe->type2.c_key_len = c_key_len; + break; + case WCRYPTO_CIPHER_DES: + sqe->type2.c_alg = C_ALG_DES; + sqe->type2.c_key_len = CKEY_LEN_DES; + break; + case WCRYPTO_CIPHER_3DES: + sqe->type2.c_alg = C_ALG_3DES; + ret = get_3des_c_key_len(msg, &c_key_len); + sqe->type2.c_key_len = c_key_len; + break; + default: + WD_ERR("Invalid cipher type!\n"); + ret = -WD_EINVAL; + break; + } + + return ret; +} + +static int fill_cipher_bd2_mode(struct wcrypto_cipher_msg *msg, + struct hisi_sec_sqe *sqe) +{ + int ret = WD_SUCCESS; + + if (msg->op_type == WCRYPTO_CIPHER_ENCRYPTION + || msg->mode == WCRYPTO_CIPHER_OFB) + sqe->cipher = CIPHER_ENCRYPT; + else if (msg->op_type == WCRYPTO_CIPHER_DECRYPTION) { + sqe->cipher = CIPHER_DECRYPT; + } else { + WD_ERR("Invalid cipher op type!\n"); + return -WD_EINVAL; + } + + switch (msg->mode) { + case WCRYPTO_CIPHER_ECB: + sqe->type2.c_mode = C_MODE_ECB; + break; + case WCRYPTO_CIPHER_CBC: + case WCRYPTO_CIPHER_OFB: + sqe->type2.c_mode = C_MODE_CBC; + break; + case WCRYPTO_CIPHER_XTS: + sqe->type2.c_mode = C_MODE_XTS; + break; + default: + WD_ERR("Invalid cipher alg type!\n"); + ret = -WD_EINVAL; + break; + } + + return ret; +} + +static void fill_bd_addr_type(__u8 data_fmt, struct hisi_sec_sqe *sqe) +{ + if (data_fmt == WD_SGL_BUF) { + sqe->src_addr_type = HISI_SGL_BUF; + sqe->dst_addr_type = HISI_SGL_BUF; + } else { + sqe->src_addr_type = HISI_FLAT_BUF; + sqe->dst_addr_type = HISI_FLAT_BUF; + } +} + +static void fill_bd3_addr_type(__u8 data_fmt, struct hisi_sec_bd3_sqe *sqe3) +{ + if (data_fmt == WD_SGL_BUF) { + sqe3->src_addr_type = HISI_SGL_BUF; + sqe3->dst_addr_type = HISI_SGL_BUF; + } else { + sqe3->src_addr_type = HISI_FLAT_BUF; + sqe3->dst_addr_type = HISI_FLAT_BUF; + } +} + +/* increment counter (128-bit int) by c */ +static void ctr_iv_inc(__u8 *counter, __u32 shift_len, __u8 data_fmt) +{ + __u32 n = CTR_128BIT_COUNTER; + __u8 *counter1 = counter; + __u32 c = shift_len; + + if (data_fmt == WD_SGL_BUF) { + counter1 = wd_get_first_sge_buf((struct wd_sgl *)counter); + if (unlikely(!counter1)) + return; + } + + do { + --n; + c += counter1[n]; + counter1[n] = (__u8)c; + c >>= BYTE_BITS; + } while (n); +} + +static void update_iv_from_res(__u8 *dst, __u8 *src, size_t offset, __u16 bytes, + __u8 data_fmt) +{ + __u8 *dst1; + int ret; + + if (data_fmt == WD_SGL_BUF) { + dst1 = wd_get_first_sge_buf((struct wd_sgl *)dst); + if (unlikely(!dst1)) + return; + ret = wd_sgl_cp_to_pbuf((struct wd_sgl *)src, offset, dst1, bytes); + if (unlikely(ret)) + return; + } else { + memcpy(dst, src + offset, bytes); + } +} + +static void update_iv(struct wcrypto_cipher_msg *msg) +{ + switch (msg->mode) { + case WCRYPTO_CIPHER_CBC: + if (msg->op_type == WCRYPTO_CIPHER_ENCRYPTION && + msg->out_bytes >= msg->iv_bytes) + update_iv_from_res(msg->iv, msg->out, + msg->out_bytes - msg->iv_bytes, + msg->iv_bytes, msg->data_fmt); + if (msg->op_type == WCRYPTO_CIPHER_DECRYPTION && + msg->in_bytes >= msg->iv_bytes) + update_iv_from_res(msg->iv, msg->in, + msg->in_bytes - msg->iv_bytes, + msg->iv_bytes, msg->data_fmt); + break; + case WCRYPTO_CIPHER_OFB: + case WCRYPTO_CIPHER_CFB: + if (msg->out_bytes >= msg->iv_bytes) + update_iv_from_res(msg->iv, msg->out, + msg->out_bytes - msg->iv_bytes, + msg->iv_bytes, msg->data_fmt); + break; + case WCRYPTO_CIPHER_CTR: + ctr_iv_inc(msg->iv, msg->in_bytes >> CTR_MODE_LEN_SHIFT, + msg->data_fmt); + break; + default: + break; + } +} + +static int fill_cipher_bd1_type(struct wcrypto_cipher_msg *msg, + struct hisi_sec_sqe *sqe) +{ + if (msg->op_type == WCRYPTO_CIPHER_ENCRYPTION + || msg->mode == WCRYPTO_CIPHER_OFB) + sqe->cipher = CIPHER_ENCRYPT; + else if (msg->op_type == WCRYPTO_CIPHER_DECRYPTION) { + sqe->cipher = CIPHER_DECRYPT; + } else { + WD_ERR("Invalid cipher op type for bd1!\n"); + return -WD_EINVAL; + } + + if (msg->data_fmt > WD_SGL_BUF) { + WD_ERR("Invalid data format for bd1!\n"); + return -WD_EINVAL; + } + + fill_bd_addr_type(msg->data_fmt, sqe); + + /* + * BD1 cipher only provides ci_gen=0 for compatibility, so user + * should prepare iv[gran_num] and iv_bytes is sum of all grans + */ + sqe->type1.ci_gen = CI_GEN_BY_ADDR; + + return WD_SUCCESS; +} + +static int fill_cipher_bd1_alg(struct wcrypto_cipher_msg *msg, + struct hisi_sec_sqe *sqe) +{ + int ret = WD_SUCCESS; + __u8 c_key_len = 0; + + switch (msg->alg) { + case WCRYPTO_CIPHER_SM4: + sqe->type1.c_alg = C_ALG_SM4; + sqe->type1.c_key_len = CKEY_LEN_SM4; + break; + case WCRYPTO_CIPHER_AES: + sqe->type1.c_alg = C_ALG_AES; + ret = get_aes_c_key_len(msg->mode, msg->key_bytes, &c_key_len); + sqe->type2.c_key_len = c_key_len; + break; + case WCRYPTO_CIPHER_DES: + sqe->type1.c_alg = C_ALG_DES; + sqe->type1.c_key_len = CKEY_LEN_DES; + break; + case WCRYPTO_CIPHER_3DES: + sqe->type1.c_alg = C_ALG_3DES; + ret = get_3des_c_key_len(msg, &c_key_len); + sqe->type2.c_key_len = c_key_len; + break; + default: + WD_ERR("Invalid cipher type for bd1\n"); + ret = -WD_EINVAL; + break; + } + + return ret; +} + +static int fill_cipher_bd1_mode(struct wcrypto_cipher_msg *msg, + struct hisi_sec_sqe *sqe) +{ + switch (msg->mode) { + case WCRYPTO_CIPHER_ECB: + sqe->type1.c_mode = C_MODE_ECB; + break; + case WCRYPTO_CIPHER_CBC: + case WCRYPTO_CIPHER_OFB: + sqe->type1.c_mode = C_MODE_CBC; + break; + case WCRYPTO_CIPHER_CTR: + sqe->type1.c_mode = C_MODE_CTR; + break; + case WCRYPTO_CIPHER_XTS: + sqe->type1.c_mode = C_MODE_XTS; + break; + default: + WD_ERR("Invalid cipher alg type for bd1\n"); + return -WD_EINVAL; + } + + return WD_SUCCESS; +} + +static void fill_cipher_bd1_udata(struct hisi_sec_sqe *sqe, + struct wd_sec_udata *udata) +{ + sqe->type1.gran_num = udata->gran_num; + sqe->type1.src_skip_data_len = udata->src_offset; + sqe->type1.dst_skip_data_len = udata->dst_offset; + sqe->type1.gen_ver_val = udata->dif.ver; + sqe->type1.gen_app_val = udata->dif.app; + sqe->type1.gen_page_pad_ctrl = udata->dif.ctrl.gen.page_layout_gen_type; + sqe->type1.gen_grd_ctrl = udata->dif.ctrl.gen.grd_gen_type; + sqe->type1.gen_ver_ctrl = udata->dif.ctrl.gen.ver_gen_type; + sqe->type1.gen_app_ctrl = udata->dif.ctrl.gen.app_gen_type; + sqe->type1.gen_ref_ctrl = udata->dif.ctrl.gen.ref_gen_type; + sqe->type1.page_pad_type = udata->dif.ctrl.gen.page_layout_pad_type; + + sqe->type1.block_size = udata->block_size; + sqe->type1.private_info = udata->dif.priv_info; + sqe->type1.chk_grd_ctrl = udata->dif.ctrl.verify.grd_verify_type; + sqe->type1.chk_ref_ctrl = udata->dif.ctrl.verify.ref_verify_type; + sqe->type1.lba_l = udata->dif.lba & QM_L32BITS_MASK; + sqe->type1.lba_h = udata->dif.lba >> QM_HADDR_SHIFT; +} + +static int map_addr(struct wd_queue *q, __u8 *key, __u16 len, + __u32 *addr_l, __u32 *addr_h, __u8 data_fmt) +{ + uintptr_t phy; + void *p; + + /* 'msg->key' and 'msg->iv' use pBuffer, so when 'data_fmt' is sgl, + * we use its first buffer as pBuffer, and 'buf_sz > key_sz' is needed. + */ + if (data_fmt == WD_SGL_BUF) { + if (unlikely(!key)) + return -WD_ENOMEM; + p = drv_get_sgl_pri((struct wd_sgl *)key); + phy = ((struct hisi_sgl *)p)->sge_entries[0].buf; + } else { + phy = (uintptr_t)drv_iova_map(q, key, len); + } + if (unlikely(!phy)) { + WD_ERR("Get key dma address fail!\n"); + return -WD_ENOMEM; + } + + *addr_l = (__u32)(phy & QM_L32BITS_MASK); + *addr_h = HI_U32(phy); + + return WD_SUCCESS; +} + +static void unmap_addr(struct wd_queue *q, __u8 *key, __u16 len, + __u32 addr_l, __u32 addr_h, __u8 data_fmt) +{ + uintptr_t phy; + + if (data_fmt == WD_FLAT_BUF) { + phy = DMA_ADDR(addr_h, addr_l); + drv_iova_unmap(q, key, (void *)(uintptr_t)phy, len); + } +} + +static int fill_cipher_bd1_addr(struct wd_queue *q, + struct wcrypto_cipher_msg *msg, struct hisi_sec_sqe *sqe) +{ + uintptr_t phy; + int ret; + + ret = map_addr(q, msg->key, msg->key_bytes, &sqe->type1.c_key_addr_l, + &sqe->type1.c_key_addr_h, msg->data_fmt); + if (unlikely(ret)) { + WD_ERR("Get key dma address fail for bd1\n"); + return ret; + } + + /* for storage scene, data address using physical address */ + phy = (uintptr_t)msg->in; + sqe->type1.data_src_addr_l = phy & QM_L32BITS_MASK; + sqe->type1.data_src_addr_h = phy >> QM_HADDR_SHIFT; + phy = (uintptr_t)msg->out; + sqe->type1.data_dst_addr_l = phy & QM_L32BITS_MASK; + sqe->type1.data_dst_addr_h = phy >> QM_HADDR_SHIFT; + + if (msg->iv) { + ret = map_addr(q, msg->iv, msg->iv_bytes, + &sqe->type1.c_ivin_addr_l, + &sqe->type1.c_ivin_addr_h, + msg->data_fmt); + if (unlikely(ret)) { + WD_ERR("Get IV dma address fail for bd1\n"); + goto map_key_error; + } + } + + return WD_SUCCESS; + +map_key_error: + unmap_addr(q, msg->key, msg->key_bytes, sqe->type1.c_key_addr_l, + sqe->type1.c_key_addr_h, msg->data_fmt); + return -WD_ENOMEM; +} + +static int fill_cipher_bd1(struct wd_queue *q, struct hisi_sec_sqe *sqe, + struct wcrypto_cipher_msg *msg, struct wcrypto_cipher_tag *tag) +{ + int ret; + struct wd_sec_udata *udata = tag->priv; + + sqe->type = BD_TYPE1; + sqe->scene = SCENE_STORAGE; + sqe->de = DATA_DST_ADDR_ENABLE; + + ret = fill_cipher_bd1_type(msg, sqe); + if (ret != WD_SUCCESS) + return ret; + + ret = fill_cipher_bd1_alg(msg, sqe); + if (ret != WD_SUCCESS) + return ret; + + ret = fill_cipher_bd1_mode(msg, sqe); + if (ret != WD_SUCCESS) + return ret; + + fill_cipher_bd1_udata(sqe, udata); + + ret = fill_cipher_bd1_addr(q, msg, sqe); + if (ret != WD_SUCCESS) + return ret; + + sqe->type1.tag = tag->wcrypto_tag.ctx_id; + + return ret; +} + +static int get_cipher_data_phy(struct wcrypto_cipher_msg *msg, + struct wd_queue *q, + uintptr_t *phy) +{ + if (msg->mode != WCRYPTO_CIPHER_OFB) { + *phy = (uintptr_t)drv_iova_map(q, msg->in, msg->in_bytes); + if (unlikely(*phy == 0)) { + WD_ERR("Get message in dma address fail!\n"); + return -WD_ENOMEM; + } + + return 0; + } + + if (msg->in == msg->out) { + WD_ERR("Not support for src override for OFB\n"); + return -WD_EINVAL; + } + /* While using OFB mode of cipher, output buffer should be cleared */ + if (msg->data_fmt == WD_SGL_BUF) + wd_sgl_memset((struct wd_sgl *)msg->out, 0); + else + memset(msg->out, 0, msg->out_bytes); + + return 0; +} + +static int fill_cipher_bd2_addr(struct wd_queue *q, + struct wcrypto_cipher_msg *msg, struct hisi_sec_sqe *sqe) +{ + int ret; + uintptr_t phy; + + phy = (uintptr_t)drv_iova_map(q, msg->out, msg->out_bytes); + if (unlikely(!phy)) { + WD_ERR("Get cipher bd2 message out dma address fail!\n"); + return -WD_ENOMEM; + } + sqe->type2.data_dst_addr_l = (__u32)(phy & QM_L32BITS_MASK); + sqe->type2.data_dst_addr_h = HI_U32(phy); + + ret = get_cipher_data_phy(msg, q, &phy); + if (ret) + goto map_in_error; + + sqe->type2.data_src_addr_l = (__u32)(phy & QM_L32BITS_MASK); + sqe->type2.data_src_addr_h = HI_U32(phy); + + ret = map_addr(q, msg->key, msg->key_bytes, &sqe->type2.c_key_addr_l, + &sqe->type2.c_key_addr_h, msg->data_fmt); + if (unlikely(ret)) { + WD_ERR("Get key dma address fail!\n"); + goto map_key_error; + } + + if (msg->iv_bytes == 0) + return WD_SUCCESS; + ret = map_addr(q, msg->iv, msg->iv_bytes, &sqe->type2.c_ivin_addr_l, + &sqe->type2.c_ivin_addr_h, msg->data_fmt); + if (unlikely(ret)) { + WD_ERR("Get iv dma address fail!\n"); + goto map_iv_error; + } + + return WD_SUCCESS; + +map_iv_error: + unmap_addr(q, msg->key, msg->key_bytes, sqe->type2.c_key_addr_l, + sqe->type2.c_key_addr_h, msg->data_fmt); +map_key_error: + if (msg->mode != WCRYPTO_CIPHER_OFB) { + phy = DMA_ADDR(sqe->type2.data_src_addr_h, + sqe->type2.data_src_addr_l); + drv_iova_unmap(q, msg->in, (void *)(uintptr_t)phy, + msg->in_bytes); + } +map_in_error: + phy = DMA_ADDR(sqe->type2.data_dst_addr_h, + sqe->type2.data_dst_addr_l); + drv_iova_unmap(q, msg->out, (void *)(uintptr_t)phy, + msg->out_bytes); + return ret; +} + +static int cipher_param_check(struct wcrypto_cipher_msg *msg) +{ + if (unlikely(msg->in_bytes > MAX_CIPHER_LENGTH || + !msg->in_bytes)) { + WD_ERR("input cipher len is too large!\n"); + return -WD_EINVAL; + } + + if (msg->mode == WCRYPTO_CIPHER_OFB || + msg->mode == WCRYPTO_CIPHER_CFB || + msg->mode == WCRYPTO_CIPHER_CTR) + return WD_SUCCESS; + + if (msg->mode == WCRYPTO_CIPHER_XTS) { + if (unlikely(msg->in_bytes < CBC_AES_BLOCK_SIZE)) { + WD_ERR("input cipher length is too small!\n"); + return -WD_EINVAL; + } + return WD_SUCCESS; + } + + if (msg->alg == WCRYPTO_CIPHER_3DES || msg->alg == WCRYPTO_CIPHER_DES) { + if (unlikely(msg->in_bytes & (CBC_3DES_BLOCK_SIZE - 1))) { + WD_ERR("input 3DES or DES cipher parameter is error!\n"); + return -WD_EINVAL; + } + } + + if (msg->alg == WCRYPTO_CIPHER_AES || msg->alg == WCRYPTO_CIPHER_SM4) { + if (unlikely(msg->in_bytes & (CBC_AES_BLOCK_SIZE - 1))) { + WD_ERR("input AES or SM4 cipher parameter is error!\n"); + return -WD_EINVAL; + } + } + + return WD_SUCCESS; +} + +static int fill_cipher_bd2(struct wd_queue *q, struct hisi_sec_sqe *sqe, + struct wcrypto_cipher_msg *msg, struct wcrypto_cipher_tag *tag) +{ + int ret; + + ret = cipher_param_check(msg); + if (unlikely(ret)) + return ret; + + sqe->type = BD_TYPE2; + sqe->scene = SCENE_IPSEC; + + sqe->de = DATA_DST_ADDR_ENABLE; + + sqe->type2.c_len = msg->in_bytes; + + fill_bd_addr_type(msg->data_fmt, sqe); + + ret = fill_cipher_bd2_alg(msg, sqe); + if (ret != WD_SUCCESS) { + WD_ERR("fill_cipher_bd2_alg fail!\n"); + return ret; + } + + ret = fill_cipher_bd2_mode(msg, sqe); + if (ret != WD_SUCCESS) { + WD_ERR("fill_cipher_bd2_mode fail!\n"); + return ret; + } + + ret = fill_cipher_bd2_addr(q, msg, sqe); + if (ret != WD_SUCCESS) + return ret; + + if (tag) + sqe->type2.tag = tag->wcrypto_tag.ctx_id; + + return ret; +} + +static int fill_cipher_bd3_alg(struct wcrypto_cipher_msg *msg, + struct hisi_sec_bd3_sqe *sqe) +{ + int ret = WD_SUCCESS; + + ret = cipher_param_check(msg); + if (unlikely(ret)) + return ret; + + __u8 c_key_len = 0; + + switch (msg->alg) { + case WCRYPTO_CIPHER_SM4: + sqe->c_alg = C_ALG_SM4; + sqe->c_key_len = CKEY_LEN_SM4; + break; + case WCRYPTO_CIPHER_AES: + sqe->c_alg = C_ALG_AES; + ret = get_aes_c_key_len(msg->mode, msg->key_bytes, &c_key_len); + sqe->c_key_len = c_key_len; + break; + case WCRYPTO_CIPHER_DES: + sqe->c_alg = C_ALG_DES; + sqe->c_key_len = CKEY_LEN_DES; + break; + case WCRYPTO_CIPHER_3DES: + sqe->c_alg = C_ALG_3DES; + ret = get_3des_c_key_len(msg, &c_key_len); + sqe->c_key_len = c_key_len; + break; + default: + WD_ERR("Invalid cipher type.\n"); + ret = -WD_EINVAL; + break; + } + + return ret; +} + +static int fill_cipher_bd3_area(struct wd_queue *q, + struct wcrypto_cipher_msg *msg, struct hisi_sec_bd3_sqe *sqe) +{ + uintptr_t phy; + int ret; + + phy = (uintptr_t)drv_iova_map(q, msg->in, msg->in_bytes); + if (unlikely(!phy)) { + WD_ERR("Fail to get message in dma address.\n"); + return -WD_ENOMEM; + } + sqe->data_src_addr_l = (__u32)(phy & QM_L32BITS_MASK); + sqe->data_src_addr_h = HI_U32(phy); + phy = (uintptr_t)drv_iova_map(q, msg->out, msg->out_bytes); + if (unlikely(!phy)) { + WD_ERR("Fail to get message out dma address.\n"); + goto map_out_error; + } + sqe->data_dst_addr_l = (__u32)(phy & QM_L32BITS_MASK); + sqe->data_dst_addr_h = HI_U32(phy); + + ret = map_addr(q, msg->key, msg->key_bytes, &sqe->c_key_addr_l, + &sqe->c_key_addr_h, msg->data_fmt); + if (unlikely(ret)) { + WD_ERR("Fail to get cipher key dma address.\n"); + goto map_key_error; + } + + if (msg->iv_bytes == 0) + return WD_SUCCESS; + ret = map_addr(q, msg->iv, msg->iv_bytes, + &sqe->ipsec_scene.c_ivin_addr_l, + &sqe->ipsec_scene.c_ivin_addr_h, + msg->data_fmt); + if (unlikely(ret)) { + WD_ERR("Fail to get iv dma address\n"); + goto map_iv_error; + } + + return WD_SUCCESS; + +map_iv_error: + unmap_addr(q, msg->key, msg->key_bytes, sqe->c_key_addr_l, + sqe->c_key_addr_h, msg->data_fmt); +map_key_error: + phy = DMA_ADDR(sqe->data_dst_addr_h, sqe->data_dst_addr_l); + drv_iova_unmap(q, msg->out, (void *)(uintptr_t)phy, + msg->out_bytes); +map_out_error: + phy = DMA_ADDR(sqe->data_src_addr_h, sqe->data_src_addr_l); + drv_iova_unmap(q, msg->in, (void *)(uintptr_t)phy, + msg->in_bytes); + return -WD_ENOMEM; +} + +static int fill_cipher_bd3_mode(struct wcrypto_cipher_msg *msg, + struct hisi_sec_bd3_sqe *sqe) +{ + int ret = WD_SUCCESS; + + if (msg->op_type == WCRYPTO_CIPHER_ENCRYPTION) + sqe->cipher = CIPHER_ENCRYPT; + else if (msg->op_type == WCRYPTO_CIPHER_DECRYPTION) { + sqe->cipher = CIPHER_DECRYPT; + } else { + WD_ERR("Invalid cipher op type!\n"); + return -WD_EINVAL; + } + + switch (msg->mode) { + case WCRYPTO_CIPHER_ECB: + sqe->c_mode = C_MODE_ECB; + break; + case WCRYPTO_CIPHER_CBC: + sqe->c_mode = C_MODE_CBC; + break; + case WCRYPTO_CIPHER_OFB: + sqe->c_mode = C_MODE_OFB; + break; + case WCRYPTO_CIPHER_CTR: + sqe->c_mode = C_MODE_CTR; + sqe->ctr_counter_mode = CTR_128BIT_FLIP; + break; + case WCRYPTO_CIPHER_XTS: + sqe->c_mode = C_MODE_XTS; + break; + case WCRYPTO_CIPHER_CFB: + sqe->c_mode = C_MODE_CFB; + break; + default: + WD_ERR("Invalid cipher alg type!\n"); + ret = -WD_EINVAL; + break; + } + + return ret; +} + +static int fill_cipher_bd3(struct wd_queue *q, struct hisi_sec_bd3_sqe *sqe, + struct wcrypto_cipher_msg *msg, struct wcrypto_cipher_tag *tag) +{ + int ret; + + sqe->type = BD_TYPE3; + sqe->scene = SCENE_IPSEC; + + sqe->de = DATA_DST_ADDR_ENABLE; + if (msg->in_bytes > MAX_CIPHER_LENGTH) { + WD_ERR("input data is too large.\n"); + return -WD_EINVAL; + } + sqe->c_len = msg->in_bytes; + + fill_bd3_addr_type(msg->data_fmt, sqe); + + ret = fill_cipher_bd3_alg(msg, sqe); + if (ret != WD_SUCCESS) { + WD_ERR("fail to fill_cipher_bd3_alg.\n"); + return ret; + } + + ret = fill_cipher_bd3_mode(msg, sqe); + if (ret != WD_SUCCESS) { + WD_ERR("fail to fill_cipher_bd3_mode.\n"); + return ret; + } + + ret = fill_cipher_bd3_area(q, msg, sqe); + if (ret != WD_SUCCESS) { + WD_ERR("fail to fill_cipher_bd3_addr.\n"); + return ret; + } + + if (tag) + sqe->tag_l = tag->wcrypto_tag.ctx_id; + + return ret; +} + +static int sm4_aes_mode_check(int mode) +{ + switch (mode) { + case WCRYPTO_CIPHER_ECB: + case WCRYPTO_CIPHER_CBC: + case WCRYPTO_CIPHER_OFB: + case WCRYPTO_CIPHER_CFB: + case WCRYPTO_CIPHER_CTR: + case WCRYPTO_CIPHER_XTS: + case WCRYPTO_CIPHER_CCM: + case WCRYPTO_CIPHER_GCM: + return WD_SUCCESS; + default: + return -WD_EINVAL; + } +} + +static int triple_des_mode_check(int mode) +{ + switch (mode) { + case WCRYPTO_CIPHER_ECB: + case WCRYPTO_CIPHER_CBC: + case WCRYPTO_CIPHER_OFB: + return WD_SUCCESS; + default: + return -WD_EINVAL; + } +} + +static int cipher_comb_param_check(struct wcrypto_cipher_msg *msg) +{ + int ret = WD_SUCCESS; + + switch (msg->alg) { + case WCRYPTO_CIPHER_SM4: + case WCRYPTO_CIPHER_AES: + ret = sm4_aes_mode_check(msg->mode); + break; + case WCRYPTO_CIPHER_DES: + case WCRYPTO_CIPHER_3DES: + ret = triple_des_mode_check(msg->mode); + break; + default: + return -WD_EINVAL; + } + + return ret; +} + +int qm_fill_cipher_sqe(void *message, struct qm_queue_info *info, __u16 i) +{ + struct hisi_sec_sqe *sqe; + struct wcrypto_cipher_msg *msg = message; + struct wd_queue *q = info->q; + struct wcrypto_cipher_tag *tag = (void *)(uintptr_t)msg->usr_data; + uintptr_t temp; + int ret; + + ret = cipher_comb_param_check(msg); + if (ret) { + WD_ERR("invalid cipher alg = %hhu and mode = %hhu combination\n", + msg->alg, msg->mode); + return ret; + } + + temp = (uintptr_t)info->sq_base + i * info->sqe_size; + sqe = (struct hisi_sec_sqe *)temp; + + memset(sqe, 0, sizeof(struct hisi_sec_sqe)); + + if (tag->priv) + ret = fill_cipher_bd1(q, sqe, msg, tag); + else + ret = fill_cipher_bd2(q, sqe, msg, tag); + if (ret != WD_SUCCESS) + return ret; + + info->req_cache[i] = msg; + +#ifdef DEBUG_LOG + sec_dump_bd((unsigned char *)sqe, SQE_BYTES_NUMS); +#endif + + return ret; +} + +int qm_fill_cipher_bd3_sqe(void *message, struct qm_queue_info *info, __u16 i) +{ + struct hisi_sec_bd3_sqe *sqe3; + struct wcrypto_cipher_msg *msg = message; + struct wd_queue *q = info->q; + struct wcrypto_cipher_tag *tag = (void *)(uintptr_t)msg->usr_data; + uintptr_t temp; + int ret; + + ret = cipher_comb_param_check(msg); + if (ret) { + WD_ERR("invalid cipher alg = %hhu and mode = %hhu combination\n", + msg->alg, msg->mode); + return ret; + } + + temp = (uintptr_t)info->sq_base + i * info->sqe_size; + sqe3 = (struct hisi_sec_bd3_sqe *)temp; + + memset(sqe3, 0, sizeof(struct hisi_sec_bd3_sqe)); + + ret = fill_cipher_bd3(q, sqe3, msg, tag); + if (ret != WD_SUCCESS) + return ret; + + info->req_cache[i] = msg; + +#ifdef DEBUG_LOG + sec_dump_bd((unsigned char *)sqe3, SQE_BYTES_NUMS); +#endif + + return ret; +} + +static int digest_param_check(struct wcrypto_digest_msg *msg) +{ + if (unlikely(msg->alg >= WCRYPTO_MAX_DIGEST_TYPE)) { + WD_ERR("invalid digest type!\n"); + return -WD_EINVAL; + } + + if (unlikely(msg->in_bytes > MAX_CIPHER_LENGTH)) { + WD_ERR("invalid digest in_bytes!\n"); + return -WD_EINVAL; + } + + if (unlikely(msg->out_bytes & WORD_ALIGNMENT_MASK)) { + WD_ERR("invalid digest out_bytes!\n"); + return -WD_EINVAL; + } + + return 0; +} + +static int fill_digest_bd2_alg(struct wcrypto_digest_msg *msg, + struct hisi_sec_sqe *sqe) +{ + int ret; + + ret = digest_param_check(msg); + if (unlikely(ret)) + return ret; + + if (unlikely(msg->in_bytes == 0)) { + WD_ERR("digest bd2 not supports 0 packet!\n"); + return -WD_EINVAL; + } + + sqe->type2.mac_len = msg->out_bytes / WORD_BYTES; + if (msg->mode == WCRYPTO_DIGEST_NORMAL) + sqe->type2.a_alg = g_digest_a_alg[msg->alg]; + else if (msg->mode == WCRYPTO_DIGEST_HMAC) + sqe->type2.a_alg = g_hmac_a_alg[msg->alg]; + else { + WD_ERR("Invalid digest mode!\n"); + return -WD_EINVAL; + } + + return WD_SUCCESS; +} + +static void qm_fill_digest_long_bd(struct wcrypto_digest_msg *msg, + struct hisi_sec_sqe *sqe) +{ + __u64 total_bits = 0; + struct wcrypto_digest_tag *digest_tag = (void *)(uintptr_t)msg->usr_data; + + if (msg->has_next && (msg->iv_bytes == 0)) { + /* LONG BD FIRST */ + sqe->type2.ai_gen = AI_GEN_INNER; + sqe->type2.a_pad = AUTHPAD_NOPAD; + msg->iv_bytes = msg->out_bytes; + } else if (msg->has_next && (msg->iv_bytes != 0)) { + /* LONG BD MIDDLE */ + sqe->type2.ai_gen = AI_GEN_IVIN_ADDR; + sqe->type2.a_pad = AUTHPAD_NOPAD; + sqe->type2.a_ivin_addr_h = sqe->type2.mac_addr_h; + sqe->type2.a_ivin_addr_l = sqe->type2.mac_addr_l; + msg->iv_bytes = msg->out_bytes; + } else if (!msg->has_next && (msg->iv_bytes != 0)) { + /* LONG BD END */ + sqe->type2.ai_gen = AI_GEN_IVIN_ADDR; + sqe->type2.a_pad = AUTHPAD_PAD; + sqe->type2.a_ivin_addr_h = sqe->type2.mac_addr_h; + sqe->type2.a_ivin_addr_l = sqe->type2.mac_addr_l; + total_bits = digest_tag->long_data_len * BYTE_BITS; + sqe->type2.long_a_data_len_l = total_bits & QM_L32BITS_MASK; + sqe->type2.long_a_data_len_h = HI_U32(total_bits); + msg->iv_bytes = 0; + } else { + /* SHORT BD */ + msg->iv_bytes = 0; + } +} + +static int fill_digest_bd1_alg(struct wcrypto_digest_msg *msg, + struct hisi_sec_sqe *sqe) +{ + int ret; + + ret = digest_param_check(msg); + if (unlikely(ret)) + return ret; + + if (unlikely(msg->in_bytes == 0)) { + WD_ERR("digest bd1 not supports 0 packet!\n"); + return -WD_EINVAL; + } + + sqe->type1.mac_len = msg->out_bytes / WORD_BYTES; + if (msg->mode == WCRYPTO_DIGEST_NORMAL) + sqe->type1.a_alg = g_digest_a_alg[msg->alg]; + else if (msg->mode == WCRYPTO_DIGEST_HMAC) + sqe->type1.a_alg = g_hmac_a_alg[msg->alg]; + else { + WD_ERR("Invalid digest mode for BD1\n"); + return -WD_EINVAL; + } + + return WD_SUCCESS; +} + +static int fill_digest_bd1_addr(struct wd_queue *q, + struct wcrypto_digest_msg *msg, struct hisi_sec_sqe *sqe) +{ + uintptr_t phy; + int ret; + + if (msg->mode == WCRYPTO_DIGEST_HMAC) { + if (unlikely(msg->key_bytes & WORD_ALIGNMENT_MASK)) { + WD_ERR("Invalid digest key_bytes!\n"); + return -WD_EINVAL; + } + sqe->type1.a_key_len = msg->key_bytes / WORD_BYTES; + + ret = map_addr(q, msg->key, msg->key_bytes, + &sqe->type1.a_key_addr_l, + &sqe->type1.a_key_addr_h, msg->data_fmt); + if (unlikely(ret)) { + WD_ERR("Get digest bd1 hmac key dma address fail for bd1\n"); + return -WD_ENOMEM; + } + } + + /* for storage scene, data address using physical address */ + phy = (uintptr_t)msg->in; + sqe->type1.data_src_addr_l = (__u32)(phy & QM_L32BITS_MASK); + sqe->type1.data_src_addr_h = HI_U32(phy); + + phy = (uintptr_t)msg->out; + sqe->type1.mac_addr_l = (__u32)(phy & QM_L32BITS_MASK); + sqe->type1.mac_addr_h = HI_U32(phy); + + return WD_SUCCESS; +} + +static void fill_digest_bd1_udata(struct hisi_sec_sqe *sqe, + struct wd_sec_udata *udata) +{ + sqe->type1.gran_num = udata->gran_num; + sqe->type1.src_skip_data_len = udata->src_offset; + sqe->type1.block_size = udata->block_size; + sqe->type1.private_info = udata->dif.priv_info; + sqe->type1.chk_grd_ctrl = udata->dif.ctrl.verify.grd_verify_type; + sqe->type1.chk_ref_ctrl = udata->dif.ctrl.verify.ref_verify_type; + sqe->type1.lba_l = udata->dif.lba & QM_L32BITS_MASK; + sqe->type1.lba_h = udata->dif.lba >> QM_HADDR_SHIFT; +} + +static int fill_digest_bd1(struct wd_queue *q, struct hisi_sec_sqe *sqe, + struct wcrypto_digest_msg *msg, struct wcrypto_digest_tag *tag) +{ + struct wd_sec_udata *udata = tag->priv; + int ret = WD_SUCCESS; + + sqe->type = BD_TYPE1; + sqe->scene = SCENE_STORAGE; + sqe->auth = AUTH_MAC_CALCULATE; + + /* 'src' and 'dst' data using input data fmt, MAC output using pBuffer */ + sqe->mac_addr_type = HISI_FLAT_BUF; + + ret = fill_digest_bd1_alg(msg, sqe); + if (ret != WD_SUCCESS) + return ret; + + fill_digest_bd1_udata(sqe, udata); + + ret = fill_digest_bd1_addr(q, msg, sqe); + if (ret != WD_SUCCESS) + return ret; + + sqe->type1.tag = tag->wcrypto_tag.ctx_id; + + return ret; +} + +static int set_hmac_mode(struct wcrypto_digest_msg *msg, + struct hisi_sec_sqe *sqe, + struct wd_queue *q) +{ + int ret; + + if (msg->mode != WCRYPTO_DIGEST_HMAC) + return 0; + + if (unlikely(msg->key_bytes & WORD_ALIGNMENT_MASK)) { + WD_ERR("Invalid digest key_bytes!\n"); + return -WD_EINVAL; + } + sqe->type2.a_key_len = msg->key_bytes / WORD_BYTES; + + ret = map_addr(q, msg->key, msg->key_bytes, + &sqe->type2.a_key_addr_l, + &sqe->type2.a_key_addr_h, msg->data_fmt); + if (unlikely(ret)) { + WD_ERR("Get digest bd2 hmac key dma address fail!\n"); + return ret; + } + + return 0; +} + +static int fill_digest_bd2(struct wd_queue *q, struct hisi_sec_sqe *sqe, + struct wcrypto_digest_msg *msg, struct wcrypto_digest_tag *tag) +{ + int ret = -WD_ENOMEM; + uintptr_t phy; + + sqe->type = BD_TYPE2; + sqe->scene = SCENE_IPSEC; + + sqe->auth = AUTH_MAC_CALCULATE; + sqe->type2.a_len = msg->in_bytes; + + phy = (uintptr_t)drv_iova_map(q, msg->in, msg->in_bytes); + if (unlikely(!phy)) { + WD_ERR("Get message in dma address fail!\n"); + return -WD_ENOMEM; + } + sqe->type2.data_src_addr_l = (__u32)(phy & QM_L32BITS_MASK); + sqe->type2.data_src_addr_h = HI_U32(phy); + + /* out = mac, so 'out' format is as same as 'mac', which is pbuffer */ + ret = map_addr(q, msg->out, msg->out_bytes, &sqe->type2.mac_addr_l, + &sqe->type2.mac_addr_h, msg->data_fmt); + if (unlikely(ret)) { + WD_ERR("Get digest bd2 message out dma address fail!\n"); + goto map_out_error; + } + + ret = set_hmac_mode(msg, sqe, q); + if (ret) + goto map_key_error; + + ret = fill_digest_bd2_alg(msg, sqe); + if (ret != WD_SUCCESS) { + WD_ERR("fill_digest_bd2_alg fail!\n"); + goto map_alg_error; + } + qm_fill_digest_long_bd(msg, sqe); + + if (tag) + sqe->type2.tag = tag->wcrypto_tag.ctx_id; + + return ret; + +map_alg_error: + unmap_addr(q, msg->key, msg->key_bytes, sqe->type2.a_key_addr_l, + sqe->type2.a_key_addr_h, msg->data_fmt); +map_key_error: + unmap_addr(q, msg->out, msg->out_bytes, sqe->type2.mac_addr_l, + sqe->type2.mac_addr_h, msg->data_fmt); +map_out_error: + phy = DMA_ADDR(sqe->type2.data_src_addr_h, + sqe->type2.data_src_addr_l); + drv_iova_unmap(q, msg->in, (void *)(uintptr_t)phy, msg->in_bytes); + return ret; +} + +/* + * According to wcrypto_digest_poll(), the return number mean: + * 0: parse failed + * 1: parse a BD successfully + */ +int qm_fill_digest_sqe(void *message, struct qm_queue_info *info, __u16 i) +{ + struct hisi_sec_sqe *sqe; + struct wcrypto_digest_msg *msg = message; + struct wd_queue *q = info->q; + struct wcrypto_digest_tag *tag = (void *)(uintptr_t)msg->usr_data; + int ret; + uintptr_t temp; + + temp = (uintptr_t)info->sq_base + i * info->sqe_size; + sqe = (struct hisi_sec_sqe *)temp; + + memset(sqe, 0, sizeof(struct hisi_sec_sqe)); + + fill_bd_addr_type(msg->data_fmt, sqe); + + if (tag->priv) + ret = fill_digest_bd1(q, sqe, msg, tag); + else + ret = fill_digest_bd2(q, sqe, msg, tag); + + if (ret != WD_SUCCESS) + return ret; + + info->req_cache[i] = msg; + +#ifdef DEBUG_LOG + sec_dump_bd((unsigned char *)sqe, SQE_BYTES_NUMS); +#endif + + return WD_SUCCESS; +} + +static void qm_fill_digest_long_bd3(struct wcrypto_digest_msg *msg, + struct hisi_sec_bd3_sqe *sqe) +{ + struct wcrypto_digest_tag *digest_tag = (void *)(uintptr_t)msg->usr_data; + __u64 total_bits = 0; + + /* iv_bytes is multiplexed as a flag bit to determine whether it is LOGN BD FIRST */ + if (msg->has_next && msg->iv_bytes == 0) { + /* LONG BD FIRST */ + sqe->ai_gen = AI_GEN_INNER; + sqe->stream_scene.auth_pad = AUTHPAD_NOPAD; + msg->iv_bytes = msg->out_bytes; + } else if (msg->has_next && msg->iv_bytes != 0) { + /* LONG BD MIDDLE */ + sqe->ai_gen = AI_GEN_IVIN_ADDR; + sqe->stream_scene.auth_pad = AUTHPAD_NOPAD; + sqe->auth_key_iv.a_ivin_addr_h = sqe->mac_addr_h; + sqe->auth_key_iv.a_ivin_addr_l = sqe->mac_addr_l; + msg->iv_bytes = msg->out_bytes; + } else if (!msg->has_next && msg->iv_bytes != 0) { + /* LONG BD END */ + sqe->ai_gen = AI_GEN_IVIN_ADDR; + sqe->stream_scene.auth_pad = AUTHPAD_PAD; + sqe->auth_key_iv.a_ivin_addr_h = sqe->mac_addr_h; + sqe->auth_key_iv.a_ivin_addr_l = sqe->mac_addr_l; + total_bits = digest_tag->long_data_len * BYTE_BITS; + sqe->stream_scene.long_a_data_len_l = total_bits & QM_L32BITS_MASK; + sqe->stream_scene.long_a_data_len_h = HI_U32(total_bits); + msg->iv_bytes = 0; + } else { + /* SHORT BD */ + msg->iv_bytes = 0; + } +} + +static int fill_digest_bd3_alg(struct wcrypto_digest_msg *msg, + struct hisi_sec_bd3_sqe *sqe) +{ + int ret; + + ret = digest_param_check(msg); + if (unlikely(ret)) + return ret; + + sqe->mac_len = msg->out_bytes / WORD_BYTES; + if (msg->mode == WCRYPTO_DIGEST_NORMAL) + sqe->a_alg = g_digest_a_alg[msg->alg]; + else if (msg->mode == WCRYPTO_DIGEST_HMAC) + sqe->a_alg = g_hmac_a_alg[msg->alg]; + else { + WD_ERR("Invalid digest mode!\n"); + return -WD_EINVAL; + } + + return WD_SUCCESS; +} + +static int set_hmac_mode_v3(struct wcrypto_digest_msg *msg, + struct hisi_sec_bd3_sqe *sqe, + struct wd_queue *q) +{ + int ret; + + if (msg->mode != WCRYPTO_DIGEST_HMAC) + return 0; + + if (unlikely(msg->key_bytes & WORD_ALIGNMENT_MASK)) { + WD_ERR("Invalid digest key_bytes!\n"); + ret = -WD_EINVAL; + return ret; + } + sqe->a_key_len = msg->key_bytes / WORD_BYTES; + ret = map_addr(q, msg->key, msg->key_bytes, + &sqe->auth_key_iv.a_key_addr_l, + &sqe->auth_key_iv.a_key_addr_h, + msg->data_fmt); + if (unlikely(ret)) { + WD_ERR("Get digest bd3 hmac key dma address fail!\n"); + return ret; + } + + return 0; +} + +static int fill_digest_bd3(struct wd_queue *q, struct hisi_sec_bd3_sqe *sqe, + struct wcrypto_digest_msg *msg, struct wcrypto_digest_tag *tag) +{ + int ret = -WD_ENOMEM; + uintptr_t phy; + + sqe->type = BD_TYPE3; + sqe->scene = SCENE_STREAM; + + sqe->auth = AUTH_MAC_CALCULATE; + sqe->a_len = msg->in_bytes; + + phy = (uintptr_t)drv_iova_map(q, msg->in, msg->in_bytes); + if (unlikely(!phy)) { + WD_ERR("Get message in dma address fail!\n"); + return -WD_ENOMEM; + } + sqe->data_src_addr_l = (__u32)(phy & QM_L32BITS_MASK); + sqe->data_src_addr_h = HI_U32(phy); + + /* out = mac, so 'out' format is as same as 'mac', which is pbuffer */ + ret = map_addr(q, msg->out, msg->out_bytes, &sqe->mac_addr_l, + &sqe->mac_addr_h, msg->data_fmt); + if (unlikely(ret)) { + WD_ERR("Get digest bd3 message out dma address fail!\n"); + goto map_out_error; + } + + ret = set_hmac_mode_v3(msg, sqe, q); + if (ret) + goto map_key_error; + + ret = fill_digest_bd3_alg(msg, sqe); + if (ret != WD_SUCCESS) { + WD_ERR("fill_digest_bd3_alg fail!\n"); + goto map_alg_error; + } + qm_fill_digest_long_bd3(msg, sqe); + + if (tag) + sqe->tag_l = tag->wcrypto_tag.ctx_id; + + return ret; + +map_alg_error: + unmap_addr(q, msg->key, msg->key_bytes, sqe->auth_key_iv.a_key_addr_l, + sqe->auth_key_iv.a_key_addr_h, msg->data_fmt); +map_key_error: + unmap_addr(q, msg->out, msg->out_bytes, sqe->mac_addr_l, + sqe->mac_addr_h, msg->data_fmt); +map_out_error: + phy = DMA_ADDR(sqe->data_src_addr_h, sqe->data_src_addr_l); + drv_iova_unmap(q, msg->in, (void *)(uintptr_t)phy, msg->in_bytes); + return ret; +} + +int qm_fill_digest_bd3_sqe(void *message, struct qm_queue_info *info, __u16 i) +{ + struct wcrypto_digest_msg *msg = message; + struct wcrypto_digest_tag *tag = (void *)(uintptr_t)msg->usr_data; + struct hisi_sec_bd3_sqe *sqe; + struct wd_queue *q = info->q; + uintptr_t temp; + int ret; + + temp = (uintptr_t)info->sq_base + i * info->sqe_size; + sqe = (struct hisi_sec_bd3_sqe *)temp; + + memset(sqe, 0, sizeof(struct hisi_sec_bd3_sqe)); + + fill_bd3_addr_type(msg->data_fmt, sqe); + + ret = fill_digest_bd3(q, sqe, msg, tag); + if (ret != WD_SUCCESS) + return ret; + + info->req_cache[i] = msg; + +#ifdef DEBUG_LOG + sec_dump_bd((unsigned int *)sqe, SQE_BYTES_NUMS); +#endif + + return WD_SUCCESS; +} + +static void parse_cipher_bd1(struct wd_queue *q, struct hisi_sec_sqe *sqe, + struct wcrypto_cipher_msg *cipher_msg) +{ + __u64 dma_addr; + + if (sqe->type1.done != SEC_HW_TASK_DONE || sqe->type1.error_type) { + WD_ERR("SEC BD1 %s fail!done=0x%x, etype=0x%x\n", "cipher", + sqe->type1.done, sqe->type1.error_type); + cipher_msg->result = WD_IN_EPARA; + } else { + if (sqe->type1.dif_check == DIF_VERIFY_FAIL) + cipher_msg->result = WD_VERIFY_ERR; + else + cipher_msg->result = WD_SUCCESS; + } + + dma_addr = DMA_ADDR(sqe->type1.c_key_addr_h, + sqe->type1.c_key_addr_l); + drv_iova_unmap(q, cipher_msg->key, (void *)(uintptr_t)dma_addr, + cipher_msg->key_bytes); + if (cipher_msg->iv) { + dma_addr = DMA_ADDR(sqe->type1.c_ivin_addr_h, + sqe->type1.c_ivin_addr_l); + drv_iova_unmap(q, cipher_msg->iv, (void *)(uintptr_t)dma_addr, + cipher_msg->iv_bytes); + } +} + +static void cipher_ofb_data_handle(struct wcrypto_cipher_msg *msg) +{ + __u64 *in_data, *out_data; + __u32 bufsz = 0; + __u8 *in, *out; + __u32 i, j; + int ret; + + if (msg->data_fmt == WD_SGL_BUF) { + ret = wd_get_sgl_bufsize((struct wd_sgl *)msg->out, &bufsz); + if (unlikely(ret || !bufsz)) + return; + + /* When SGL pool creating, 'bufsz' is at least 4096, and align_sz + * is at least 8, so 'bufsz' is an integer multiple of 8. + */ + for (i = 1; i < msg->out_bytes / bufsz + 1; i++) { + in_data = wd_get_sge_buf((struct wd_sgl *)msg->in, i); + out_data = wd_get_sge_buf((struct wd_sgl *)msg->out, i); + if (unlikely(!in_data || !out_data)) + return; + for (j = 0; j < (bufsz >> U64_DATA_SHIFT) + 1; j++) + out_data[j] = in_data[j] ^ out_data[j]; + } + + in = wd_get_sge_buf((struct wd_sgl *)msg->in, i); + out = wd_get_sge_buf((struct wd_sgl *)msg->out, i); + if (unlikely(!in || !out)) + return; + for (j = 0; j < msg->out_bytes - bufsz * (i - 1); j++) + out[j] = in[j] ^ out[j]; + } else { + out_data = (__u64 *)msg->out; + in_data = (__u64 *)msg->in; + + for (i = 0; i < msg->out_bytes >> U64_DATA_SHIFT; i++) + out_data[i] = in_data[i] ^ out_data[i]; + for (i = i * U64_DATA_BYTES; i < msg->out_bytes; i++) + msg->out[i] = msg->in[i] ^ msg->out[i]; + } +} + +static void parse_cipher_bd2(struct wd_queue *q, struct hisi_sec_sqe *sqe, + struct wcrypto_cipher_msg *cipher_msg) +{ + __u64 dma_addr; + + if (sqe->type2.done != SEC_HW_TASK_DONE || sqe->type2.error_type) { + WD_ERR("SEC BD2 %s fail!done=0x%x, etype=0x%x\n", "cipher", + sqe->type2.done, sqe->type2.error_type); + cipher_msg->result = WD_IN_EPARA; + } else + cipher_msg->result = WD_SUCCESS; + + dma_addr = DMA_ADDR(sqe->type2.data_src_addr_h, + sqe->type2.data_src_addr_l); + drv_iova_unmap(q, cipher_msg->in, (void *)(uintptr_t)dma_addr, + cipher_msg->in_bytes); + dma_addr = DMA_ADDR(sqe->type2.data_dst_addr_h, + sqe->type2.data_dst_addr_l); + drv_iova_unmap(q, cipher_msg->out, (void *)(uintptr_t)dma_addr, + cipher_msg->out_bytes); + unmap_addr(q, cipher_msg->key, cipher_msg->key_bytes, + sqe->type2.c_key_addr_l, sqe->type2.c_key_addr_h, + cipher_msg->data_fmt); + + if (cipher_msg->iv_bytes != 0) + unmap_addr(q, cipher_msg->iv, cipher_msg->iv_bytes, + sqe->type2.c_ivin_addr_l, sqe->type2.c_ivin_addr_h, + cipher_msg->data_fmt); + + update_iv(cipher_msg); + + if (cipher_msg->mode == WCRYPTO_CIPHER_OFB) + cipher_ofb_data_handle(cipher_msg); +} + +static void parse_cipher_bd3(struct wd_queue *q, struct hisi_sec_bd3_sqe *sqe, + struct wcrypto_cipher_msg *cipher_msg) +{ + __u64 dma_addr; + + if (sqe->done != SEC_HW_TASK_DONE || sqe->error_type) { + WD_ERR("Fail to parse SEC BD3 %s, done=0x%x, etype=0x%x\n", "cipher", + sqe->done, sqe->error_type); + cipher_msg->result = WD_IN_EPARA; + } else { + cipher_msg->result = WD_SUCCESS; + } + + dma_addr = DMA_ADDR(sqe->data_src_addr_h, sqe->data_src_addr_l); + drv_iova_unmap(q, cipher_msg->in, (void *)(uintptr_t)dma_addr, + cipher_msg->in_bytes); + dma_addr = DMA_ADDR(sqe->data_dst_addr_h, sqe->data_dst_addr_l); + drv_iova_unmap(q, cipher_msg->out, (void *)(uintptr_t)dma_addr, + cipher_msg->out_bytes); + unmap_addr(q, cipher_msg->key, cipher_msg->key_bytes, sqe->c_key_addr_l, + sqe->c_key_addr_h, cipher_msg->data_fmt); + + if (cipher_msg->iv_bytes != 0) + unmap_addr(q, cipher_msg->iv, cipher_msg->iv_bytes, + sqe->ipsec_scene.c_ivin_addr_l, + sqe->ipsec_scene.c_ivin_addr_h, + cipher_msg->data_fmt); + + update_iv(cipher_msg); +} + +/* + * According to wcrypto_cipher_poll(), the return number mean: + * 0: parse failed + * 1: parse a BD successfully + */ +int qm_parse_cipher_sqe(void *msg, const struct qm_queue_info *info, + __u16 i, __u16 usr) +{ + struct wcrypto_cipher_msg *cipher_msg = info->req_cache[i]; + struct hisi_sec_sqe *sqe = msg; + struct wd_queue *q = info->q; + + if (unlikely(!cipher_msg)) { + WD_ERR("info->req_cache is null at index:%hu\n", i); + return 0; + } + + if (sqe->type == BD_TYPE2) { + if (usr && sqe->type2.tag != usr) + return 0; + parse_cipher_bd2(q, sqe, cipher_msg); + } else if (sqe->type == BD_TYPE1) { + if (usr && sqe->type1.tag != usr) + return 0; + parse_cipher_bd1(q, sqe, cipher_msg); + } else { + WD_ERR("SEC BD Type error\n"); + cipher_msg->result = WD_IN_EPARA; + } + +#ifdef DEBUG_LOG + sec_dump_bd((unsigned char *)sqe, SQE_BYTES_NUMS); +#endif + + return 1; +} + +int qm_parse_cipher_bd3_sqe(void *msg, const struct qm_queue_info *info, + __u16 i, __u16 usr) +{ + struct wcrypto_cipher_msg *cipher_msg = info->req_cache[i]; + struct hisi_sec_bd3_sqe *sqe = msg; + struct wd_queue *q = info->q; + + if (unlikely(!cipher_msg)) { + WD_ERR("info->req_cache is null at index:%hu\n", i); + return 0; + } + + if (likely(sqe->type == BD_TYPE3)) { + if (unlikely(usr && sqe->tag_l != usr)) + return 0; + parse_cipher_bd3(q, sqe, cipher_msg); + } else { + WD_ERR("SEC BD Type error\n"); + cipher_msg->result = WD_IN_EPARA; + } + +#ifdef DEBUG_LOG + sec_dump_bd((unsigned char *)sqe, SQE_BYTES_NUMS); +#endif + + return 1; +} + +static void parse_digest_bd1(struct wd_queue *q, struct hisi_sec_sqe *sqe, + struct wcrypto_digest_msg *digest_msg) +{ + __u64 dma_addr; + + if (sqe->type1.done != SEC_HW_TASK_DONE + || sqe->type1.error_type) { + WD_ERR("SEC BD1 %s fail!done=0x%x, etype=0x%x\n", "digest", + sqe->type1.done, sqe->type1.error_type); + digest_msg->result = WD_IN_EPARA; + } else { + if (sqe->type1.dif_check == DIF_VERIFY_FAIL) + digest_msg->result = WD_VERIFY_ERR; + else + digest_msg->result = WD_SUCCESS; + } + + if (digest_msg->mode == WCRYPTO_DIGEST_HMAC) { + dma_addr = DMA_ADDR(sqe->type1.a_key_addr_h, + sqe->type1.a_key_addr_h); + drv_iova_unmap(q, digest_msg->key, + (void *)(uintptr_t)dma_addr, digest_msg->key_bytes); + } +} + +static void parse_digest_bd2(struct wd_queue *q, struct hisi_sec_sqe *sqe, + struct wcrypto_digest_msg *digest_msg) +{ + __u64 dma_addr; + + if (sqe->type2.done != SEC_HW_TASK_DONE + || sqe->type2.error_type) { + WD_ERR("SEC BD2 %s fail!done=0x%x, etype=0x%x\n", "digest", + sqe->type2.done, sqe->type2.error_type); + digest_msg->result = WD_IN_EPARA; + } else + digest_msg->result = WD_SUCCESS; + + dma_addr = DMA_ADDR(sqe->type2.data_src_addr_h, + sqe->type2.data_src_addr_l); + drv_iova_unmap(q, digest_msg->in, (void *)(uintptr_t)dma_addr, + digest_msg->in_bytes); + /* out = mac, so 'out' format is as same as 'mac', which is pbuffer */ + unmap_addr(q, digest_msg->out, digest_msg->out_bytes, + sqe->type2.mac_addr_l, sqe->type2.mac_addr_h, + digest_msg->data_fmt); + if (digest_msg->mode == WCRYPTO_DIGEST_HMAC) + unmap_addr(q, digest_msg->key, digest_msg->key_bytes, + sqe->type2.a_key_addr_l, sqe->type2.a_key_addr_h, + digest_msg->data_fmt); +} + +int qm_parse_digest_sqe(void *msg, const struct qm_queue_info *info, + __u16 i, __u16 usr) +{ + struct wcrypto_digest_msg *digest_msg = info->req_cache[i]; + struct hisi_sec_sqe *sqe = msg; + struct wd_queue *q = info->q; + + if (unlikely(!digest_msg)) { + WD_ERR("info->req_cache is null at index:%hu\n", i); + return 0; + } + + if (sqe->type == BD_TYPE2) { + if (usr && sqe->type2.tag != usr) + return 0; + parse_digest_bd2(q, sqe, digest_msg); + } else if (sqe->type == BD_TYPE1) { + if (usr && sqe->type1.tag != usr) + return 0; + parse_digest_bd1(q, sqe, digest_msg); + } else { + WD_ERR("SEC Digest BD Type error\n"); + digest_msg->result = WD_IN_EPARA; + } + +#ifdef DEBUG_LOG + sec_dump_bd((unsigned char *)sqe, SQE_BYTES_NUMS); +#endif + + return 1; +} + +static int fill_aead_bd3_alg(struct wcrypto_aead_msg *msg, + struct hisi_sec_bd3_sqe *sqe) +{ + __u8 c_key_len = 0; + int ret = WD_SUCCESS; + + switch (msg->calg) { + case WCRYPTO_CIPHER_SM4: + sqe->c_alg = C_ALG_SM4; + sqe->c_key_len = CKEY_LEN_SM4; + break; + case WCRYPTO_CIPHER_AES: + sqe->c_alg = C_ALG_AES; + ret = get_aes_c_key_len(msg->cmode, msg->ckey_bytes, &c_key_len); + sqe->c_key_len = c_key_len; + break; + default: + WD_ERR("Invalid cipher type!\n"); + return -WD_EINVAL; + } + + /* CCM/GCM this region is set to 0 */ + if (msg->cmode == WCRYPTO_CIPHER_CCM || + msg->cmode == WCRYPTO_CIPHER_GCM) + return ret; + + sqe->mac_len = msg->auth_bytes / SEC_SQE_LEN_RATE; + sqe->a_key_len = msg->akey_bytes / SEC_SQE_LEN_RATE; + + if (msg->dalg == WCRYPTO_SHA1 || msg->dalg == WCRYPTO_SHA256 || + msg->dalg == WCRYPTO_SHA512) { + sqe->a_alg = g_hmac_a_alg[msg->dalg]; + } else { + WD_ERR("Invalid digest type!\n"); + ret = -WD_EINVAL; + } + + return ret; +} + +static int fill_aead_bd3_mode(struct wcrypto_aead_msg *msg, + struct hisi_sec_bd3_sqe *sqe3) +{ + int ret = WD_SUCCESS; + + if (msg->op_type == WCRYPTO_CIPHER_ENCRYPTION_DIGEST) { + sqe3->cipher = CIPHER_ENCRYPT; + sqe3->auth = AUTH_MAC_CALCULATE; + sqe3->seq = WCRYPTO_CIPHER_THEN_DIGEST; + } else if (msg->op_type == WCRYPTO_CIPHER_DECRYPTION_DIGEST) { + sqe3->cipher = CIPHER_DECRYPT; + sqe3->auth = AUTH_MAC_VERIFY; + sqe3->seq = WCRYPTO_DIGEST_THEN_CIPHER; + } else { + WD_ERR("Invalid cipher op type!\n"); + return -WD_EINVAL; + } + + switch (msg->cmode) { + case WCRYPTO_CIPHER_ECB: + sqe3->c_mode = C_MODE_ECB; + break; + case WCRYPTO_CIPHER_CBC: + sqe3->c_mode = C_MODE_CBC; + break; + case WCRYPTO_CIPHER_CTR: + sqe3->c_mode = C_MODE_CTR; + sqe3->ctr_counter_mode = CTR_128BIT_FLIP; + break; + case WCRYPTO_CIPHER_CCM: + sqe3->c_mode = C_MODE_CCM; + sqe3->auth = NO_AUTH; + sqe3->a_len = msg->assoc_bytes; + sqe3->c_icv_len = msg->auth_bytes; + break; + case WCRYPTO_CIPHER_GCM: + sqe3->c_mode = C_MODE_GCM; + sqe3->auth = NO_AUTH; + sqe3->a_len = msg->assoc_bytes; + sqe3->c_icv_len = msg->auth_bytes; + break; + default: + WD_ERR("Invalid cipher cmode type!\n"); + ret = -WD_EINVAL; + } + + return ret; +} + +#define IV_LAST_BYTE1 1 +#define IV_LAST_BYTE2 2 +#define IV_CTR_INIT 1 +#define IV_CM_CAL_NUM 2 +#define IV_CL_MASK 0x7 +#define IV_FLAGS_OFFSET 0x6 +#define IV_CM_OFFSET 0x3 +#define IV_LAST_BYTE_MASK 0xFF +#define IV_BYTE_OFFSET 0x8 + +static void set_aead_auth_iv(struct wcrypto_aead_msg *msg) +{ + __u32 data_size = msg->in_bytes; + __u8 flags = 0x00; + __u8 *iv, *aiv; + __u8 cl, cm; + + if (msg->data_fmt == WD_SGL_BUF) { + /* CCM need to cal a_iv, GCM same as c_iv */ + iv = wd_get_first_sge_buf((struct wd_sgl *)msg->iv); + aiv = wd_get_first_sge_buf((struct wd_sgl *)msg->aiv); + } else { + iv = msg->iv; + aiv = msg->aiv; + } + + memcpy(aiv, iv, msg->iv_bytes); + if (msg->cmode == WCRYPTO_CIPHER_CCM) { + iv[msg->iv_bytes - IV_LAST_BYTE2] = 0x00; + iv[msg->iv_bytes - IV_LAST_BYTE1] = IV_CTR_INIT; + + /* the last 3bit is L' */ + cl = iv[0] & IV_CL_MASK; + flags |= cl; + + /* the M' is bit3~bit5, the Flags is bit6 */ + cm = (msg->auth_bytes - IV_CM_CAL_NUM) / IV_CM_CAL_NUM; + flags |= cm << IV_CM_OFFSET; + if (msg->assoc_bytes > 0) + flags |= 0x01 << IV_FLAGS_OFFSET; + + aiv[0] = flags; + /* + * the last 32bit is counter's initial number, + * but the nonce uses the first 16bit + * the tail 16bit fill with the cipher length + */ + aiv[msg->iv_bytes - IV_LAST_BYTE1] = + data_size & IV_LAST_BYTE_MASK; + data_size >>= IV_BYTE_OFFSET; + aiv[msg->iv_bytes - IV_LAST_BYTE2] = + data_size & IV_LAST_BYTE_MASK; + } +} + +static int fill_aead_bd3_addr_src(struct wd_queue *q, + struct wcrypto_aead_msg *msg, struct hisi_sec_bd3_sqe *sqe) +{ + uintptr_t phy1, phy2; + + phy1 = (uintptr_t)drv_iova_map(q, msg->in, msg->in_bytes); + if (unlikely(!phy1)) { + WD_ERR("fail to get bd3 message in dma address!\n"); + return -WD_ENOMEM; + } + sqe->data_src_addr_l = (__u32)(phy1 & QM_L32BITS_MASK); + sqe->data_src_addr_h = HI_U32(phy1); + + if (msg->op_type == WCRYPTO_CIPHER_DECRYPTION_DIGEST && + msg->data_fmt == WD_FLAT_BUF) { + phy2 = phy1 + msg->assoc_bytes + msg->in_bytes; + sqe->mac_addr_l = (__u32)(phy2 & QM_L32BITS_MASK); + sqe->mac_addr_h = HI_U32(phy2); + } + + return WD_SUCCESS; +} + +static int fill_aead_bd3_addr_dst(struct wd_queue *q, + struct wcrypto_aead_msg *msg, struct hisi_sec_bd3_sqe *sqe) +{ + uintptr_t phy1, phy2; + + phy1 = (uintptr_t)drv_iova_map(q, msg->out, msg->out_bytes); + if (unlikely(!phy1)) { + WD_ERR("fail to get bd3 message out dma address!\n"); + return -WD_ENOMEM; + } + sqe->data_dst_addr_l = (__u32)(phy1 & QM_L32BITS_MASK); + sqe->data_dst_addr_h = HI_U32(phy1); + + if (msg->op_type == WCRYPTO_CIPHER_ENCRYPTION_DIGEST && + msg->data_fmt == WD_FLAT_BUF) { + phy2 = phy1 + msg->out_bytes - msg->auth_bytes; + sqe->mac_addr_l = (__u32)(phy2 & QM_L32BITS_MASK); + sqe->mac_addr_h = HI_U32(phy2); + } + + return WD_SUCCESS; +} + + +static int aead_bd3_map_iv_mac(struct wd_queue *q, struct wcrypto_aead_msg *msg, + struct hisi_sec_bd3_sqe *sqe) +{ + __u8 mac[AEAD_IV_MAX_BYTES] = { 0 }; + uintptr_t phy, phy_mac; + void *p; + int ret; + + /* + * 'msg->iv' use pBuffer, so when 'data_fmt' is sgl, we use its + * first buffer as pBuffer, and 'buf_sz > key_sz' is needed. + */ + if (msg->data_fmt == WD_SGL_BUF) { + if (unlikely(!msg->iv)) + return -WD_ENOMEM; + p = drv_get_sgl_pri((struct wd_sgl *)msg->iv); + phy = ((struct hisi_sgl *)p)->sge_entries[0].buf; + } else { + phy = (uintptr_t)drv_iova_map(q, msg->iv, msg->iv_bytes); + } + if (unlikely(!phy)) { + WD_ERR("Get key dma address fail!\n"); + return -WD_ENOMEM; + } + + sqe->ipsec_scene.c_ivin_addr_l = (__u32)(phy & QM_L32BITS_MASK); + sqe->ipsec_scene.c_ivin_addr_h = HI_U32(phy); + + if (msg->data_fmt == WD_SGL_BUF) { + if (msg->op_type == WCRYPTO_CIPHER_DECRYPTION_DIGEST) { + /* + *'MAC' is at the end of 'in', as it is not easy to get + * 'MAC' dma address, so when we do decrypt, we copy + * 'MAC' to the end of 'IV'. + */ + ret = wd_sgl_cp_to_pbuf((struct wd_sgl *)msg->in, + msg->assoc_bytes + msg->in_bytes, + (void *)mac, msg->auth_bytes); + if (ret) + return ret; + ret = wd_sgl_cp_from_pbuf((struct wd_sgl *)msg->iv, + AEAD_IV_MAX_BYTES, + (void *)mac, msg->auth_bytes); + if (ret) + return ret; + } + /* + * When we do decrypt, 'MAC' has been at the end 'IV', + * and when we do encrypt, obtain a memory from IV SGL as a + * temporary address space for MAC. + */ + phy_mac = phy + AEAD_IV_MAX_BYTES; + sqe->mac_addr_l = (__u32)(phy_mac & QM_L32BITS_MASK); + sqe->mac_addr_h = HI_U32(phy); + } + + return WD_SUCCESS; +} + +/* + * As 'MAC' needs an continuous memory, + * When do decrypt: + * 'MAC' dma is at the tail of 'out' when use pbuffer; + * 'MAC' dma is at the tail of 'iv' when use sgl; + * When do encrypt: + * 'MAC' dma is at the tail of 'in' when use pbuffer; + * 'MAC' dma is at the tail of 'iv' when use sgl; + */ +static int fill_aead_bd3_addr(struct wd_queue *q, + struct wcrypto_aead_msg *msg, struct hisi_sec_bd3_sqe *sqe) +{ + uintptr_t phy; + int ret; + + /* AEAD algorithms CCM/GCM support 0 in_bytes */ + ret = fill_aead_bd3_addr_src(q, msg, sqe); + if (unlikely(ret)) + return ret; + + ret = fill_aead_bd3_addr_dst(q, msg, sqe); + if (unlikely(ret)) + goto map_out_error; + + ret = map_addr(q, msg->ckey, msg->ckey_bytes, &sqe->c_key_addr_l, + &sqe->c_key_addr_h, msg->data_fmt); + if (unlikely(ret)) { + WD_ERR("fail to get aead bd3 key dma address!\n"); + goto map_ckey_error; + } + + ret = map_addr(q, msg->akey, msg->akey_bytes, &sqe->auth_key_iv.a_key_addr_l, + &sqe->auth_key_iv.a_key_addr_h, msg->data_fmt); + if (unlikely(ret)) { + WD_ERR("fail to get auth key dma address!\n"); + goto map_akey_error; + } + + ret = aead_bd3_map_iv_mac(q, msg, sqe); + if (unlikely(ret)) + goto map_civ_error; + + /* CCM/GCM should init a_iv */ + set_aead_auth_iv(msg); + ret = map_addr(q, msg->aiv, msg->iv_bytes, &sqe->auth_key_iv.a_ivin_addr_l, + &sqe->auth_key_iv.a_ivin_addr_h, msg->data_fmt); + if (unlikely(ret)) { + WD_ERR("fail to get auth iv dma address!\n"); + goto map_aiv_error; + } + + return WD_SUCCESS; + +map_aiv_error: + unmap_addr(q, msg->iv, msg->iv_bytes, sqe->ipsec_scene.c_ivin_addr_l, + sqe->ipsec_scene.c_ivin_addr_h, msg->data_fmt); +map_civ_error: + unmap_addr(q, msg->akey, msg->akey_bytes, sqe->auth_key_iv.a_key_addr_l, + sqe->ipsec_scene.c_ivin_addr_h, msg->data_fmt); +map_akey_error: + unmap_addr(q, msg->ckey, msg->ckey_bytes, sqe->c_key_addr_l, + sqe->c_key_addr_h, msg->data_fmt); +map_ckey_error: + phy = DMA_ADDR(sqe->data_dst_addr_h, sqe->data_dst_addr_l); + drv_iova_unmap(q, msg->out, (void *)(uintptr_t)phy, msg->out_bytes); +map_out_error: + phy = DMA_ADDR(sqe->data_src_addr_h, sqe->data_src_addr_l); + if (msg->in_bytes) + drv_iova_unmap(q, msg->in, (void *)(uintptr_t)phy, + msg->in_bytes); + return -WD_ENOMEM; +} + +static int fill_aead_bd3(struct wd_queue *q, struct hisi_sec_bd3_sqe *sqe, + struct wcrypto_aead_msg *msg, struct wcrypto_aead_tag *tag) +{ + int ret; + + sqe->type = BD_TYPE3; + sqe->scene = SCENE_IPSEC; + sqe->de = DATA_DST_ADDR_ENABLE; + sqe->c_len = msg->in_bytes; + sqe->cipher_src_offset = msg->assoc_bytes; + sqe->a_len = msg->in_bytes + msg->assoc_bytes; + + ret = fill_aead_bd3_alg(msg, sqe); + if (ret != WD_SUCCESS) { + WD_ERR("fail to fill_aead_bd3_alg!\n"); + return ret; + } + + ret = fill_aead_bd3_mode(msg, sqe); + if (ret != WD_SUCCESS) { + WD_ERR("fail to fill_aead_bd3_mode!\n"); + return ret; + } + + ret = fill_aead_bd3_addr(q, msg, sqe); + if (ret != WD_SUCCESS) { + WD_ERR("fail to fill_aead_bd3_addr!\n"); + return ret; + } + + if (tag) + sqe->tag_l = tag->wcrypto_tag.ctx_id; + + return ret; +} + +static int aead_comb_param_check(struct wcrypto_aead_msg *msg) +{ + int ret; + + if (unlikely(msg->in_bytes + msg->assoc_bytes > MAX_CIPHER_LENGTH)) { + WD_ERR("fail to check input data length!\n"); + return -WD_EINVAL; + } + + if (msg->cmode == WCRYPTO_CIPHER_CCM) { + if (unlikely(msg->auth_bytes < WORD_BYTES || + msg->auth_bytes > AES_BLOCK_SIZE || + msg->auth_bytes % (WORD_BYTES >> 1))) { + WD_ERR("Invalid aead ccm mode auth_bytes!\n"); + return -WD_EINVAL; + } + if (unlikely(msg->assoc_bytes > MAX_CCM_AAD_LEN)) { + WD_ERR("aead ccm mode aasoc_bytes is too long!\n"); + return -WD_EINVAL; + } + return WD_SUCCESS; + } + if (msg->cmode == WCRYPTO_CIPHER_GCM) { + if (unlikely(msg->auth_bytes < U64_DATA_BYTES || + msg->auth_bytes > AES_BLOCK_SIZE)) { + WD_ERR("Invalid aead gcm mode auth_bytes!\n"); + return -WD_EINVAL; + } + return WD_SUCCESS; + } + + /* CCM/GCM support 0 in_bytes, but others not support */ + if (unlikely(msg->in_bytes == 0)) { + WD_ERR("aead in_bytes is zero!\n"); + return -WD_EINVAL; + } + + if (unlikely(msg->auth_bytes != AES_BLOCK_SIZE && + msg->auth_bytes != AES_BLOCK_SIZE << 1)) { + WD_ERR("Invalid aead auth_bytes!\n"); + return -WD_EINVAL; + } + + if (unlikely(msg->akey_bytes & WORD_ALIGNMENT_MASK)) { + WD_ERR("Invalid aead auth key bytes!\n"); + return -WD_EINVAL; + } + + switch (msg->calg) { + case WCRYPTO_CIPHER_SM4: + case WCRYPTO_CIPHER_AES: + ret = sm4_aes_mode_check(msg->cmode); + break; + default: + return -WD_EINVAL; + } + + return ret; +} + +int qm_fill_aead_bd3_sqe(void *message, struct qm_queue_info *info, __u16 i) +{ + struct wcrypto_aead_msg *msg = message; + struct wcrypto_aead_tag *tag = (void *)(uintptr_t)msg->usr_data; + struct wd_queue *q = info->q; + struct hisi_sec_bd3_sqe *sqe; + uintptr_t temp; + int ret; + + ret = aead_comb_param_check(msg); + if (ret) { + WD_ERR("Invalid aead cipher alg = %hhu and mode = %hhu combination\n", + msg->calg, msg->cmode); + return ret; + } + + temp = (uintptr_t)info->sq_base + i * info->sqe_size; + sqe = (struct hisi_sec_bd3_sqe *)temp; + + memset(sqe, 0, sizeof(struct hisi_sec_bd3_sqe)); + + fill_bd3_addr_type(msg->data_fmt, sqe); + + ret = fill_aead_bd3(q, sqe, msg, tag); + if (ret != WD_SUCCESS) + return ret; + + info->req_cache[i] = msg; + +#ifdef DEBUG_LOG + sec_dump_bd((unsigned char *)sqe, SQE_BYTES_NUMS); +#endif + + return ret; +} + +static void parse_aead_bd3(struct wd_queue *q, struct hisi_sec_bd3_sqe *sqe3, + struct wcrypto_aead_msg *msg) +{ + __u8 mac[AEAD_IV_MAX_BYTES] = { 0 }; + __u64 dma_addr; + int ret; + + if (sqe3->done != SEC_HW_TASK_DONE || sqe3->error_type || + sqe3->icv == SEC_HW_ICV_ERR) { + WD_ERR("SEC BD3 aead fail! done=0x%x, etype=0x%x, icv=0x%x\n", + sqe3->done, sqe3->error_type, sqe3->icv); + msg->result = WD_IN_EPARA; + } else { + msg->result = WD_SUCCESS; + } + + /* + * We obtain a memory from IV SGL as a temporary address space for MAC, + * After the encryption is completed, copy the data from this temporary + * address space to dst. + */ + if (msg->data_fmt == WD_SGL_BUF && + msg->op_type == WCRYPTO_CIPHER_ENCRYPTION_DIGEST) { + ret = wd_sgl_cp_to_pbuf((struct wd_sgl *)msg->iv, + AEAD_IV_MAX_BYTES, + (void *)mac, msg->auth_bytes); + if (ret) + return; + ret = wd_sgl_cp_from_pbuf((struct wd_sgl *)msg->out, + msg->out_bytes - msg->auth_bytes, + (void *)mac, msg->auth_bytes); + if (ret) + return; + } + + dma_addr = DMA_ADDR(sqe3->data_src_addr_h, sqe3->data_src_addr_l); + drv_iova_unmap(q, msg->in, (void *)(uintptr_t)dma_addr, msg->in_bytes); + dma_addr = DMA_ADDR(sqe3->data_dst_addr_h, sqe3->data_dst_addr_l); + drv_iova_unmap(q, msg->out, (void *)(uintptr_t)dma_addr, msg->out_bytes); + unmap_addr(q, msg->ckey, msg->ckey_bytes, sqe3->c_key_addr_l, + sqe3->c_key_addr_h, msg->data_fmt); + unmap_addr(q, msg->akey, msg->akey_bytes, sqe3->auth_key_iv.a_key_addr_l, + sqe3->auth_key_iv.a_key_addr_h, msg->data_fmt); + unmap_addr(q, msg->iv, msg->iv_bytes, sqe3->ipsec_scene.c_ivin_addr_l, + sqe3->ipsec_scene.c_ivin_addr_h, msg->data_fmt); + unmap_addr(q, msg->aiv, msg->iv_bytes, sqe3->auth_key_iv.a_ivin_addr_l, + sqe3->auth_key_iv.a_ivin_addr_h, msg->data_fmt); +} + +/* + * According to wcrypto_aead_poll(), the return number mean: + * 0: parse failed + * 1: parse a BD successfully + */ +int qm_parse_aead_bd3_sqe(void *msg, const struct qm_queue_info *info, + __u16 i, __u16 usr) +{ + struct wcrypto_aead_msg *aead_msg = info->req_cache[i]; + struct hisi_sec_bd3_sqe *sqe = msg; + struct wd_queue *q = info->q; + + if (unlikely(!aead_msg)) { + WD_ERR("info->req_cache is null at index:%hu\n", i); + return 0; + } + + if (sqe->type == BD_TYPE3) { + if (usr && sqe->tag_l != usr) + return 0; + parse_aead_bd3(q, sqe, aead_msg); + } else { + WD_ERR("SEC BD Type error\n"); + aead_msg->result = WD_IN_EPARA; + } + +#ifdef DEBUG_LOG + sec_dump_bd((unsigned char *)sqe, SQE_BYTES_NUMS); +#endif + + return 1; +} + +static void parse_digest_bd3(struct wd_queue *q, struct hisi_sec_bd3_sqe *sqe, + struct wcrypto_digest_msg *digest_msg) +{ + __u64 dma_addr; + + if (sqe->done != SEC_HW_TASK_DONE || sqe->error_type) { + WD_ERR("SEC BD3 %s fail!done=0x%x, etype=0x%x\n", "digest", + sqe->done, sqe->error_type); + digest_msg->result = WD_IN_EPARA; + } else { + digest_msg->result = WD_SUCCESS; + } + + dma_addr = DMA_ADDR(sqe->data_src_addr_h, sqe->data_src_addr_l); + drv_iova_unmap(q, digest_msg->in, (void *)(uintptr_t)dma_addr, + digest_msg->in_bytes); + /* out = mac, so 'out' format is as same as 'mac', which is pbuffer */ + unmap_addr(q, digest_msg->out, digest_msg->out_bytes, sqe->mac_addr_l, + sqe->mac_addr_h, digest_msg->data_fmt); + if (digest_msg->mode == WCRYPTO_DIGEST_HMAC) + unmap_addr(q, digest_msg->key, digest_msg->key_bytes, + sqe->auth_key_iv.a_key_addr_l, + sqe->auth_key_iv.a_key_addr_h, digest_msg->data_fmt); +} + +int qm_parse_digest_bd3_sqe(void *msg, const struct qm_queue_info *info, + __u16 i, __u16 usr) +{ + struct wcrypto_digest_msg *digest_msg = info->req_cache[i]; + struct hisi_sec_bd3_sqe *sqe = msg; + struct wd_queue *q = info->q; + + if (unlikely(!digest_msg)) { + WD_ERR("info->req_cache is null at index:%hu\n", i); + return 0; + } + + if (sqe->type == BD_TYPE3) { + if (usr && sqe->tag_l != usr) + return 0; + parse_digest_bd3(q, sqe, digest_msg); + } else { + WD_ERR("SEC Digest BD Type error\n"); + digest_msg->result = WD_IN_EPARA; + } + +#ifdef DEBUG_LOG + sec_dump_bd((unsigned int *)sqe, SQE_BYTES_NUMS); +#endif + + return 1; +} + +static int fill_aead_bd2_alg(struct wcrypto_aead_msg *msg, + struct hisi_sec_sqe *sqe) +{ + __u8 c_key_len = 0; + int ret = WD_SUCCESS; + + switch (msg->calg) { + case WCRYPTO_CIPHER_AES: + sqe->type2.c_alg = C_ALG_AES; + ret = get_aes_c_key_len(msg->cmode, msg->ckey_bytes, &c_key_len); + sqe->type2.c_key_len = c_key_len; + break; + default: + WD_ERR("Invalid cipher type!\n"); + return -WD_EINVAL; + } + + /* CCM/GCM this region is set to 0 */ + if (msg->cmode == WCRYPTO_CIPHER_CCM || + msg->cmode == WCRYPTO_CIPHER_GCM) + return ret; + + sqe->type2.mac_len = msg->auth_bytes / SEC_SQE_LEN_RATE; + sqe->type2.a_key_len = msg->akey_bytes / SEC_SQE_LEN_RATE; + + if (msg->dalg == WCRYPTO_SHA1 || msg->dalg == WCRYPTO_SHA256 || + msg->dalg == WCRYPTO_SHA512) { + sqe->type2.a_alg = g_hmac_a_alg[msg->dalg]; + } else { + WD_ERR("Invalid digest type!\n"); + ret = -WD_EINVAL; + } + + return ret; +} + +static int fill_aead_bd2_mode(struct wcrypto_aead_msg *msg, + struct hisi_sec_sqe *sqe) +{ + int ret = WD_SUCCESS; + + if (msg->op_type == WCRYPTO_CIPHER_ENCRYPTION_DIGEST) { + sqe->cipher = CIPHER_ENCRYPT; + sqe->auth = AUTH_MAC_CALCULATE; + sqe->seq = WCRYPTO_CIPHER_THEN_DIGEST; + } else if (msg->op_type == WCRYPTO_CIPHER_DECRYPTION_DIGEST) { + sqe->cipher = CIPHER_DECRYPT; + sqe->auth = AUTH_MAC_VERIFY; + sqe->seq = WCRYPTO_DIGEST_THEN_CIPHER; + } else { + WD_ERR("Invalid cipher op type!\n"); + return -WD_EINVAL; + } + + switch (msg->cmode) { + case WCRYPTO_CIPHER_ECB: + sqe->type2.c_mode = C_MODE_ECB; + break; + case WCRYPTO_CIPHER_CBC: + sqe->type2.c_mode = C_MODE_CBC; + break; + case WCRYPTO_CIPHER_CCM: + sqe->type2.c_mode = C_MODE_CCM; + sqe->auth = NO_AUTH; + sqe->type2.a_len = msg->assoc_bytes; + sqe->type2.c_icv_len = msg->auth_bytes; + break; + case WCRYPTO_CIPHER_GCM: + sqe->type2.c_mode = C_MODE_GCM; + sqe->auth = NO_AUTH; + sqe->type2.a_len = msg->assoc_bytes; + sqe->type2.c_icv_len = msg->auth_bytes; + break; + default: + WD_ERR("Invalid cipher cmode type!\n"); + ret = -WD_EINVAL; + } + + return ret; +} + +static int fill_aead_bd2_addr_src(struct wd_queue *q, + struct wcrypto_aead_msg *msg, struct hisi_sec_sqe *sqe) +{ + uintptr_t phy1, phy2; + + phy1 = (uintptr_t)drv_iova_map(q, msg->in, msg->in_bytes); + if (unlikely(!phy1)) { + WD_ERR("fail to get message in dma address!\n"); + return -WD_ENOMEM; + } + sqe->type2.data_src_addr_l = (__u32)(phy1 & QM_L32BITS_MASK); + sqe->type2.data_src_addr_h = HI_U32(phy1); + + if (msg->op_type == WCRYPTO_CIPHER_DECRYPTION_DIGEST && + msg->data_fmt == WD_FLAT_BUF) { + phy2 = phy1 + msg->assoc_bytes + msg->in_bytes; + sqe->type2.mac_addr_l = (__u32)(phy2 & QM_L32BITS_MASK); + sqe->type2.mac_addr_h = HI_U32(phy2); + } + + return WD_SUCCESS; +} + +static int fill_aead_bd2_addr_dst(struct wd_queue *q, + struct wcrypto_aead_msg *msg, struct hisi_sec_sqe *sqe) +{ + uintptr_t phy1, phy2; + + phy1 = (uintptr_t)drv_iova_map(q, msg->out, msg->out_bytes); + if (unlikely(!phy1)) { + WD_ERR("fail to get message out dma address!\n"); + return -WD_ENOMEM; + } + sqe->type2.data_dst_addr_l = (__u32)(phy1 & QM_L32BITS_MASK); + sqe->type2.data_dst_addr_h = HI_U32(phy1); + + if (msg->op_type == WCRYPTO_CIPHER_ENCRYPTION_DIGEST && + msg->data_fmt == WD_FLAT_BUF) { + phy2 = phy1 + msg->out_bytes - msg->auth_bytes; + sqe->type2.mac_addr_l = (__u32)(phy2 & QM_L32BITS_MASK); + sqe->type2.mac_addr_h = HI_U32(phy2); + } + + return WD_SUCCESS; +} + +static int aead_bd2_map_iv_mac(struct wd_queue *q, struct wcrypto_aead_msg *msg, + struct hisi_sec_sqe *sqe) +{ + __u8 mac[AEAD_IV_MAX_BYTES] = { 0 }; + uintptr_t phy, phy_mac; + void *p; + int ret; + + /* + * 'msg->iv' use pBuffer, so when 'data_fmt' is sgl, we use its + * first buffer as pBuffer, and 'buf_sz > key_sz' is needed. + */ + if (msg->data_fmt == WD_SGL_BUF) { + if (unlikely(!msg->iv)) + return -WD_ENOMEM; + p = drv_get_sgl_pri((struct wd_sgl *)msg->iv); + phy = ((struct hisi_sgl *)p)->sge_entries[0].buf; + } else { + phy = (uintptr_t)drv_iova_map(q, msg->iv, msg->iv_bytes); + } + if (unlikely(!phy)) { + WD_ERR("Get key dma address fail!\n"); + return -WD_ENOMEM; + } + + sqe->type2.c_ivin_addr_l = (__u32)(phy & QM_L32BITS_MASK); + sqe->type2.c_ivin_addr_h = HI_U32(phy); + + if (msg->data_fmt == WD_SGL_BUF) { + if (msg->op_type == WCRYPTO_CIPHER_DECRYPTION_DIGEST) { + /* + *'MAC' is at the end of 'in', as it is not easy to get + * 'MAC' dma address, so when we do decrypt, we copy + * 'MAC' to the end of 'IV'. + */ + ret = wd_sgl_cp_to_pbuf((struct wd_sgl *)msg->in, + msg->assoc_bytes + msg->in_bytes, + (void *)mac, msg->auth_bytes); + if (ret) + return ret; + + ret = wd_sgl_cp_from_pbuf((struct wd_sgl *)msg->iv, + AEAD_IV_MAX_BYTES, + (void *)mac, msg->auth_bytes); + if (ret) + return ret; + } + + phy_mac = phy + AEAD_IV_MAX_BYTES; + sqe->type2.mac_addr_l = (__u32)(phy_mac & QM_L32BITS_MASK); + sqe->type2.mac_addr_h = HI_U32(phy_mac); + } + + return WD_SUCCESS; +} + +/* + * As 'MAC' needs an continuous memory, + * When do decrypt: + * 'MAC' dma is at the tail of 'out' when use pbuffer; + * 'MAC' dma is at the tail of 'iv' when use sgl; + * When do encrypt: + * 'MAC' dma is at the tail of 'in' when use pbuffer; + * 'MAC' dma is at the tail of 'iv' when use sgl; + */ +static int fill_aead_bd2_addr(struct wd_queue *q, + struct wcrypto_aead_msg *msg, struct hisi_sec_sqe *sqe) +{ + uintptr_t phy; + int ret; + + ret = fill_aead_bd2_addr_src(q, msg, sqe); + if (unlikely(ret)) + return ret; + + ret = fill_aead_bd2_addr_dst(q, msg, sqe); + if (unlikely(ret)) + goto map_out_error; + + ret = map_addr(q, msg->ckey, msg->ckey_bytes, &sqe->type2.c_key_addr_l, + &sqe->type2.c_key_addr_h, msg->data_fmt); + if (unlikely(ret)) + goto map_ckey_error; + + ret = map_addr(q, msg->akey, msg->akey_bytes, &sqe->type2.a_key_addr_l, + &sqe->type2.a_key_addr_h, msg->data_fmt); + if (unlikely(ret)) + goto map_akey_error; + + ret = aead_bd2_map_iv_mac(q, msg, sqe); + if (unlikely(ret)) + goto map_civ_error; + + /* CCM/GCM should init a_iv */ + set_aead_auth_iv(msg); + + ret = map_addr(q, msg->aiv, msg->iv_bytes, &sqe->type2.a_ivin_addr_l, + &sqe->type2.a_ivin_addr_h, msg->data_fmt); + if (unlikely(ret)) + goto map_aiv_error; + + return WD_SUCCESS; + +map_aiv_error: + unmap_addr(q, msg->iv, msg->iv_bytes, sqe->type2.c_ivin_addr_l, + sqe->type2.c_ivin_addr_h, msg->data_fmt); +map_civ_error: + unmap_addr(q, msg->akey, msg->akey_bytes, sqe->type2.a_key_addr_l, + sqe->type2.a_key_addr_h, msg->data_fmt); +map_akey_error: + unmap_addr(q, msg->ckey, msg->ckey_bytes, sqe->type2.c_key_addr_l, + sqe->type2.c_key_addr_h, msg->data_fmt); +map_ckey_error: + phy = DMA_ADDR(sqe->type2.data_dst_addr_h, + sqe->type2.data_dst_addr_l); + drv_iova_unmap(q, msg->out, (void *)(uintptr_t)phy, msg->out_bytes); +map_out_error: + phy = DMA_ADDR(sqe->type2.data_src_addr_h, + sqe->type2.data_src_addr_l); + drv_iova_unmap(q, msg->in, (void *)(uintptr_t)phy, msg->in_bytes); + return -WD_ENOMEM; +} + +static int aead_param_len_check(struct wcrypto_aead_msg *msg) +{ + if (unlikely(msg->in_bytes == 0)) { + WD_ERR("fail to support input 0 length\n"); + return -WD_EINVAL; + } + + if (msg->cmode == WCRYPTO_CIPHER_CBC && + (msg->in_bytes & (AES_BLOCK_SIZE - 1))) { + WD_ERR("failed to check input data length!\n"); + return -WD_EINVAL; + } + + return 0; +} + +static int fill_aead_bd2(struct wd_queue *q, struct hisi_sec_sqe *sqe, + struct wcrypto_aead_msg *msg, struct wcrypto_aead_tag *tag) +{ + int ret; + + sqe->type = BD_TYPE2; + sqe->scene = SCENE_IPSEC; + sqe->de = DATA_DST_ADDR_ENABLE; + + fill_bd_addr_type(msg->data_fmt, sqe); + + ret = aead_param_len_check(msg); + if (unlikely(ret)) + return ret; + + sqe->type2.c_len = msg->in_bytes; + sqe->type2.cipher_src_offset = msg->assoc_bytes; + + sqe->type2.a_len = msg->in_bytes + msg->assoc_bytes; + + ret = fill_aead_bd2_alg(msg, sqe); + if (ret != WD_SUCCESS) { + WD_ERR("fill_cipher_bd2_alg fail!\n"); + return ret; + } + + ret = fill_aead_bd2_mode(msg, sqe); + if (ret != WD_SUCCESS) { + WD_ERR("fill_cipher_bd2_mode fail!\n"); + return ret; + } + + ret = fill_aead_bd2_addr(q, msg, sqe); + if (ret != WD_SUCCESS) + return ret; + + if (tag) + sqe->type2.tag = tag->wcrypto_tag.ctx_id; + + return ret; +} + +int qm_fill_aead_sqe(void *message, struct qm_queue_info *info, __u16 i) +{ + struct wcrypto_aead_msg *msg = message; + struct wcrypto_aead_tag *tag = (void *)(uintptr_t)msg->usr_data; + struct wd_queue *q = info->q; + struct hisi_sec_sqe *sqe; + uintptr_t temp; + int ret; + + ret = aead_comb_param_check(msg); + if (ret) { + WD_ERR("Invalid aead cipher alg = %hhu and mode = %hhu combination\n", + msg->calg, msg->cmode); + return ret; + } + + temp = (uintptr_t)info->sq_base + i * info->sqe_size; + sqe = (struct hisi_sec_sqe *)temp; + + memset(sqe, 0, sizeof(struct hisi_sec_sqe)); + + ret = fill_aead_bd2(q, sqe, msg, tag); + if (ret != WD_SUCCESS) + return ret; + + info->req_cache[i] = msg; + +#ifdef DEBUG_LOG + sec_dump_bd((unsigned char *)sqe, SQE_BYTES_NUMS); +#endif + + return ret; +} + +static void parse_aead_bd2(struct wd_queue *q, struct hisi_sec_sqe *sqe, + struct wcrypto_aead_msg *msg) +{ + __u8 mac[64] = { 0 }; + __u64 dma_addr; + int ret; + + if (sqe->type2.done != SEC_HW_TASK_DONE || sqe->type2.error_type || + sqe->type2.icv == SEC_HW_ICV_ERR) { + WD_ERR("SEC BD2 aead fail! done=0x%x, etype=0x%x, icv=0x%x\n", + sqe->type2.done, sqe->type2.error_type, sqe->type2.icv); + msg->result = WD_IN_EPARA; + } else { + msg->result = WD_SUCCESS; + } + + /* + * We obtain a memory from IV SGL as a temporary address space for MAC, + * After the encryption is completed, copy the data from this temporary + * address space to dst. + */ + if (msg->data_fmt == WD_SGL_BUF && + msg->op_type == WCRYPTO_CIPHER_ENCRYPTION_DIGEST) { + ret = wd_sgl_cp_to_pbuf((struct wd_sgl *)msg->iv, + AEAD_IV_MAX_BYTES, + (void *)mac, msg->auth_bytes); + if (ret) + return; + ret = wd_sgl_cp_from_pbuf((struct wd_sgl *)msg->out, + msg->out_bytes - msg->auth_bytes, + (void *)mac, msg->auth_bytes); + if (ret) + return; + } + + dma_addr = DMA_ADDR(sqe->type2.data_src_addr_h, + sqe->type2.data_src_addr_l); + drv_iova_unmap(q, msg->in, (void *)(uintptr_t)dma_addr, + msg->in_bytes); + dma_addr = DMA_ADDR(sqe->type2.data_dst_addr_h, + sqe->type2.data_dst_addr_l); + drv_iova_unmap(q, msg->out, (void *)(uintptr_t)dma_addr, + msg->out_bytes); + unmap_addr(q, msg->ckey, msg->ckey_bytes, sqe->type2.c_key_addr_l, + sqe->type2.c_key_addr_h, msg->data_fmt); + unmap_addr(q, msg->akey, msg->akey_bytes, sqe->type2.a_key_addr_l, + sqe->type2.a_key_addr_h, msg->data_fmt); + unmap_addr(q, msg->iv, msg->iv_bytes, sqe->type2.c_ivin_addr_l, + sqe->type2.c_ivin_addr_h, msg->data_fmt); + unmap_addr(q, msg->aiv, msg->iv_bytes, sqe->type2.a_ivin_addr_l, + sqe->type2.a_ivin_addr_h, msg->data_fmt); +} + +/* + * According to wcrypto_aead_poll(), the return number mean: + * 0: parse failed + * 1: parse a BD successfully + */ +int qm_parse_aead_sqe(void *msg, const struct qm_queue_info *info, + __u16 i, __u16 usr) +{ + struct wcrypto_aead_msg *aead_msg = info->req_cache[i]; + struct hisi_sec_sqe *sqe = msg; + struct wd_queue *q = info->q; + + if (unlikely(!aead_msg)) { + WD_ERR("info->req_cache is null at index:%hu\n", i); + return 0; + } + + if (sqe->type == BD_TYPE2) { + if (usr && sqe->type2.tag != usr) + return 0; + parse_aead_bd2(q, sqe, aead_msg); + } else { + WD_ERR("SEC BD Type error\n"); + aead_msg->result = WD_IN_EPARA; + } + +#ifdef DEBUG_LOG + sec_dump_bd((unsigned char *)sqe, SQE_BYTES_NUMS); +#endif + + return 1; +} diff --git a/uadk/v1/drv/hisi_sec_udrv.h b/uadk/v1/drv/hisi_sec_udrv.h new file mode 100644 index 0000000..9c0da47 --- /dev/null +++ b/uadk/v1/drv/hisi_sec_udrv.h @@ -0,0 +1,546 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#ifndef __HISI_SEC_DRV_H__ +#define __HISI_SEC_DRV_H__ + +#include +#include "config.h" +#include "v1/wd.h" +#include "v1/wd_util.h" +#include "v1/wd_cipher.h" +#include "v1/wd_digest.h" +#include "v1/wd_aead.h" +#include "v1/drv/hisi_qm_udrv.h" + +/* The max BD cipher length is 16M-512B */ +#define MAX_CIPHER_LENGTH 16776704 +#define SEC_SQE_LEN_RATE 4 + +struct hisi_sec_sqe_type1 { + __u32 rsvd2:6; + __u32 ci_gen:2; + __u32 ai_gen:2; + __u32 rsvd1:7; + __u32 c_key_type:2; + __u32 a_key_type:2; + __u32 rsvd0:10; + __u32 inveld:1; + __u32 mac_len:5; + __u32 a_key_len:6; + __u32 a_alg:6; + __u32 rsvd3:15; + __u32 c_icv_len:6; + __u32 c_width:3; + __u32 c_key_len:3; + __u32 c_mode:4; + __u32 c_alg:4; + __u32 rsvd4:12; + __u32 dw4; + __u32 dw5; + __u32 auth_src_offset:16; + __u32 cipher_src_offset:16; + __u32 gran_num:16; + __u32 rsvd5:16; + __u32 src_skip_data_len:24; + __u32 rsvd6:8; + __u32 dst_skip_data_len:24; + __u32 rsvd7:8; + __u32 tag:16; + __u32 rsvd8:16; + __u32 gen_page_pad_ctrl:4; + __u32 gen_grd_ctrl:4; + __u32 gen_ver_ctrl:4; + __u32 gen_app_ctrl:4; + __u32 gen_ver_val:8; + __u32 gen_app_val:8; + __u32 private_info; + __u32 gen_ref_ctrl:4; + __u32 page_pad_type:2; + __u32 rsvd9:2; + __u32 chk_grd_ctrl:4; + __u32 chk_ref_ctrl:4; + __u32 block_size:16; + __u32 lba_l; + __u32 lba_h; + __u32 a_key_addr_l; + __u32 a_key_addr_h; + __u32 mac_addr_l; + __u32 mac_addr_h; + __u32 c_ivin_addr_l; + __u32 c_ivin_addr_h; + __u32 c_key_addr_l; + __u32 c_key_addr_h; + __u32 data_src_addr_l; + __u32 data_src_addr_h; + __u32 data_dst_addr_l; + __u32 data_dst_addr_h; + __u32 done:1; + __u32 icv:3; + __u32 rsvd11:3; + __u32 flag:4; + __u32 dif_check:3; + __u32 rsvd10:2; + __u32 error_type:8; + __u32 warning_type:8; + __u32 dw29; + __u32 dw30; + __u32 dw31; +}; + +struct hisi_sec_sqe_type2 { + __u32 nonce_len:4; + __u32 huk:1; + __u32 key_s:1; + __u32 ci_gen:2; + __u32 ai_gen:2; + __u32 a_pad:2; + __u32 c_s:2; + __u32 rsvd1:2; + __u32 rhf:1; + __u32 c_key_type:2; + __u32 a_key_type:2; + __u32 write_frame_len:3; + __u32 cal_iv_addr_en:1; + __u32 tls_up:1; + __u32 rsvd0:5; + __u32 inveld:1; + __u32 mac_len:5; + __u32 a_key_len:6; + __u32 a_alg:6; + __u32 rsvd3:15; + __u32 c_icv_len:6; + __u32 c_width:3; + __u32 c_key_len:3; + __u32 c_mode:4; + __u32 c_alg:4; + __u32 rsvd4:12; + __u32 a_len:24; + __u32 iv_offset_l:8; + __u32 c_len:24; + __u32 iv_offset_h:8; + __u32 auth_src_offset:16; + __u32 cipher_src_offset:16; + __u32 cs_ip_header_offset:16; + __u32 cs_udp_header_offset:16; + __u32 pass_word_len:16; + __u32 dk_len:16; + __u32 salt3:8; + __u32 salt2:8; + __u32 salt1:8; + __u32 salt0:8; + __u32 tag:16; + __u32 rsvd5:16; + __u32 c_pad_type:4; + __u32 c_pad_len:8; + __u32 c_pad_data_type:4; + __u32 c_pad_len_field:2; + __u32 rsvd6:14; + __u32 long_a_data_len_l; + __u32 long_a_data_len_h; + __u32 a_ivin_addr_l; + __u32 a_ivin_addr_h; + __u32 a_key_addr_l; + __u32 a_key_addr_h; + __u32 mac_addr_l; + __u32 mac_addr_h; + __u32 c_ivin_addr_l; + __u32 c_ivin_addr_h; + __u32 c_key_addr_l; + __u32 c_key_addr_h; + __u32 data_src_addr_l; + __u32 data_src_addr_h; + __u32 data_dst_addr_l; + __u32 data_dst_addr_h; + __u32 done:1; + __u32 icv:3; + __u32 rsvd11:3; + __u32 flag:4; + __u32 rsvd10:5; + __u32 error_type:8; + __u32 warning_type:8; + __u32 mac_i3:8; + __u32 mac_i2:8; + __u32 mac_i1:8; + __u32 mac_i0:8; + __u32 check_sum_i:16; + __u32 tls_pad_len_i:8; + __u32 rsvd12:8; + __u32 counter; +}; + +struct hisi_sec_sqe { + __u32 type:4; + __u32 cipher:2; + __u32 auth:2; + __u32 seq:1; + __u32 de:2; + __u32 scene:4; + __u32 src_addr_type:3; + __u32 dst_addr_type:3; + __u32 mac_addr_type:3; + __u32 rsvd0:8; + union { + struct hisi_sec_sqe_type1 type1; /* storage scene */ + struct hisi_sec_sqe_type2 type2; /* the other scene */ + }; +}; + +struct bd3_auth_key_iv { + __u32 a_key_addr_l; + __u32 a_key_addr_h; + __u32 a_ivin_addr_l; + __u32 a_ivin_addr_h; + __u32 rsvd0; + __u32 rsvd1; +}; + +struct bd3_skip_data { + __u32 c_iv_a_key_l; + __u32 c_iv_a_key_h; + __u32 rsvd0; + __u32 gran_num:16; + __u32 rsvd1:16; + __u32 src_skip_data_len:25; + __u32 rsvd2:7; + __u32 dst_skip_data_len:25; + __u32 rsvd3:7; +}; + +struct bd3_ipsec_scene { + __u32 c_ivin_addr_l; + __u32 c_ivin_addr_h; + __u32 c_s:2; + __u32 deal_esp_ah:4; + __u32 protocol_type:4; + __u32 mode:2; + __u32 ip_type:2; + __u32 mac_sel:1; + __u32 rsvd0:1; + __u32 next_header:8; + __u32 pad_len:8; + __u32 iv_offset:16; + __u32 rsvd1:16; + __u32 cs_ip_header_offset:16; + __u32 cs_udp_header_offset:16; +}; + +struct bd3_pbkdf2_scene { + __u32 c_ivin_addr_l; + __u32 c_ivin_addr_h; + __u32 pbkdf2_salt_len:24; + __u32 rsvd0:8; + __u32 c_num:24; + __u32 rsvd1:8; + __u32 pass_word_len:16; + __u32 dk_len:16; +}; + +struct bd3_stream_scene { + __u32 c_ivin_addr_l; + __u32 c_ivin_addr_h; + __u32 long_a_data_len_l; + __u32 long_a_data_len_h; + __u32 auth_pad:2; + __u32 stream_protocol:3; + __u32 mac_sel:1; + __u32 rsvd0:2; + __u32 plaintext_type:8; + __u32 pad_len_1p3:16; +}; + +struct bd3_dtls_scene { + __u32 c_ivin_addr_l; + __u32 c_ivin_addr_h; + __u32 sn_l; + __u32 sn_h; + __u32 c_pad_type:4; + __u32 c_pad_len:8; + __u32 c_pad_data_type:4; + __u32 c_pad_len_field:2; + __u32 tls_len_update:1; + __u32 rsvd0:13; +}; + +struct bd3_tls1p3_scene { + __u32 c_ivin_addr_l; + __u32 c_ivin_addr_h; + __u32 a_ivin_addr_l; + __u32 a_ivin_addr_h; + __u32 deal_tls_1p3:3; + __u32 mac_sel:1; + __u32 rsvd0:4; + __u32 plaintext_type:8; + __u32 pad_len_1p3:16; +}; + +struct bd3_storage_scene { + __u32 lba_l; + __u32 lba_h; + __u32 gen_page_pad_ctrl:4; + __u32 gen_grd_ctrl:4; + __u32 gen_ver_ctrl:4; + __u32 gen_app_ctrl:4; + __u32 gen_ver_val:8; + __u32 gen_app_val:8; + __u32 private_info; + __u32 gen_ref_ctrl:4; + __u32 page_pad_type:2; + __u32 pagePadNogen:1; + __u32 pagePadNocheck:1; + __u32 chk_grd_ctrl:4; + __u32 chk_ref_ctrl:4; + __u32 block_size:16; +}; + +struct bd3_no_scene { + __u32 c_ivin_addr_l; + __u32 c_ivin_addr_h; + __u32 rsvd0; + __u32 rsvd1; + __u32 rsvd2; +}; + +struct bd3_check_sum { + __u32 rsvd0:8; + __u32 hac_sva_status:8; + __u32 check_sum_i:16; +}; + +struct bd3_tls_type_back { + __u32 tls_1p3_type_back:8; + __u32 hac_sva_status:8; + __u32 pad_len_1p3_back:16; +}; + +/* the kp930 sence */ +struct hisi_sec_bd3_sqe { + __u32 type:4; + __u32 inveld:1; + __u32 scene:4; + __u32 de:2; + __u32 src_addr_type:3; + __u32 dst_addr_type:3; + __u32 mac_addr_type:3; + __u32 rsvd:12; + + __u32 cipher:2; + __u32 ci_gen:2; + __u32 c_icv_len:6; + __u32 c_width:3; + __u32 c_key_len:3; + __u32 c_mode:4; + __u32 c_alg:4; + __u32 nonce_len:4; + __u32 rsv:1; + __u32 cal_iv_addr_en:1; + __u32 seq:1; + __u32 rsvd0:1; + + __u32 tag_l; + __u32 tag_h; + __u32 data_src_addr_l; + __u32 data_src_addr_h; + + union { + struct bd3_auth_key_iv auth_key_iv; + struct bd3_skip_data skip_data; + }; + + __u32 c_key_addr_l; + __u32 c_key_addr_h; + __u32 auth:2; + __u32 ai_gen:2; + __u32 mac_len:5; + __u32 a_key_len:6; + __u32 a_alg:6; + __u32 key_sel:4; + __u32 ctr_counter_mode:2; + __u32 sva_prefetch:1; + __u32 key_wrap_num:3; + __u32 update_key:1; + + __u32 salt3:8; + __u32 salt2:8; + __u32 salt1:8; + __u32 salt0:8; + __u32 auth_src_offset:16; + __u32 cipher_src_offset:16; + __u32 a_len:24; + __u32 auth_key_offset:8; + __u32 c_len:24; + __u32 auth_ivin_offset:8; + __u32 data_dst_addr_l; + __u32 data_dst_addr_h; + __u32 mac_addr_l; + __u32 mac_addr_h; + union { + struct bd3_ipsec_scene ipsec_scene; + struct bd3_pbkdf2_scene pbkdf2_scene; + struct bd3_stream_scene stream_scene; + struct bd3_dtls_scene dtls_scene; + struct bd3_tls1p3_scene tls1p3_scene; + struct bd3_storage_scene storage_scene; + struct bd3_no_scene no_scene; + }; + + __u32 done:1; + __u32 icv:3; + __u32 csc:3; + __u32 flag:4; + __u32 dc:3; + __u32 rsvd10:2; + __u32 error_type:8; + __u32 warning_type:8; + union { + __u32 mac_i; + __u32 kek_key_addr_l; + }; + union { + __u32 kek_key_addr_h; + struct bd3_check_sum check_sum; + struct bd3_tls_type_back tls_type_back; + }; + __u32 counter; +}; + +enum C_ALG { + C_ALG_DES = 0x0, + C_ALG_3DES = 0x1, + C_ALG_AES = 0x2, + C_ALG_SM4 = 0x3, +}; + +enum A_ALG { + A_ALG_SHA1 = 0x0, + A_ALG_SHA256 = 0x1, + A_ALG_MD5 = 0x2, + A_ALG_SHA224 = 0x3, + A_ALG_SHA384 = 0x4, + A_ALG_SHA512 = 0x5, + A_ALG_SHA512_224 = 0x6, + A_ALG_SHA512_256 = 0x7, + A_ALG_HMAC_SHA1 = 0x10, + A_ALG_HMAC_SHA256 = 0x11, + A_ALG_HMAC_MD5 = 0x12, + A_ALG_HMAC_SHA224 = 0x13, + A_ALG_HMAC_SHA384 = 0x14, + A_ALG_HMAC_SHA512 = 0x15, + A_ALG_HMAC_SHA512_224 = 0x16, + A_ALG_HMAC_SHA512_256 = 0x17, + A_ALG_AES_XCBC_MAC_96 = 0x20, + A_ALG_AES_XCBC_PRF_128 = 0x20, + A_ALG_AES_CMAC = 0x21, + A_ALG_AES_GMAC = 0x22, + A_ALG_SM3 = 0x25, + A_ALG_HMAC_SM3 = 0x26 +}; + +enum C_MODE { + C_MODE_ECB = 0x0, + C_MODE_CBC = 0x1, + C_MODE_CFB = 0x2, + C_MODE_OFB = 0x3, + C_MODE_CTR = 0x4, + C_MODE_CCM = 0x5, + C_MODE_GCM = 0x6, + C_MODE_XTS = 0x7, + C_MODE_CBC_CS = 0x9 +}; + +enum CKEY_LEN { + CKEY_LEN_128_BIT = 0x0, + CKEY_LEN_192_BIT = 0x1, + CKEY_LEN_256_BIT = 0x2, + CKEY_LEN_SM4 = 0x0, + CKEY_LEN_DES = 0x1, + CKEY_LEN_3DES_3KEY = 0x1, + CKEY_LEN_3DES_2KEY = 0x3, +}; + +enum { + BD_TYPE1 = 0x1, + BD_TYPE2 = 0x2, + BD_TYPE3 = 0x3, +}; + +enum { + NO_CIPHER, + CIPHER_ENCRYPT, + CIPHER_DECRYPT, + REPORT_COPY, +}; + +enum { + NO_AUTH, + AUTH_MAC_CALCULATE, + AUTH_MAC_VERIFY, +}; + +enum { + DATA_DST_ADDR_DISABLE, + DATA_DST_ADDR_ENABLE, +}; + +enum { + SCENE_NOTHING = 0x0, + SCENE_IPSEC = 0x1, + SCENE_SSL_TLS = 0x3, + SCENE_DTLS = 0x4, + SCENE_STORAGE = 0x5, + SCENE_NAS = 0x6, + SCENE_STREAM = 0x7, + SCENE_PBKDF2 = 0x8, + SCENE_SMB = 0x9, +}; + +enum { + CI_GEN_BY_ADDR = 0x0, + CI_GEN_BY_LBA = 0X3, +}; + +enum { + AI_GEN_INNER, + AI_GEN_IVIN_ADDR, + AI_GEN_CAL_IV_ADDR, + AI_GEN_TRNG, +}; + +enum { + AUTHPAD_PAD, + AUTHPAD_NOPAD, +}; + +int qm_fill_cipher_sqe(void *message, struct qm_queue_info *info, __u16 i); +int qm_fill_digest_sqe(void *message, struct qm_queue_info *info, __u16 i); +int qm_fill_aead_sqe(void *message, struct qm_queue_info *info, __u16 i); +int qm_fill_cipher_bd3_sqe(void *message, struct qm_queue_info *info, __u16 i); +int qm_fill_aead_bd3_sqe(void *message, struct qm_queue_info *info, __u16 i); +int qm_fill_digest_bd3_sqe(void *message, struct qm_queue_info *info, __u16 i); + +int qm_parse_cipher_sqe(void *msg, const struct qm_queue_info *info, + __u16 i, __u16 usr); +int qm_parse_digest_sqe(void *msg, const struct qm_queue_info *info, + __u16 i, __u16 usr); +int qm_parse_aead_sqe(void *msg, const struct qm_queue_info *info, + __u16 i, __u16 usr); +int qm_parse_cipher_bd3_sqe(void *msg, const struct qm_queue_info *info, + __u16 i, __u16 usr); +int qm_parse_aead_bd3_sqe(void *msg, const struct qm_queue_info *info, + __u16 i, __u16 usr); +int qm_parse_digest_bd3_sqe(void *msg, const struct qm_queue_info *info, + __u16 i, __u16 usr); +#endif diff --git a/uadk/v1/drv/hisi_zip_udrv.c b/uadk/v1/drv/hisi_zip_udrv.c new file mode 100644 index 0000000..1dec4d6 --- /dev/null +++ b/uadk/v1/drv/hisi_zip_udrv.c @@ -0,0 +1,887 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "config.h" +#include "v1/wd_util.h" +#include "v1/wd_comp.h" +#include "v1/wd_cipher.h" +#include "v1/drv/hisi_zip_udrv.h" +#include "v1/wd_sgl.h" + +#define BD_TYPE_SHIFT 28 +#define STREAM_FLUSH_SHIFT 25 +#define STREAM_POS_SHIFT 2 +#define STREAM_MODE_SHIFT 1 +#define WINDOWS_SIZE_SHIFT 12 +#define SEQUENCE_SZIE 8 + +#define HW_NEGACOMPRESS 0x0d +#define HW_CRC_ERR 0x10 +#define HW_DECOMP_END 0x13 +#define HW_IN_DATA_DIF_CHECK_ERR 0xf +#define HW_UNCOMP_DIF_CHECK_ERR 0x12 + +#define HW_DECOMP_NO_SPACE 0x01 +#define HW_DECOMP_BLK_NOSTART 0x03 +#define HW_DECOMP_NO_CRC 0x04 +#define ZIP_DIF_LEN 8 +#define ZIP_PAD_LEN 56 +#define MAX_BUFFER_SIZE 0x800000 +#define MAX_ZSTD_INPUT_SIZE 0x20000 +#define ZSTD_LIT_RSV_SIZE 16 +#define ZSTD_FREQ_DATA_SIZE 784 +#define REPCODE_SIZE 12 + +#define CTX_PRIV1_OFFSET 4 +#define CTX_PRIV2_OFFSET 8 +#define CTX_REPCODE1_OFFSET 12 +#define CTX_REPCODE2_OFFSET 24 +#define CTX_BUFFER_OFFSET 64 +#define CTX_HW_REPCODE_OFFSET 784 + +#define get_arrsize(arr) (sizeof(arr) / sizeof(arr[0])) +#define lower_32_bits(phy) ((__u32)((__u64)(phy))) +#define upper_32_bits(phy) ((__u32)((__u64)(phy) >> QM_HADDR_SHIFT)) + +enum { + BD_TYPE, + BD_TYPE3 = 3, +}; + +enum lz77_compress_status { + UNCOMP_BLK, + RLE_BLK, + COMP_BLK, +}; + +struct hisi_zip_sqe_addr { + uintptr_t source_addr; + uintptr_t dest_addr; + uintptr_t ctxbuf_addr; +}; + +struct zip_fill_sqe_ops { + const char *alg_type; + int (*fill_sqe_alg)(void *ssqe, struct wcrypto_comp_msg *msg); + int (*fill_sqe_buffer_size)(void *ssqe, struct wcrypto_comp_msg *msg); + int (*fill_sqe_window_size)(void *ssqe, struct wcrypto_comp_msg *msg); + int (*fill_sqe_addr)(void *ssqe, struct wcrypto_comp_msg *msg, + struct wd_queue *q); + void (*fill_sqe_hw_info)(void *ssqe, struct wcrypto_comp_msg *msg); +}; + +static int fill_zip_comp_alg_v1(struct hisi_zip_sqe *sqe, + struct wcrypto_comp_msg *msg) +{ + switch (msg->alg_type) { + case WCRYPTO_ZLIB: + sqe->dw9 = HW_ZLIB; + break; + case WCRYPTO_GZIP: + sqe->dw9 = HW_GZIP; + break; + default: + return -WD_EINVAL; + } + + return WD_SUCCESS; +} + +static int qm_fill_zip_sqe_get_phy_addr(struct hisi_zip_sqe_addr *addr, + struct wcrypto_comp_msg *msg, + struct wd_queue *q, bool is_lz77) +{ + uintptr_t phy_ctxbuf = 0; + uintptr_t phy_out = 0; + uintptr_t phy_in; + + phy_in = (uintptr_t)drv_iova_map(q, msg->src, msg->in_size); + if (!phy_in) { + WD_ERR("Get zip in buf dma address fail!\n"); + return -WD_ENOMEM; + } + if (!(is_lz77 && msg->data_fmt == WD_SGL_BUF)) { + phy_out = (uintptr_t)drv_iova_map(q, msg->dst, msg->avail_out); + if (!phy_out) { + WD_ERR("Get zip out buf dma address fail!\n"); + goto unmap_phy_in; + } + } + + if (msg->stream_mode == WCRYPTO_COMP_STATEFUL) { + phy_ctxbuf = (uintptr_t)drv_iova_map(q, msg->ctx_buf, + MAX_CTX_RSV_SIZE); + if (!phy_ctxbuf) { + WD_ERR("Get zip ctx buf dma address fail!\n"); + goto unmap_phy_out; + } + } + + addr->source_addr = phy_in; + addr->dest_addr = phy_out; + addr->ctxbuf_addr = phy_ctxbuf + CTX_BUFFER_OFFSET; + + return WD_SUCCESS; + +unmap_phy_out: + if (!(is_lz77 && msg->data_fmt == WD_SGL_BUF)) + drv_iova_unmap(q, msg->dst, (void *)phy_out, msg->avail_out); +unmap_phy_in: + drv_iova_unmap(q, msg->src, (void *)phy_in, msg->in_size); + + return -WD_ENOMEM; +} + +int qm_fill_zip_sqe(void *smsg, struct qm_queue_info *info, __u16 i) +{ + struct hisi_zip_sqe *sqe = (struct hisi_zip_sqe *)info->sq_base + i; + struct wcrypto_comp_msg *msg = smsg; + struct wcrypto_comp_tag *tag = (void *)(uintptr_t)msg->udata; + struct hisi_zip_sqe_addr addr = {0}; + struct wd_queue *q = info->q; + __u8 flush_type; + __u8 data_fmt; + int ret; + + memset((void *)sqe, 0, sizeof(*sqe)); + + ret = fill_zip_comp_alg_v1(sqe, msg); + if (ret) { + WD_ERR("The algorithm is invalid!\n"); + return -WD_EINVAL; + } + + if (unlikely(msg->data_fmt != WD_SGL_BUF && + msg->in_size > MAX_BUFFER_SIZE)) { + WD_ERR("The in_len is out of range in_len(%u)!\n", msg->in_size); + return -WD_EINVAL; + } + if (unlikely(msg->data_fmt != WD_SGL_BUF && + msg->avail_out > MAX_BUFFER_SIZE)) { + WD_ERR("warning: avail_out is out of range (%u), will set 8MB size max!\n", + msg->avail_out); + msg->avail_out = MAX_BUFFER_SIZE; + } + sqe->input_data_length = msg->in_size; + sqe->dest_avail_out = msg->avail_out; + + ret = qm_fill_zip_sqe_get_phy_addr(&addr, msg, q, false); + if (ret) + return ret; + + sqe->source_addr_l = lower_32_bits((__u64)addr.source_addr); + sqe->source_addr_h = upper_32_bits((__u64)addr.source_addr); + sqe->dest_addr_l = lower_32_bits((__u64)addr.dest_addr); + sqe->dest_addr_h = upper_32_bits((__u64)addr.dest_addr); + sqe->stream_ctx_addr_l = lower_32_bits((__u64)addr.ctxbuf_addr); + sqe->stream_ctx_addr_h = upper_32_bits((__u64)addr.ctxbuf_addr); + + flush_type = (msg->flush_type == WCRYPTO_FINISH) ? HZ_FINISH : + HZ_SYNC_FLUSH; + sqe->dw7 |= ((msg->stream_pos << STREAM_POS_SHIFT) | + (msg->stream_mode << STREAM_MODE_SHIFT) | + (flush_type)) << STREAM_FLUSH_SHIFT; + + /* data_fmt: 4'b0000 - Pbuffer, 4'b0001 - SGL */ + data_fmt = (msg->data_fmt == WD_SGL_BUF) ? HISI_SGL_BUF : HISI_FLAT_BUF; + sqe->dw9 |= data_fmt << HZ_BUF_TYPE_SHIFT; + + if (msg->ctx_buf) { + sqe->ctx_dw0 = *(__u32 *)msg->ctx_buf; + sqe->ctx_dw1 = *(__u32 *)(msg->ctx_buf + CTX_PRIV1_OFFSET); + sqe->ctx_dw2 = *(__u32 *)(msg->ctx_buf + CTX_PRIV2_OFFSET); + } + sqe->isize = msg->isize; + sqe->checksum = msg->checksum; + sqe->tag = msg->tag; + if (tag && info->sqe_fill_priv) + info->sqe_fill_priv(sqe, WCRYPTO_COMP, tag->priv); + + info->req_cache[i] = msg; + + return WD_SUCCESS; +} + +static void qm_parse_zip_sqe_set_status(struct wcrypto_comp_msg *recv_msg, + __u32 status, __u16 lstblk, __u16 ctx_st) +{ + if ((status == HW_DECOMP_END) && lstblk) + recv_msg->status = WCRYPTO_DECOMP_END; + else if (status == HW_CRC_ERR) /* deflate type no crc, do normal */ + recv_msg->status = WD_VERIFY_ERR; + else if (status == HW_IN_DATA_DIF_CHECK_ERR) + recv_msg->status = WCRYPTO_SRC_DIF_ERR; + else if (status == HW_UNCOMP_DIF_CHECK_ERR) + recv_msg->status = WCRYPTO_DST_DIF_ERR; + else if (status == HW_NEGACOMPRESS) + recv_msg->status = WCRYPTO_NEGTIVE_COMP_ERR; + + /* deflate type no crc, need return status */ + if (ctx_st == HW_DECOMP_NO_CRC) + recv_msg->status = WCRYPTO_DECOMP_NO_CRC; + /* last block no space, need resend null size req */ + else if (ctx_st == HW_DECOMP_NO_SPACE) + recv_msg->status = WCRYPTO_DECOMP_END_NOSPACE; + else if (ctx_st == HW_DECOMP_BLK_NOSTART && lstblk) + recv_msg->status = WCRYPTO_DECOMP_BLK_NOSTART; +} + +int qm_parse_zip_sqe(void *hw_msg, const struct qm_queue_info *info, + __u16 i, __u16 usr) +{ + struct wcrypto_comp_msg *recv_msg = info->req_cache[i]; + struct hisi_zip_sqe *sqe = hw_msg; + __u16 ctx_st = sqe->ctx_dw0 & HZ_CTX_ST_MASK; + __u16 lstblk = sqe->dw3 & HZ_LSTBLK_MASK; + __u32 status = sqe->dw3 & HZ_STATUS_MASK; + __u32 type = sqe->dw9 & HZ_REQ_TYPE_MASK; + uintptr_t phy_in, phy_out, phy_ctxbuf; + struct wd_queue *q = info->q; + + if (unlikely(!recv_msg)) { + WD_ERR("info->req_cache is null at index:%hu\n", i); + return 0; + } + + if (usr && sqe->tag != usr) + return 0; + + if (status != 0 && status != HW_NEGACOMPRESS && + status != HW_CRC_ERR && status != HW_DECOMP_END) { + WD_ERR("bad status(ctx_st=0x%x, s=0x%x, t=%u)\n", + ctx_st, status, type); + recv_msg->status = WD_IN_EPARA; + } else { + recv_msg->status = 0; + } + recv_msg->in_cons = sqe->consumed; + recv_msg->produced = sqe->produced; + if (recv_msg->ctx_buf) { + *(__u32 *)recv_msg->ctx_buf = sqe->ctx_dw0; + *(__u32 *)(recv_msg->ctx_buf + CTX_PRIV1_OFFSET) = sqe->ctx_dw1; + *(__u32 *)(recv_msg->ctx_buf + CTX_PRIV2_OFFSET) = sqe->ctx_dw2; + } + recv_msg->isize = sqe->isize; + recv_msg->checksum = sqe->checksum; + + phy_in = DMA_ADDR(sqe->source_addr_h, sqe->source_addr_l); + drv_iova_unmap(q, recv_msg->src, (void *)phy_in, recv_msg->in_size); + phy_out = DMA_ADDR(sqe->dest_addr_h, sqe->dest_addr_l); + drv_iova_unmap(q, recv_msg->dst, (void *)phy_out, recv_msg->avail_out); + if (recv_msg->ctx_buf) { + phy_ctxbuf = DMA_ADDR(sqe->stream_ctx_addr_h, + sqe->stream_ctx_addr_l); + drv_iova_unmap(q, recv_msg->ctx_buf, (void *)phy_ctxbuf, + MAX_CTX_RSV_SIZE); + } + + qm_parse_zip_sqe_set_status(recv_msg, status, lstblk, ctx_st); + + return 1; +} + +static int fill_zip_comp_alg_deflate(void *ssqe, struct wcrypto_comp_msg *msg) +{ + struct hisi_zip_sqe_v3 *sqe = ssqe; + + switch (msg->alg_type) { + case WCRYPTO_ZLIB: + sqe->dw9 = HW_ZLIB; + break; + case WCRYPTO_GZIP: + sqe->dw9 = HW_GZIP; + break; + case WCRYPTO_RAW_DEFLATE: + sqe->dw9 = HW_RAW_DEFLATE; + break; + default: + return -WD_EINVAL; + } + + return WD_SUCCESS; +} + +static int fill_zip_comp_alg_zstd(void *ssqe, struct wcrypto_comp_msg *msg) +{ + struct hisi_zip_sqe_v3 *sqe = ssqe; + + if (msg->comp_lv == WCRYPTO_COMP_L9) { + sqe->dw9 = HW_LZ77_ZSTD_PRICE; + } else if (msg->comp_lv == WCRYPTO_COMP_L8 || msg->comp_lv == 0) { + sqe->dw9 = HW_LZ77_ZSTD; + } else { + WD_ERR("The compress level is invalid!\n"); + return -WD_EINVAL; + } + + return WD_SUCCESS; +} + +static int fill_zip_buffer_size_deflate(void *ssqe, struct wcrypto_comp_msg *msg) +{ + struct hisi_zip_sqe_v3 *sqe = ssqe; + + if (unlikely(msg->data_fmt != WD_SGL_BUF && + msg->in_size > MAX_BUFFER_SIZE)) { + WD_ERR("The in_len is out of range in_len(%u)!\n", msg->in_size); + return -WD_EINVAL; + } + + if (unlikely(msg->data_fmt != WD_SGL_BUF && + msg->avail_out > MAX_BUFFER_SIZE)) { + WD_ERR("warning: avail_out is out of range (%u), will set 8MB size max!\n", + msg->avail_out); + msg->avail_out = MAX_BUFFER_SIZE; + } + + sqe->input_data_length = msg->in_size; + sqe->dest_avail_out = msg->avail_out; + + return WD_SUCCESS; +} + +static int fill_zip_buffer_size_zstd(void *ssqe, struct wcrypto_comp_msg *msg) +{ + __u32 lit_size = msg->in_size + ZSTD_LIT_RSV_SIZE; + struct hisi_zip_sqe_v3 *sqe = ssqe; + struct wcrypto_zstd_out *zstd_out; + + if (unlikely(msg->in_size > MAX_ZSTD_INPUT_SIZE)) { + WD_ERR("The in_len is out of range in_len(%u)!\n", msg->in_size); + return -WD_EINVAL; + } + + if (msg->data_fmt == WD_SGL_BUF) { + zstd_out = (void *)msg->dst; + + if (unlikely(zstd_out->lit_sz < lit_size || + zstd_out->seq_sz < ZSTD_FREQ_DATA_SIZE )) { + WD_ERR("literal(%u) or sequence(%u) of lz77_zstd is not enough.\n", + zstd_out->lit_sz, zstd_out->seq_sz); + return -WD_EINVAL; + } + sqe->dw13 = zstd_out->lit_sz; + /* fill the sequences output size */ + sqe->dest_avail_out = zstd_out->seq_sz; + } else { + if (unlikely(msg->avail_out > MAX_BUFFER_SIZE)) { + WD_ERR("warning: avail_out is out of range (%u), will set 8MB size max!\n", + msg->avail_out); + msg->avail_out = MAX_BUFFER_SIZE; + } + + /* + * For lz77_zstd, the hardware need 784 Bytes buffer to output + * the frequency information about input data. + */ + if (unlikely(msg->avail_out < ZSTD_FREQ_DATA_SIZE + lit_size)) { + WD_ERR("output buffer size of lz77_zstd is not enough(%u)\n", + ZSTD_FREQ_DATA_SIZE + lit_size); + return -WD_EINVAL; + } + /* fill the literals output size */ + sqe->dw13 = lit_size; + /* fill the sequences output size */ + sqe->dest_avail_out = msg->avail_out - lit_size; + } + sqe->input_data_length = msg->in_size; + + return WD_SUCCESS; +} + +static int fill_zip_window_size(void *ssqe, struct wcrypto_comp_msg *msg) +{ + struct hisi_zip_sqe_v3 *sqe = ssqe; + + if (msg->op_type == WCRYPTO_INFLATE) + return WD_SUCCESS; + + switch (msg->win_size) { + case WCRYPTO_COMP_WS_4K: + case WCRYPTO_COMP_WS_8K: + case WCRYPTO_COMP_WS_16K: + case WCRYPTO_COMP_WS_24K: + case WCRYPTO_COMP_WS_32K: + sqe->dw9 |= msg->win_size << WINDOWS_SIZE_SHIFT; + break; + default: + return -WD_EINVAL; + } + + return WD_SUCCESS; +} + +static int fill_zip_addr_deflate(void *ssqe, + struct wcrypto_comp_msg *msg, + struct wd_queue *q) +{ + struct hisi_zip_sqe_v3 *sqe = ssqe; + struct hisi_zip_sqe_addr addr = {0}; + int ret; + + ret = qm_fill_zip_sqe_get_phy_addr(&addr, msg, q, false); + if (ret) + return ret; + + sqe->source_addr_l = lower_32_bits((__u64)addr.source_addr); + sqe->source_addr_h = upper_32_bits((__u64)addr.source_addr); + sqe->dest_addr_l = lower_32_bits((__u64)addr.dest_addr); + sqe->dest_addr_h = upper_32_bits((__u64)addr.dest_addr); + sqe->stream_ctx_addr_l = lower_32_bits((__u64)addr.ctxbuf_addr); + sqe->stream_ctx_addr_h = upper_32_bits((__u64)addr.ctxbuf_addr); + + return WD_SUCCESS; +} + +static int fill_zip_addr_lz77_zstd(void *ssqe, + struct wcrypto_comp_msg *msg, + struct wd_queue *q) +{ + struct hisi_zip_sqe_addr addr = {0}; + struct hisi_zip_sqe_v3 *sqe = ssqe; + struct wcrypto_zstd_out *zstd_out; + uintptr_t phy_lit, phy_seq; + int ret; + + ret = qm_fill_zip_sqe_get_phy_addr(&addr, msg, q, true); + if (ret) + return ret; + + sqe->source_addr_l = lower_32_bits((__u64)addr.source_addr); + sqe->source_addr_h = upper_32_bits((__u64)addr.source_addr); + if (msg->data_fmt == WD_SGL_BUF) { + zstd_out = (void *)msg->dst; + phy_lit = (uintptr_t)drv_iova_map(q, zstd_out->literal, zstd_out->lit_sz); + if (!phy_lit) { + WD_ERR("Get literal buf dma address fail!\n"); + goto unmap_phy_lit; + } + + phy_seq = (uintptr_t)drv_iova_map(q, zstd_out->sequence, zstd_out->seq_sz); + if (!phy_seq) { + WD_ERR("Get sequence buf dma address fail!\n"); + goto unmap_phy_seq; + } + + sqe->cipher_key_addr_l = lower_32_bits((__u64)phy_lit); + sqe->cipher_key_addr_h = upper_32_bits((__u64)phy_lit); + sqe->dest_addr_l = lower_32_bits((__u64)phy_seq); + sqe->dest_addr_h = upper_32_bits((__u64)phy_seq); + } else { + sqe->cipher_key_addr_l = lower_32_bits((__u64)addr.dest_addr); + sqe->cipher_key_addr_h = upper_32_bits((__u64)addr.dest_addr); + sqe->dest_addr_l = lower_32_bits((__u64)addr.dest_addr + msg->in_size); + sqe->dest_addr_h = upper_32_bits((__u64)addr.dest_addr + msg->in_size); + } + + sqe->stream_ctx_addr_l = lower_32_bits((__u64)addr.ctxbuf_addr); + sqe->stream_ctx_addr_h = upper_32_bits((__u64)addr.ctxbuf_addr); + + return WD_SUCCESS; + +unmap_phy_seq: + drv_iova_unmap(q, zstd_out->literal, (void *)phy_lit, zstd_out->lit_sz); +unmap_phy_lit: + drv_iova_unmap(q, msg->src, (void *)addr.source_addr, msg->in_size); + return -WD_ENOMEM; +} + +static void fill_zip_sqe_hw_info(void *ssqe, struct wcrypto_comp_msg *msg) +{ + struct hisi_zip_sqe_v3 *sqe = ssqe; + + if (msg->ctx_buf) { + sqe->ctx_dw0 = *(__u32 *)msg->ctx_buf; + sqe->ctx_dw1 = *(__u32 *)(msg->ctx_buf + CTX_PRIV1_OFFSET); + sqe->ctx_dw2 = *(__u32 *)(msg->ctx_buf + CTX_PRIV2_OFFSET); + } + + sqe->isize = msg->isize; + sqe->checksum = msg->checksum; +} + +static void fill_zip_sqe_hw_info_lz77_zstd(void *ssqe, struct wcrypto_comp_msg *msg) +{ + struct wcrypto_comp_tag *tag = (void *)(uintptr_t)msg->udata; + struct wcrypto_lz77_zstd_format *format = tag->priv; + struct hisi_zip_sqe_v3 *sqe = ssqe; + + if (msg->ctx_buf) { + sqe->ctx_dw0 = *(__u32 *)msg->ctx_buf; + sqe->ctx_dw1 = *(__u32 *)(msg->ctx_buf + CTX_PRIV1_OFFSET); + sqe->ctx_dw2 = *(__u32 *)(msg->ctx_buf + CTX_PRIV2_OFFSET); + if (format->blk_type != COMP_BLK) + memcpy(msg->ctx_buf + CTX_HW_REPCODE_OFFSET + CTX_BUFFER_OFFSET, + msg->ctx_buf + CTX_REPCODE2_OFFSET, REPCODE_SIZE); + } + + sqe->isize = msg->isize; + sqe->checksum = msg->checksum; +} + +static struct zip_fill_sqe_ops ops[] = { { + .alg_type = "zlib", + .fill_sqe_alg = fill_zip_comp_alg_deflate, + .fill_sqe_buffer_size = fill_zip_buffer_size_deflate, + .fill_sqe_window_size = fill_zip_window_size, + .fill_sqe_addr = fill_zip_addr_deflate, + .fill_sqe_hw_info = fill_zip_sqe_hw_info, + }, { + .alg_type = "gzip", + .fill_sqe_alg = fill_zip_comp_alg_deflate, + .fill_sqe_buffer_size = fill_zip_buffer_size_deflate, + .fill_sqe_window_size = fill_zip_window_size, + .fill_sqe_addr = fill_zip_addr_deflate, + .fill_sqe_hw_info = fill_zip_sqe_hw_info, + }, { + .alg_type = "raw_deflate", + .fill_sqe_alg = fill_zip_comp_alg_deflate, + .fill_sqe_buffer_size = fill_zip_buffer_size_deflate, + .fill_sqe_window_size = fill_zip_window_size, + .fill_sqe_addr = fill_zip_addr_deflate, + .fill_sqe_hw_info = fill_zip_sqe_hw_info, + }, { + .alg_type = "lz77_zstd", + .fill_sqe_alg = fill_zip_comp_alg_zstd, + .fill_sqe_buffer_size = fill_zip_buffer_size_zstd, + .fill_sqe_window_size = fill_zip_window_size, + .fill_sqe_addr = fill_zip_addr_lz77_zstd, + .fill_sqe_hw_info = fill_zip_sqe_hw_info_lz77_zstd, + }, +}; + +int qm_fill_zip_sqe_v3(void *smsg, struct qm_queue_info *info, __u16 i) +{ + struct hisi_zip_sqe_v3 *sqe = (struct hisi_zip_sqe_v3 *)info->sq_base + i; + struct wcrypto_comp_msg *msg = smsg; + struct wd_queue *q = info->q; + __u8 flush_type; + __u8 data_fmt; + int ret; + + memset(sqe, 0, sizeof(*sqe)); + + if (unlikely(msg->alg_type >= get_arrsize(ops))) { + WD_ERR("The algorithm is invalid!\n"); + return -WD_EINVAL; + } + + ret = ops[msg->alg_type].fill_sqe_alg(sqe, msg); + if (unlikely(ret)) { + WD_ERR("The algorithm is unsupported!\n"); + return ret; + } + + ret = ops[msg->alg_type].fill_sqe_buffer_size(sqe, msg); + if (unlikely(ret)) { + WD_ERR("The buffer size is invalid!\n"); + return ret; + } + + ret = ops[msg->alg_type].fill_sqe_window_size(sqe, msg); + if (unlikely(ret)) { + WD_ERR("The window size is invalid!\n"); + return ret; + } + + ret = ops[msg->alg_type].fill_sqe_addr(sqe, msg, q); + if (unlikely(ret)) + return ret; + + flush_type = (msg->flush_type == WCRYPTO_FINISH) ? HZ_FINISH : + HZ_SYNC_FLUSH; + sqe->dw7 |= ((msg->stream_pos << STREAM_POS_SHIFT) | + (msg->stream_mode << STREAM_MODE_SHIFT) | + (flush_type)) << STREAM_FLUSH_SHIFT | + BD_TYPE3 << BD_TYPE_SHIFT; + + /* data_fmt: 4'b0000 - Pbuffer, 4'b0001 - SGL */ + data_fmt = (msg->data_fmt == WD_SGL_BUF) ? HISI_SGL_BUF : HISI_FLAT_BUF; + sqe->dw9 |= data_fmt << HZ_BUF_TYPE_SHIFT; + + ops[msg->alg_type].fill_sqe_hw_info(sqe, msg); + sqe->tag_l = msg->tag; + + info->req_cache[i] = msg; + + return WD_SUCCESS; +} + +/* + * Checksum[31:24] equals LitLength_Overflow_Pos; + * Checksum[23:0] equals Freq_Literal_Overflow_cnt; + */ +#define LILL_OVERFLOW_POS 0x00ffffff +#define LILL_OVERFLOW_CNT_OFFSET 24 +static void fill_priv_lz77_zstd(void *ssqe, struct wcrypto_comp_msg *recv_msg) +{ + struct wcrypto_comp_tag *tag = (void *)(uintptr_t)recv_msg->udata; + struct wcrypto_lz77_zstd_format *format = tag->priv; + struct hisi_zip_sqe_v3 *sqe = ssqe; + struct wcrypto_zstd_out *zstd_out; + void *ctx_buf = recv_msg->ctx_buf; + + format->lit_num = sqe->comp_data_length; + format->seq_num = sqe->produced; + + format->lit_length_overflow_cnt = sqe->checksum & LILL_OVERFLOW_POS; + format->lit_length_overflow_pos = (sqe->checksum & ~LILL_OVERFLOW_POS) >> + LILL_OVERFLOW_CNT_OFFSET; + + if (recv_msg->data_fmt == WD_SGL_BUF) { + zstd_out = (void *)recv_msg->dst; + format->literals_start = zstd_out->literal; + format->sequences_start = zstd_out->sequence; + } else { + format->literals_start = recv_msg->dst; + format->sequences_start = recv_msg->dst + recv_msg->in_size; + format->freq = (void *)(&format->lit_length_overflow_pos + 1); + } + + if (ctx_buf) { + memcpy(ctx_buf + CTX_REPCODE2_OFFSET, + ctx_buf + CTX_REPCODE1_OFFSET, REPCODE_SIZE); + memcpy(ctx_buf + CTX_REPCODE1_OFFSET, + ctx_buf + CTX_BUFFER_OFFSET + CTX_HW_REPCODE_OFFSET, + REPCODE_SIZE); + } +} + +int qm_parse_zip_sqe_v3(void *hw_msg, const struct qm_queue_info *info, + __u16 i, __u16 usr) +{ + struct wcrypto_comp_msg *recv_msg = info->req_cache[i]; + struct hisi_zip_sqe_v3 *sqe = hw_msg; + __u16 ctx_st = sqe->ctx_dw0 & HZ_CTX_ST_MASK; + __u16 lstblk = sqe->dw3 & HZ_LSTBLK_MASK; + __u32 status = sqe->dw3 & HZ_STATUS_MASK; + __u32 type = sqe->dw9 & HZ_REQ_TYPE_MASK; + uintptr_t phy_in, phy_out, phy_ctxbuf; + struct wd_queue *q = info->q; + struct wcrypto_comp_tag *tag; + + if (unlikely(!recv_msg)) { + WD_ERR("info->req_cache is null at index:%hu\n", i); + return 0; + } + + if (usr && sqe->tag_l != usr) + return 0; + + if (status != 0 && status != HW_NEGACOMPRESS && status != HW_DECOMP_END) { + WD_ERR("bad status(ctx_st=0x%x, s=0x%x, t=%u)\n", + ctx_st, status, type); + recv_msg->status = WD_IN_EPARA; + } else { + recv_msg->status = 0; + } + recv_msg->in_cons = sqe->consumed; + recv_msg->produced = sqe->produced; + if (recv_msg->ctx_buf) { + *(__u32 *)recv_msg->ctx_buf = sqe->ctx_dw0; + *(__u32 *)(recv_msg->ctx_buf + CTX_PRIV1_OFFSET) = sqe->ctx_dw1; + *(__u32 *)(recv_msg->ctx_buf + CTX_PRIV2_OFFSET) = sqe->ctx_dw2; + } + recv_msg->isize = sqe->isize; + recv_msg->checksum = sqe->checksum; + + phy_in = DMA_ADDR(sqe->source_addr_h, sqe->source_addr_l); + drv_iova_unmap(q, recv_msg->src, (void *)phy_in, recv_msg->in_size); + phy_out = DMA_ADDR(sqe->dest_addr_h, sqe->dest_addr_l); + drv_iova_unmap(q, recv_msg->dst, (void *)phy_out, recv_msg->avail_out); + if (recv_msg->ctx_buf) { + phy_ctxbuf = DMA_ADDR(sqe->stream_ctx_addr_h, + sqe->stream_ctx_addr_l); + drv_iova_unmap(q, recv_msg->ctx_buf, (void *)phy_ctxbuf, + MAX_CTX_RSV_SIZE); + } + + qm_parse_zip_sqe_set_status(recv_msg, status, lstblk, ctx_st); + + tag = (void *)(uintptr_t)recv_msg->udata; + if (tag && tag->priv && !info->sqe_fill_priv) + fill_priv_lz77_zstd(sqe, recv_msg); + + return 1; +} + +static void qm_fill_zip_cipher_sqe_with_priv(struct hisi_zip_sqe *sqe, void *priv) +{ + struct wd_sec_udata *udata = priv; + __u32 dif_size = 0; + __u32 pad_size = 0; + + if (!udata) + return; + + sqe->lba_l = lower_32_bits(udata->dif.lba); + sqe->lba_h = upper_32_bits(udata->dif.lba); + sqe->dw7 = udata->src_offset; + sqe->dw8 = udata->dst_offset; + sqe->dw10 = (udata->dif.ctrl.gen.page_layout_gen_type) | + (udata->dif.ctrl.gen.grd_gen_type << HZ_GRD_GTYPE_SHIFT) | + (udata->dif.ctrl.gen.ver_gen_type << HZ_VER_GTYPE_SHIFT) | + (udata->dif.ctrl.gen.app_gen_type << HZ_APP_GTYPE_SHIFT) | + (udata->dif.app << HZ_APP_SHIFT) | (udata->dif.ver << HZ_VER_SHIFT); + sqe->priv_info = udata->dif.priv_info; + sqe->dw12 = (udata->dif.ctrl.gen.ref_gen_type) | + (udata->dif.ctrl.gen.page_layout_pad_type << HZ_PAD_TYPE_SHIFT) | + (udata->dif.ctrl.verify.grd_verify_type << HZ_GRD_VTYPE_SHIFT) | + (udata->dif.ctrl.verify.ref_verify_type << HZ_REF_VTYPE_SHIFT) | + (udata->block_size << HZ_BLK_SIZE_SHIFT); + + if (udata->dif.ctrl.gen.grd_gen_type) { + dif_size = ZIP_DIF_LEN; + if (udata->dif.ctrl.gen.page_layout_gen_type) + pad_size = ZIP_PAD_LEN; + } + + sqe->input_data_length = + (udata->block_size + dif_size + pad_size) * udata->gran_num; + sqe->dest_avail_out = sqe->input_data_length; +} + +static int fill_zip_cipher_alg(struct wcrypto_cipher_msg *msg, + struct hisi_zip_sqe *sqe, __u16 *key_len) +{ + int ret = -WD_EINVAL; + __u16 len; + + if (msg->mode != WCRYPTO_CIPHER_XTS) + return -WD_EINVAL; + + len = msg->key_bytes >> XTS_MODE_KEY_SHIFT; + + switch (msg->alg) { + case WCRYPTO_CIPHER_SM4: + sqe->dw9 = HW_XTS_SM4_128; + ret = WD_SUCCESS; + break; + case WCRYPTO_CIPHER_AES: + if (len == AES_KEYSIZE_128) { + sqe->dw9 = HW_XTS_AES_128; + ret = WD_SUCCESS; + } else if (len == AES_KEYSIZE_256) { + sqe->dw9 = HW_XTS_AES_256; + ret = WD_SUCCESS; + } else { + WD_ERR("Zip invalid AES key size!\n"); + } + break; + default: + WD_ERR("Zip invalid cipher type!\n"); + break; + } + + *key_len = len; + return ret; +} + +int qm_fill_zip_cipher_sqe(void *send_msg, struct qm_queue_info *info, __u16 i) +{ + struct hisi_zip_sqe *sqe = (struct hisi_zip_sqe *)info->sq_base + i; + struct wcrypto_cipher_msg *msg = send_msg; + struct wcrypto_cipher_tag *cipher_tag = (void *)(uintptr_t)msg->usr_data; + struct wd_queue *q = info->q; + __u8 data_fmt; + uintptr_t phy; + __u16 key_len; + int ret; + + memset((void *)sqe, 0, sizeof(*sqe)); + + ret = fill_zip_cipher_alg(msg, sqe, &key_len); + if (ret) + return ret; + + phy = (uintptr_t)msg->in; + sqe->source_addr_l = lower_32_bits(phy); + sqe->source_addr_h = upper_32_bits(phy); + + phy = (uintptr_t)msg->out; + sqe->dest_addr_l = lower_32_bits(phy); + sqe->dest_addr_h = upper_32_bits(phy); + + data_fmt = (msg->data_fmt == WD_SGL_BUF) ? HISI_SGL_BUF : HISI_FLAT_BUF; + sqe->dw9 |= data_fmt << HZ_BUF_TYPE_SHIFT; + + phy = (uintptr_t)drv_iova_map(q, msg->key, msg->key_bytes); + if (!phy) { + WD_ERR("Get zip key buf dma address fail!\n"); + return -WD_ENOMEM; + } + sqe->cipher_key1_addr_l = lower_32_bits(phy); + sqe->cipher_key1_addr_h = upper_32_bits(phy); + + phy += key_len; + sqe->cipher_key2_addr_l = lower_32_bits(phy); + sqe->cipher_key2_addr_h = upper_32_bits(phy); + if (cipher_tag) { + sqe->tag = cipher_tag->wcrypto_tag.ctx_id; + qm_fill_zip_cipher_sqe_with_priv(sqe, cipher_tag->priv); + } + + info->req_cache[i] = msg; + + return WD_SUCCESS; +} + +int qm_parse_zip_cipher_sqe(void *hw_msg, const struct qm_queue_info *info, + __u16 i, __u16 usr) +{ + struct wcrypto_cipher_msg *recv_msg = info->req_cache[i]; + struct hisi_zip_sqe *sqe = hw_msg; + struct wd_queue *q = info->q; + __u32 status = sqe->dw3 & HZ_STATUS_MASK; + __u32 type = sqe->dw9 & HZ_REQ_TYPE_MASK; + __u64 dma_addr; + + if (unlikely(!recv_msg)) { + WD_ERR("info->req_cache is null at index:%hu\n", i); + return 0; + } + + if (usr && sqe->tag != usr) + return 0; + + if (status == 0) + recv_msg->result = 0; + else if (status == HW_IN_DATA_DIF_CHECK_ERR) + recv_msg->result = WCRYPTO_SRC_DIF_ERR; + else { + WD_ERR("bad status(s=0x%x, t=%u)\n", status, type); + recv_msg->result = WD_IN_EPARA; + } + + dma_addr = DMA_ADDR(sqe->cipher_key1_addr_h, sqe->cipher_key1_addr_l); + drv_iova_unmap(q, recv_msg->key, (void *)(uintptr_t)dma_addr, + recv_msg->key_bytes); + + return 1; +} diff --git a/uadk/v1/drv/hisi_zip_udrv.h b/uadk/v1/drv/hisi_zip_udrv.h new file mode 100644 index 0000000..c93b01a --- /dev/null +++ b/uadk/v1/drv/hisi_zip_udrv.h @@ -0,0 +1,137 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#ifndef HISI_ZIP_USR_IF_H +#define HISI_ZIP_USR_IF_H + +#include "v1/drv/hisi_qm_udrv.h" + +enum hw_comp_alg_type { + HW_RAW_DEFLATE = 0x01, + HW_ZLIB, + HW_GZIP, + HW_LZ77_ZSTD_PRICE = 0x42, + HW_LZ77_ZSTD, +}; + +enum hw_zip_cipher_alg_type { + HW_XTS_AES_128 = 0x10, + HW_XTS_AES_256 = 0x20, + HW_XTS_SM4_128 = 0x30, +}; + +enum hw_flush { + HZ_SYNC_FLUSH, + HZ_FINISH, +}; + +struct hisi_zip_sqe { + __u32 consumed; + __u32 produced; + __u32 comp_data_length; + __u32 dw3; + __u32 input_data_length; + __u32 lba_l; + __u32 lba_h; + __u32 dw7; + __u32 dw8; + __u32 dw9; + __u32 dw10; + __u32 priv_info; + __u32 dw12; + __u32 tag; + __u32 dest_avail_out; + __u32 ctx_dw0; + __u32 comp_head_addr_l; + __u32 comp_head_addr_h; + __u32 source_addr_l; + __u32 source_addr_h; + __u32 dest_addr_l; + __u32 dest_addr_h; + __u32 stream_ctx_addr_l; + __u32 stream_ctx_addr_h; + __u32 cipher_key1_addr_l; + __u32 cipher_key1_addr_h; + __u32 cipher_key2_addr_l; + __u32 cipher_key2_addr_h; + __u32 ctx_dw1; + __u32 ctx_dw2; + __u32 isize; + __u32 checksum; +}; + +struct hisi_zip_sqe_v3 { + __u32 consumed; + __u32 produced; + __u32 comp_data_length; + __u32 dw3; + __u32 input_data_length; + __u32 lba_l; + __u32 lba_h; + __u32 dw7; + __u32 dw8; + __u32 dw9; + __u32 dw10; + __u32 priv_info; + __u32 dw12; + __u32 dw13; + __u32 dest_avail_out; + __u32 ctx_dw0; + __u32 comp_head_addr_l; + __u32 comp_head_addr_h; + __u32 source_addr_l; + __u32 source_addr_h; + __u32 dest_addr_l; + __u32 dest_addr_h; + __u32 stream_ctx_addr_l; + __u32 stream_ctx_addr_h; + __u32 cipher_key_addr_l; + __u32 cipher_key_addr_h; + __u32 tag_l; + __u32 tag_h; + __u32 ctx_dw1; + __u32 ctx_dw2; + __u32 isize; + __u32 checksum; +}; + +#define HZ_BUF_TYPE_SHIFT 8 +#define HZ_ALIGN_SIZE_SHIFT 16 +#define HZ_GRD_GTYPE_SHIFT 4 +#define HZ_VER_GTYPE_SHIFT 8 +#define HZ_APP_GTYPE_SHIFT 12 +#define HZ_APP_SHIFT 16 +#define HZ_VER_SHIFT 24 +#define HZ_PAD_TYPE_SHIFT 4 +#define HZ_GRD_VTYPE_SHIFT 8 +#define HZ_REF_VTYPE_SHIFT 12 +#define HZ_BLK_SIZE_SHIFT 16 +#define HZ_CTX_ST_MASK 0x000f +#define HZ_LSTBLK_MASK 0x0100 +#define HZ_STATUS_MASK 0xff +#define HZ_REQ_TYPE_MASK 0xff + +int qm_fill_zip_sqe(void *smsg, struct qm_queue_info *info, __u16 i); +int qm_parse_zip_sqe(void *hw_msg, const struct qm_queue_info *info, + __u16 i, __u16 usr); +int qm_fill_zip_sqe_v3(void *smsg, struct qm_queue_info *info, __u16 i); +int qm_parse_zip_sqe_v3(void *msg, const struct qm_queue_info *info, + __u16 i, __u16 usr); +int qm_fill_zip_cipher_sqe(void *smsg, struct qm_queue_info *info, __u16 i); +int qm_parse_zip_cipher_sqe(void *hw_msg, const struct qm_queue_info *info, + __u16 i, __u16 usr); + +#endif diff --git a/uadk/v1/drv/wd_drv.h b/uadk/v1/drv/wd_drv.h new file mode 100644 index 0000000..ae7eec6 --- /dev/null +++ b/uadk/v1/drv/wd_drv.h @@ -0,0 +1,22 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#ifndef __WD_DRV_H +#define __WD_DRV_H + +#include "wd.h" + +#endif diff --git a/uadk/v1/internal/dummy_hw_usr_if.h b/uadk/v1/internal/dummy_hw_usr_if.h new file mode 100644 index 0000000..3a9df48 --- /dev/null +++ b/uadk/v1/internal/dummy_hw_usr_if.h @@ -0,0 +1,57 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +/* + * This file defines the dummy hardware/driver interface between the user and + * kernel space + */ + +#ifndef __DUMMY_HW_USR_IF_H +#define __DUMMY_HW_USR_IF_H + +#include + +#define DUMMY_WD "dummy_wd" + +#define Q_BDS 16 +#define DUMMY_HW_TAG_SZ 8 +#define DUMMY_HW_TAG "WDDUMMY" + +/* the format of the device ring space, which is of drv */ +#define ring_bd wd_dummy_cpy_msg + +/* the format of the device io space, which is of drv */ +struct dummy_hw_queue_reg { + char hw_tag[DUMMY_HW_TAG_SZ]; /* should be "WDDUMMY\0" */ + struct ring_bd ring[Q_BDS]; /* in real hardware, this is good to be + in memory space, and will be fast + for communication. here we keep it + in io space just to make it simple + */ + __u32 ring_bd_num; /* ring_bd_num, now it is Q_BDS until + we use a memory ring */ + __u32 head; /* assume int is atomical. it should be + fine as a dummy and test function. + head is for the writer(user) while + tail is for the reader(kernel). + head==tail means the queue is empty + */ + __u32 tail; +}; + +#define DUMMY_CMD_FLUSH _IO('d', 0) + +#endif diff --git a/uadk/v1/internal/wd_dummy_usr_if.h b/uadk/v1/internal/wd_dummy_usr_if.h new file mode 100644 index 0000000..b5673ec --- /dev/null +++ b/uadk/v1/internal/wd_dummy_usr_if.h @@ -0,0 +1,45 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +/* + * This file defines the dummy algo interface between the user + * and kernel space + */ + +#ifndef __DUMMY_USR_IF_H +#define __DUMMY_USR_IF_H + + +/* Algorithm name */ +#define AN_DUMMY_MEMCPY "memcopy" + +#define AAN_AFLAGS "aflags" +#define AAN_MAX_COPY_SIZE "max_copy_size" + +struct wd_dummy_cpy_param { + int flags; + int max_copy_size; +}; + +struct wd_dummy_cpy_msg { + char *src_addr; + char *tgt_addr; + size_t size; + void *ptr; + __u32 ret; +}; + +#endif diff --git a/uadk/v1/internal/wd_ecc_curve.h b/uadk/v1/internal/wd_ecc_curve.h new file mode 100644 index 0000000..fd04276 --- /dev/null +++ b/uadk/v1/internal/wd_ecc_curve.h @@ -0,0 +1,303 @@ +/* + * Copyright 2020 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#ifndef __WD_ECC_CURVE_H +#define __WD_ECC_CURVE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* big-endian ************************/ +#define X25519_256_PARAM {\ + /* p = (2 ^ 255 - 19) */\ + 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xed,\ + /* a = (486662 - 2) / 4 = 121665 */\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xDB, 0x41,\ + /* b : only for format, no mean */\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + /* x */\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,\ + /* y : only for format, no mean */\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + /* order : only for format, no mean */\ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ +} + +/********************* big-endian ************************/ +#define X448_448_PARAM {\ + /* p = (2 ^ 448 - 2 ^ 224 - 1) */\ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + /* a = (156326 - 2) / 4 = 39081 */\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0xA9,\ + /* b : only for format, no mean */\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + /* x */\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,\ + /* y : only for format, no mean */\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + /* order : only for format, no mean */\ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ +} + +#define SECG_P128_R1_PARAM {\ + /* p */\ + 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFF,\ + /* a */\ + 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFC,\ + /* b */\ + 0xE8, 0x75, 0x79, 0xC1, 0x10, 0x79, 0xF4, 0x3D, 0xD8, 0x24, 0x99, 0x3C,\ + 0x2C, 0xEE, 0x5E, 0xD3,\ + /* x */\ + 0x16, 0x1F, 0xF7, 0x52, 0x8B, 0x89, 0x9B, 0x2D, 0x0C, 0x28, 0x60, 0x7C,\ + 0xA5, 0x2C, 0x5B, 0x86,\ + /* y */\ + 0xcf, 0x5a, 0xc8, 0x39, 0x5b, 0xaf, 0xeb, 0x13, 0xc0, 0x2d, 0xa2, 0x92,\ + 0xdd, 0xed, 0x7a, 0x83,\ + /* order */\ + 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x75, 0xA3, 0x0D, 0x1B,\ + 0x90, 0x38, 0xA1, 0x15,\ +} + +#define SECG_P192_K1_PARAM {\ + /* p */\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xEE, 0x37,\ + /* a */\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + /* b */\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,\ + /* x */\ + 0xDB, 0x4F, 0xF1, 0x0E, 0xC0, 0x57, 0xE9, 0xAE, 0x26, 0xB0, 0x7D, 0x02,\ + 0x80, 0xB7, 0xF4, 0x34, 0x1D, 0xA5, 0xD1, 0xB1, 0xEA, 0xE0, 0x6C, 0x7D,\ + /* y */\ + 0x9b, 0x2f, 0x2f, 0x6d, 0x9c, 0x56, 0x28, 0xa7, 0x84, 0x41, 0x63, 0xd0,\ + 0x15, 0xbe, 0x86, 0x34, 0x40, 0x82, 0xaa, 0x88, 0xd9, 0x5e, 0x2f, 0x9d,\ + /* order */\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,\ + 0x26, 0xF2, 0xFC, 0x17, 0x0F, 0x69, 0x46, 0x6A, 0x74, 0xDE, 0xFD, 0x8D\ +} + +#define SECG_P256_K1_PARAM {\ + /* p */\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x2F,\ + /* a */\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + /* b */\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,\ + /* x */\ + 0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95,\ + 0xCE, 0x87, 0x0B, 0x07, 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9,\ + 0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98,\ + /* y */\ + 0x48, 0x3a, 0xda, 0x77, 0x26, 0xa3, 0xc4, 0x65, 0x5d, 0xa4, 0xfb, 0xfc,\ + 0x0e, 0x11, 0x08, 0xa8, 0xfd, 0x17, 0xb4, 0x48, 0xa6, 0x85, 0x54, 0x19,\ + 0x9c, 0x47, 0xd0, 0x8f, 0xfb, 0x10, 0xd4, 0xb8,\ + /* order */\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B,\ + 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41\ +} + +#define BRAINPOOL_P320_R1_PARAM {\ + /* p */\ + 0xD3, 0x5E, 0x47, 0x20, 0x36, 0xBC, 0x4F, 0xB7, 0xE1, 0x3C, 0x78, 0x5E,\ + 0xD2, 0x01, 0xE0, 0x65, 0xF9, 0x8F, 0xCF, 0xA6, 0xF6, 0xF4, 0x0D, 0xEF,\ + 0x4F, 0x92, 0xB9, 0xEC, 0x78, 0x93, 0xEC, 0x28, 0xFC, 0xD4, 0x12, 0xB1,\ + 0xF1, 0xB3, 0x2E, 0x27,\ + /* a */\ + 0x3E, 0xE3, 0x0B, 0x56, 0x8F, 0xBA, 0xB0, 0xF8, 0x83, 0xCC, 0xEB, 0xD4,\ + 0x6D, 0x3F, 0x3B, 0xB8, 0xA2, 0xA7, 0x35, 0x13, 0xF5, 0xEB, 0x79, 0xDA,\ + 0x66, 0x19, 0x0E, 0xB0, 0x85, 0xFF, 0xA9, 0xF4, 0x92, 0xF3, 0x75, 0xA9,\ + 0x7D, 0x86, 0x0E, 0xB4,\ + /* b */\ + 0x52, 0x08, 0x83, 0x94, 0x9D, 0xFD, 0xBC, 0x42, 0xD3, 0xAD, 0x19, 0x86,\ + 0x40, 0x68, 0x8A, 0x6F, 0xE1, 0x3F, 0x41, 0x34, 0x95, 0x54, 0xB4, 0x9A,\ + 0xCC, 0x31, 0xDC, 0xCD, 0x88, 0x45, 0x39, 0x81, 0x6F, 0x5E, 0xB4, 0xAC,\ + 0x8F, 0xB1, 0xF1, 0xA6,\ + /* x */\ + 0x43, 0xBD, 0x7E, 0x9A, 0xFB, 0x53, 0xD8, 0xB8, 0x52, 0x89, 0xBC, 0xC4,\ + 0x8E, 0xE5, 0xBF, 0xE6, 0xF2, 0x01, 0x37, 0xD1, 0x0A, 0x08, 0x7E, 0xB6,\ + 0xE7, 0x87, 0x1E, 0x2A, 0x10, 0xA5, 0x99, 0xC7, 0x10, 0xAF, 0x8D, 0x0D,\ + 0x39, 0xE2, 0x06, 0x11,\ + /* y */\ + 0x14, 0xFD, 0xD0, 0x55, 0x45, 0xEC, 0x1C, 0xC8, 0xAB, 0x40, 0x93, 0x24,\ + 0x7F, 0x77, 0x27, 0x5E, 0x07, 0x43, 0xFF, 0xED, 0x11, 0x71, 0x82, 0xEA,\ + 0xA9, 0xC7, 0x78, 0x77, 0xAA, 0xAC, 0x6A, 0xC7, 0xD3, 0x52, 0x45, 0xD1,\ + 0x69, 0x2E, 0x8E, 0xE1,\ + /* order */\ + 0xD3, 0x5E, 0x47, 0x20, 0x36, 0xBC, 0x4F, 0xB7, 0xE1, 0x3C, 0x78, 0x5E,\ + 0xD2, 0x01, 0xE0, 0x65, 0xF9, 0x8F, 0xCF, 0xA5, 0xB6, 0x8F, 0x12, 0xA3,\ + 0x2D, 0x48, 0x2E, 0xC7, 0xEE, 0x86, 0x58, 0xE9, 0x86, 0x91, 0x55, 0x5B,\ + 0x44, 0xC5, 0x93, 0x11\ +} + +#define BRAINPOOL_P384_R1_PARAM {\ + /* p */\ + 0x8C, 0xB9, 0x1E, 0x82, 0xA3, 0x38, 0x6D, 0x28, 0x0F, 0x5D, 0x6F, 0x7E,\ + 0x50, 0xE6, 0x41, 0xDF, 0x15, 0x2F, 0x71, 0x09, 0xED, 0x54, 0x56, 0xB4,\ + 0x12, 0xB1, 0xDA, 0x19, 0x7F, 0xB7, 0x11, 0x23, 0xAC, 0xD3, 0xA7, 0x29,\ + 0x90, 0x1D, 0x1A, 0x71, 0x87, 0x47, 0x00, 0x13, 0x31, 0x07, 0xEC, 0x53,\ + /* a */\ + 0x7B, 0xC3, 0x82, 0xC6, 0x3D, 0x8C, 0x15, 0x0C, 0x3C, 0x72, 0x08, 0x0A,\ + 0xCE, 0x05, 0xAF, 0xA0, 0xC2, 0xBE, 0xA2, 0x8E, 0x4F, 0xB2, 0x27, 0x87,\ + 0x13, 0x91, 0x65, 0xEF, 0xBA, 0x91, 0xF9, 0x0F, 0x8A, 0xA5, 0x81, 0x4A,\ + 0x50, 0x3A, 0xD4, 0xEB, 0x04, 0xA8, 0xC7, 0xDD, 0x22, 0xCE, 0x28, 0x26,\ + /* b */\ + 0x04, 0xA8, 0xC7, 0xDD, 0x22, 0xCE, 0x28, 0x26, 0x8B, 0x39, 0xB5, 0x54,\ + 0x16, 0xF0, 0x44, 0x7C, 0x2F, 0xB7, 0x7D, 0xE1, 0x07, 0xDC, 0xD2, 0xA6,\ + 0x2E, 0x88, 0x0E, 0xA5, 0x3E, 0xEB, 0x62, 0xD5, 0x7C, 0xB4, 0x39, 0x02,\ + 0x95, 0xDB, 0xC9, 0x94, 0x3A, 0xB7, 0x86, 0x96, 0xFA, 0x50, 0x4C, 0x11,\ + /* x */\ + 0x1D, 0x1C, 0x64, 0xF0, 0x68, 0xCF, 0x45, 0xFF, 0xA2, 0xA6, 0x3A, 0x81,\ + 0xB7, 0xC1, 0x3F, 0x6B, 0x88, 0x47, 0xA3, 0xE7, 0x7E, 0xF1, 0x4F, 0xE3,\ + 0xDB, 0x7F, 0xCA, 0xFE, 0x0C, 0xBD, 0x10, 0xE8, 0xE8, 0x26, 0xE0, 0x34,\ + 0x36, 0xD6, 0x46, 0xAA, 0xEF, 0x87, 0xB2, 0xE2, 0x47, 0xD4, 0xAF, 0x1E,\ + /* y */\ + 0x8A, 0xBE, 0x1D, 0x75, 0x20, 0xF9, 0xC2, 0xA4, 0x5C, 0xB1, 0xEB, 0x8E,\ + 0x95, 0xCF, 0xD5, 0x52, 0x62, 0xB7, 0x0B, 0x29, 0xFE, 0xEC, 0x58, 0x64,\ + 0xE1, 0x9C, 0x05, 0x4F, 0xF9, 0x91, 0x29, 0x28, 0x0E, 0x46, 0x46, 0x21,\ + 0x77, 0x91, 0x81, 0x11, 0x42, 0x82, 0x03, 0x41, 0x26, 0x3C, 0x53, 0x15,\ + /* order */\ + 0x8C, 0xB9, 0x1E, 0x82, 0xA3, 0x38, 0x6D, 0x28, 0x0F, 0x5D, 0x6F, 0x7E,\ + 0x50, 0xE6, 0x41, 0xDF, 0x15, 0x2F, 0x71, 0x09, 0xED, 0x54, 0x56, 0xB3,\ + 0x1F, 0x16, 0x6E, 0x6C, 0xAC, 0x04, 0x25, 0xA7, 0xCF, 0x3A, 0xB6, 0xAF,\ + 0x6B, 0x7F, 0xC3, 0x10, 0x3B, 0x88, 0x32, 0x02, 0xE9, 0x04, 0x65, 0x65\ +} + +#define NIST_P521_R1_PARAM {\ + /* p */\ + 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + /* a */\ + 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC,\ + /* b */\ + 0x00, 0x51, 0x95, 0x3E, 0xB9, 0x61, 0x8E, 0x1C, 0x9A, 0x1F, 0x92, 0x9A,\ + 0x21, 0xA0, 0xB6, 0x85, 0x40, 0xEE, 0xA2, 0xDA, 0x72, 0x5B, 0x99, 0xB3,\ + 0x15, 0xF3, 0xB8, 0xB4, 0x89, 0x91, 0x8E, 0xF1, 0x09, 0xE1, 0x56, 0x19,\ + 0x39, 0x51, 0xEC, 0x7E, 0x93, 0x7B, 0x16, 0x52, 0xC0, 0xBD, 0x3B, 0xB1,\ + 0xBF, 0x07, 0x35, 0x73, 0xDF, 0x88, 0x3D, 0x2C, 0x34, 0xF1, 0xEF, 0x45,\ + 0x1F, 0xD4, 0x6B, 0x50, 0x3F, 0x00,\ + /* x */\ + 0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD, 0x9E, 0x3E,\ + 0xCB, 0x66, 0x23, 0x95, 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F,\ + 0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, 0x3D, 0xBA, 0xA1, 0x4B,\ + 0x5E, 0x77, 0xEF, 0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF,\ + 0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, 0x42, 0x9B, 0xF9, 0x7E,\ + 0x7E, 0x31, 0xC2, 0xE5, 0xBD, 0x66,\ + /* y */\ + 0x01, 0x18, 0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b, 0xc0, 0x04, 0x5c, 0x8a,\ + 0x5f, 0xb4, 0x2c, 0x7d, 0x1b, 0xd9, 0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b,\ + 0x44, 0x68, 0x17, 0xaf, 0xbd, 0x17, 0x27, 0x3e, 0x66, 0x2c, 0x97, 0xee,\ + 0x72, 0x99, 0x5e, 0xf4, 0x26, 0x40, 0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad,\ + 0x07, 0x61, 0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72, 0xc2, 0x40, 0x88, 0xbe,\ + 0x94, 0x76, 0x9f, 0xd1, 0x66, 0x50,\ + /* order */\ + 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x51, 0x86,\ + 0x87, 0x83, 0xBF, 0x2F, 0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09,\ + 0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C, 0x47, 0xAE, 0xBB, 0x6F,\ + 0xB7, 0x1E, 0x91, 0x38, 0x64, 0x09\ +} + +#define SM2_P256_V1_PARAM {\ + /* p */\ + 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + /* a */\ + 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc,\ + /* b */\ + 0x28, 0xe9, 0xfa, 0x9e, 0x9d, 0x9f, 0x5e, 0x34, 0x4d, 0x5a, 0x9e, 0x4b,\ + 0xcf, 0x65, 0x09, 0xa7, 0xf3, 0x97, 0x89, 0xf5, 0x15, 0xab, 0x8f, 0x92,\ + 0xdd, 0xbc, 0xbd, 0x41, 0x4d, 0x94, 0x0e, 0x93,\ + /* x */\ + 0x32, 0xc4, 0xae, 0x2c, 0x1f, 0x19, 0x81, 0x19, 0x5f, 0x99, 0x04, 0x46,\ + 0x6a, 0x39, 0xc9, 0x94, 0x8f, 0xe3, 0x0b, 0xbf, 0xf2, 0x66, 0x0b, 0xe1,\ + 0x71, 0x5a, 0x45, 0x89, 0x33, 0x4c, 0x74, 0xc7,\ + /* y */\ + 0xbc, 0x37, 0x36, 0xa2, 0xf4, 0xf6, 0x77, 0x9c, 0x59, 0xbd, 0xce, 0xe3,\ + 0x6b, 0x69, 0x21, 0x53, 0xd0, 0xa9, 0x87, 0x7c, 0xc6, 0x2a, 0x47, 0x40,\ + 0x02, 0xdf, 0x32, 0xe5, 0x21, 0x39, 0xf0, 0xa0,\ + /* order */\ + 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + 0xff, 0xff, 0xff, 0xff, 0x72, 0x03, 0xdf, 0x6b, 0x21, 0xc6, 0x05, 0x2b,\ + 0x53, 0xbb, 0xf4, 0x09, 0x39, 0xd5, 0x41, 0x23,\ +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/uadk/v1/test/Makefile.am b/uadk/v1/test/Makefile.am new file mode 100644 index 0000000..bd41cfe --- /dev/null +++ b/uadk/v1/test/Makefile.am @@ -0,0 +1,16 @@ +AM_CFLAGS=-Wall -O0 -fno-strict-aliasing -I$(top_srcdir)/v1/internal -I$(top_srcdir)/v1 -I$(srcdir)lib -pthread + +SUBDIRS=. test_mm bmm_test + +if HAVE_ZLIB +SUBDIRS+=hisi_zip_test +endif + +SUBDIRS+=hisi_zip_test_sgl +SUBDIRS+=hisi_trng_test + +if HAVE_CRYPTO +SUBDIRS+=hisi_hpre_test +SUBDIRS+=hisi_sec_test +SUBDIRS+=hisi_sec_test_sgl +endif diff --git a/uadk/v1/test/bmm.c b/uadk/v1/test/bmm.c new file mode 100644 index 0000000..e67bab8 --- /dev/null +++ b/uadk/v1/test/bmm.c @@ -0,0 +1,172 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include "v1/test/bmm.h" +#include "v1/wd.h" +#include "v1/wd_util.h" + +#define BITMAP_MAX_BYTE 32 +#define BITMAP_BYTE_OFFSET 5 +#define BITMAP_BIT_OFFSET 0x1F + +#define __ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask)) +#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1) + +#define TAG 0x0a0b0c0d + +struct mem_pool { + unsigned int tag; + void *base; + unsigned int mem_size; + unsigned int block_size; + unsigned int block_num; + unsigned int num_free; + unsigned int index; + unsigned long *bitmap; +}; + +/** + * Initial a continue memory region to be managed by bmm. + * + * @addr_base: the first address of the managed memory region; + * @mem_size: size of the region; + * @block_size: size of evry block; + * @align_size: size of block align; + */ +int bmm_init(void *addr_base, unsigned int mem_size, + unsigned int block_size, unsigned int align_size) +{ + struct mem_pool *mempool = (struct mem_pool *)addr_base; + unsigned int act_blksize; + unsigned int bitmap_sz; + + /* align_size must be 2^N */ + if ((align_size == 0) || (align_size & (align_size - 1))) + return -EINVAL; + + if (((uintptr_t)addr_base & (align_size - 1)) != 0) + return -EINVAL; + + /* actual_block_zise is determined by align_size and block_size de */ + act_blksize = ALIGN(block_size, align_size); +#ifndef NDEBUG + printf("\nact_blksize = %d, 0x%x\n", act_blksize, act_blksize); +#endif + if (mem_size <= act_blksize) + return -ENOMEM; + + memset(mempool, 0, sizeof(*mempool)); + + mempool->tag = TAG; + mempool->mem_size = mem_size; + mempool->block_size = act_blksize; + mempool->block_num = mem_size / act_blksize; + + bitmap_sz = (((mempool->block_num - 1) >> BITMAP_BYTE_OFFSET) + 1) * + sizeof(unsigned long); + + mempool->base = (void *)((uintptr_t)addr_base + bitmap_sz + + sizeof(struct mem_pool) + align_size); + + mempool->num_free = mempool->block_num; + mempool->bitmap = (unsigned long *)((uintptr_t)mempool->base + + (sizeof(struct mem_pool) + 1)); + if (bitmap_sz <= BITMAP_MAX_BYTE) + memset(mempool->bitmap, 0, bitmap_sz); + else + return -ENOMEM; + + return 0; +} + +void *bmm_alloc(void *pool) +{ + struct mem_pool *mempool = (struct mem_pool *)pool; + unsigned long long index_tmp = mempool->index; + unsigned long *bitmap_t = mempool->bitmap; + unsigned short bit_pos; + unsigned int byte_pos; + + ASSERT(mempool->tag == TAG); + + /* find the free block from the current index to the last one */ + for (; mempool->index < mempool->block_num; mempool->index++) { + byte_pos = mempool->index >> BITMAP_BYTE_OFFSET; + bit_pos = mempool->index & BITMAP_BIT_OFFSET; + + /* find the free block */ + if (((bitmap_t[byte_pos]) & (0x1 << bit_pos)) == 0) { + mempool->index++; + mempool->num_free--; + bitmap_t[byte_pos] = bitmap_t[byte_pos] | + (0x1 << bit_pos); + mempool->bitmap = bitmap_t; + pool = (void *)mempool; + return (void *)((uintptr_t)mempool->base + + (mempool->index - 1) * mempool->block_size); + } + } + + /* find the block from the first one to the current index */ + for (mempool->index = 0; mempool->index < index_tmp; mempool->index++) { + byte_pos = mempool->index >> BITMAP_BYTE_OFFSET; + bit_pos = mempool->index & BITMAP_BIT_OFFSET; + + /* find the free block */ + if (((bitmap_t[byte_pos]) & (0x1 << bit_pos)) == 0) { + mempool->index++; + mempool->num_free--; + bitmap_t[byte_pos] = bitmap_t[byte_pos] | + (0x01 << bit_pos); + + mempool->bitmap = bitmap_t; + pool = (void *)mempool; + return (void *)((uintptr_t)mempool->base + + (mempool->index - 1) * mempool->block_size); + } + } + + return NULL; +} + +void bmm_free(void *pool, const void *buf) +{ + struct mem_pool *mempool = (struct mem_pool *)pool; + unsigned long long addr_offset; + unsigned short bit_pos; + unsigned int byte_pos; + + ASSERT(mempool->tag == TAG); + + addr_offset = ((uintptr_t)buf - (uintptr_t)mempool->base) / + mempool->block_size; + if ((addr_offset + 1) > mempool->block_num) { + errno = EINVAL; + return; + } + + byte_pos = addr_offset >> BITMAP_BYTE_OFFSET; + bit_pos = ~(1 << addr_offset & BITMAP_BIT_OFFSET); + + mempool->bitmap[byte_pos] = mempool->bitmap[byte_pos] & bit_pos; + mempool->num_free++; +} diff --git a/uadk/v1/test/bmm.h b/uadk/v1/test/bmm.h new file mode 100644 index 0000000..7a24f9f --- /dev/null +++ b/uadk/v1/test/bmm.h @@ -0,0 +1,25 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#ifndef _BMM_H +#define _BMM_H + +int bmm_init(void *addr_base, unsigned int mem_size, unsigned int block_size, + unsigned int align_size); +void *bmm_alloc(void *pool); +void bmm_free(void *pool, const void *buf); + +#endif diff --git a/uadk/v1/test/bmm_test/Makefile.am b/uadk/v1/test/bmm_test/Makefile.am new file mode 100644 index 0000000..4346720 --- /dev/null +++ b/uadk/v1/test/bmm_test/Makefile.am @@ -0,0 +1,13 @@ +AM_CFLAGS=-Wall -O0 -fno-strict-aliasing -I$(top_srcdir)/v1/include -pthread + +if WITH_OPENSSL_DIR +bin_PROGRAMS=bmm_test + +bmm_test_SOURCES=bmm_test.c bmm_test.h + +if WD_STATIC_DRV +bmm_test_LDADD=../../../.libs/libwd.la +else +bmm_test_LDADD=../../../.libs/libwd.so +endif +endif diff --git a/uadk/v1/test/bmm_test/bmm_test.c b/uadk/v1/test/bmm_test/bmm_test.c new file mode 100644 index 0000000..4f8b560 --- /dev/null +++ b/uadk/v1/test/bmm_test/bmm_test.c @@ -0,0 +1,178 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include + +#include "bmm_test.h" +#include "../../wd.h" +#include "../../wd_bmm.h" +#include "../../wd_rsa.h" +#include "../../wd_dh.h" + +//#define USERS + +void *wd_alloc_test(); +void *wd_getfreeNum_test(); +void *wd_blk_alloc_failures_test(); +void *my_alloc(void *usr, size_t size); +void *my_dma_map(void *usr, void *va, size_t sz); + +struct wd_blkpool *pool; + +int test_alloc_free(unsigned int blk_sz, unsigned int blk_num, + unsigned int align_sz); + +int main(int argc, char *argv[]) +{ + if (argc != 4) { + printf("u can input ur own params,like this:\n"); + printf("%s blk_sz blk_num align_sz\n", argv[0]); + + printf("now we go as:\n %s 64, 64, 64\n\n", argv[0]); + test_alloc_free(64, 64, 64); + return 0; + } + + unsigned int blk_sz = atoi(argv[1]); + unsigned int blk_num = atoi(argv[2]); + unsigned int align_sz = atoi(argv[3]); + + test_alloc_free(blk_sz, blk_num, align_sz); + + return 0; +} + +int test_alloc_free(unsigned int blk_sz, unsigned int blk_num, + unsigned int align_sz) +{ + struct wd_blkpool_setup wsetup; + pthread_t pid[64]; + struct wd_queue q; + int ret = 0; + int i = 0; + + memset((void *)&q, 0, sizeof(q)); + q.capa.alg = "rsa"; + ret = wd_request_queue(&q); + if (ret) { + printf("request queue fail!\n"); + return ret; + } + + memset(&wsetup, 0, sizeof(wsetup)); + wsetup.block_size = blk_sz; //key_size; + wsetup.block_num = blk_num; + wsetup.align_size = align_sz; + +#ifdef USERS + /* for user's memory */ + wsetup.br.alloc = (void *)my_alloc; + wsetup.br.wd_iova_map = (void *)my_dma_map; +#endif + + pool = wd_blkpool_create(&q, &wsetup); + if (!pool) { + printf("%s(): create ctx pool fail!\n", __func__); + goto release_q; + } + + ret = pthread_create(&pid[0], NULL, wd_getfreeNum_test, NULL); + if (ret != 0) + printf("can't create thread: %s\n", strerror(ret)); + + ret = pthread_create(&pid[1], NULL, wd_blk_alloc_failures_test, NULL); + if (ret != 0) + printf("can't create thread: %s\n", strerror(ret)); + + for (i = 2; i < 64; i++) { + ret = pthread_create(&pid[i], NULL, wd_alloc_test, NULL); + if (ret != 0) + printf("can't create thread: %s\n", strerror(ret)); + + sleep(1); + } + + while (1) + sleep(1); + + for (i = 0; i < 64; i++) + pthread_join(pid[i], NULL); + +release_q: + wd_release_queue(&q); + + return 0; +} + +void *wd_alloc_test() +{ + void *blk; + + while (1) { + blk = wd_alloc_blk(pool); + printf("---alloc blk = %p\n", blk); + + printf("wd_iova_map %p = %p\n", blk, wd_blk_iova_map(pool, blk)); + + sleep(3); + if (blk) { + wd_free_blk(pool, blk); + printf("--- now free blk = 0x%p\n", blk); + } + sleep(2); + } +} + +void *wd_getfreeNum_test() +{ + unsigned int num = 0; + + while (1) { + if (wd_get_free_blk_num(pool, &num) == WD_SUCCESS) + printf("free num = %u\n", num); + sleep(1); + } +} + +void *wd_blk_alloc_failures_test() +{ + unsigned int num = 0; + + while (1) { + if (wd_blk_alloc_failures(pool, &num) == WD_SUCCESS) + printf("alloc_fail_num = %u\n", num); + sleep(1); + } +} + +void *my_alloc(void *usr, size_t size) +{ + void *ptr; + + ptr = malloc(size); + if (!ptr) + return NULL; + + return ptr; +} + +void *my_dma_map(void *usr, void *va, size_t sz) +{ + return NULL; +} diff --git a/uadk/v1/test/bmm_test/bmm_test.h b/uadk/v1/test/bmm_test/bmm_test.h new file mode 100644 index 0000000..5be1040 --- /dev/null +++ b/uadk/v1/test/bmm_test/bmm_test.h @@ -0,0 +1,20 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#ifndef TEST_BMM +#define TEST_BMM + +#endif diff --git a/uadk/v1/test/hisi_hpre_test/Makefile.am b/uadk/v1/test/hisi_hpre_test/Makefile.am new file mode 100644 index 0000000..c124bd6 --- /dev/null +++ b/uadk/v1/test/hisi_hpre_test/Makefile.am @@ -0,0 +1,23 @@ +AM_CFLAGS=-Wall -O0 -fno-strict-aliasing -I$(top_srcdir) -I$(top_srcdir)/v1/internal -pthread + +if WITH_OPENSSL_DIR +bin_PROGRAMS=test_hisi_hpre hpre_test_tools test_hisi_hpre_times + +test_hisi_hpre_SOURCES=test_hisi_hpre.c test_hisi_hpre.h +hpre_test_tools_SOURCES=hpre_test_tools.c +test_hisi_hpre_times_SOURCES=test_hisi_hpre_times.c test_hisi_hpre.h hpre_test_sample.h + +if WD_STATIC_DRV +test_hisi_hpre_LDADD=../../../.libs/libwd.la +hpre_test_tools_LDADD=../../../.libs/libwd.la +test_hisi_hpre_times_LDADD=../../../.libs/libwd.la +else +test_hisi_hpre_LDADD=../../../.libs/libwd.so +hpre_test_tools_LDADD=../../../.libs/libwd.so +test_hisi_hpre_times_LDADD=../../../.libs/libwd.so +endif + +test_hisi_hpre_LDADD+=$(with_openssl_dir)/libcrypto_wd.so +hpre_test_tools_LDADD+=$(with_openssl_dir)/libcrypto_wd.so +test_hisi_hpre_times_LDADD+=$(with_openssl_dir)/libcrypto_wd.so +endif diff --git a/uadk/v1/test/hisi_hpre_test/hpre_test_sample.h b/uadk/v1/test/hisi_hpre_test/hpre_test_sample.h new file mode 100644 index 0000000..a6b7ba7 --- /dev/null +++ b/uadk/v1/test/hisi_hpre_test/hpre_test_sample.h @@ -0,0 +1,1497 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#ifndef __HPRE_TEST_SAMPLE_H +#define __HPRE_TEST_SAMPLE_H + +/******************************* X25519 *********************************/ +/********************* big-endian ************************/ +#if 0 +static unsigned char x25519_p_param[] = { +/* p = (2 ^ 255 - 19) */ + 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xed +}; +static unsigned char x25519_a_param[] = { + /* a = (486662 - 2) / 4 = 121665*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xDB, 0x41 +}; + +static unsigned char x25519_x_param_big[] = { + /* x */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09 +}; +#endif + +/* *** up: related of curve, down: keys *** */ +/********************* little-endian************************/ +static unsigned char x25519_x_param[] = { + /* x */ + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static unsigned char x25519_aprikey[] = { + 0x77, 0x07, 0x6d, 0x0a, 0x73, 0x18, 0xa5, 0x7d, 0x3c, 0x16, 0xc1, 0x72,\ + 0x51, 0xb2, 0x66, 0x45, 0xdf, 0x4c, 0x2f, 0x87, 0xeb, 0xc0, 0x99, 0x2a,\ + 0xb1, 0x77, 0xfb, 0xa5, 0x1d, 0xb9, 0x2c, 0x2a +}; + +#if 0 +/* Used for comparing after performance test */ +static unsigned char x25519_apubkey[] = { + 0x85, 0x20, 0xf0, 0x09, 0x89, 0x30, 0xa7, 0x54, 0x74, 0x8b, 0x7d, 0xdc,\ + 0xb4, 0x3e, 0xf7, 0x5a, 0x0d, 0xbf, 0x3a, 0x0d, 0x26, 0x38, 0x1a, 0xf4,\ + 0xeb, 0xa4, 0xa9, 0x8e, 0xaa, 0x9b, 0x4e, 0x6a +}; +#endif + +static unsigned char x25519_bpubkey[] = { + 0xde, 0x9e, 0xdb, 0x7d, 0x7b, 0x7d, 0xc1, 0xb4, 0xd3, 0x5b, 0x61, 0xc2,\ + 0xec, 0xe4, 0x35, 0x37, 0x3f, 0x83, 0x43, 0xc8, 0x5b, 0x78, 0x67, 0x4d,\ + 0xad, 0xfc, 0x7e, 0x14, 0x6f, 0x88, 0x2b, 0x4f +}; + +#if 0 +/* Used for comparing after performance test */ +static unsigned char x25519_absharekey[] = { + 0x4A, 0x5D, 0x9D, 0x5B, 0xA4, 0xCE, 0x2D, 0xE1, 0x72, 0x8E, 0x3B, 0xF4,\ + 0x80, 0x35, 0x0F, 0x25, 0xE0, 0x7E, 0x21, 0xC9, 0x47, 0xD1, 0x9E, 0x33,\ + 0x76, 0xF0, 0x9B, 0x3C, 0x1E, 0x16, 0x17, 0x42 +}; +#endif + +/* *** big-endian *** */ +static unsigned char x25519_aprikey_big[] = { + 0x2a, 0x2c, 0xb9, 0x1d, 0xa5, 0xfb, 0x77, 0xb1, 0x2a, 0x99, 0xc0, 0xeb,\ + 0x87, 0x2f, 0x4c, 0xdf, 0x45, 0x66, 0xb2, 0x51, 0x72, 0xc1, 0x16, 0x3c,\ + 0x7d, 0xa5, 0x18, 0x73, 0x0a, 0x6d, 0x07, 0x77 +}; + +static unsigned char x25519_apubke_big[] = { + 0x6a, 0x4e, 0x9b, 0xaa, 0x8e, 0xa9, 0xa4, 0xeb, 0xf4, 0x1a, 0x38, 0x26,\ + 0x0d, 0x3a, 0xbf, 0x0d, 0x5a, 0xf7, 0x3e, 0xb4, 0xdc, 0x7d, 0x8b, 0x74,\ + 0x54, 0xa7, 0x30, 0x89, 0x09, 0xf0, 0x20, 0x85 +}; + +static unsigned char x25519_bpubkey_big[] = { + 0x4f, 0x2b, 0x88, 0x6f, 0x14, 0x7e, 0xfc, 0xad, 0x4d, 0x67, 0x78, 0x5b,\ + 0xc8, 0x43, 0x83, 0x3f, 0x37, 0x35, 0xe4, 0xec, 0xc2, 0x61, 0x5b, 0xd3,\ + 0xb4, 0xc1, 0x7d, 0x7b, 0x7d, 0xdb, 0x9e, 0xde +}; + +static unsigned char x25519_absharekey_big[] = { + 0x42, 0x17, 0x16, 0x1e, 0x3c, 0x9b, 0xf0, 0x76, 0x33, 0x9e, 0xd1, 0x47,\ + 0xc9, 0x21, 0x7e, 0xe0, 0x25, 0x0f, 0x35, 0x80, 0xf4, 0x3b, 0x8e, 0x72,\ + 0xe1, 0x2d, 0xce, 0xa4, 0x5b, 0x9d, 0x5d, 0x4a +}; + +/******************************* X448 *********************************/ +/********************* big-endian ************************/ +#if 0 +static unsigned char x448_p_param[] = { + /* p = (2 ^ 448 - 2 ^ 224 - 1) */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +static unsigned char x448_a_param[] = { + /* a = (156326 - 2) / 4 = 39081*/\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0xA9 +}; + +static unsigned char x448_x_param_big[] = { + /* x */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05 +}; +#endif + +/* *** up: related of curve, down: keys *** */ +/********************* little-endian ************************/ +static unsigned char x448_x_param[] = { + /* x */ + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +static unsigned char x448_aprikey[] = { + 0x9a, 0x8f, 0x49, 0x25, 0xd1, 0x51, 0x9f, 0x57, 0x75, 0xcf, 0x46, 0xb0,\ + 0x4b, 0x58, 0x00, 0xd4, 0xee, 0x9e, 0xe8, 0xba, 0xe8, 0xbc, 0x55, 0x65,\ + 0xd4, 0x98, 0xc2, 0x8d, 0xd9, 0xc9, 0xba, 0xf5, 0x74, 0xa9, 0x41, 0x97,\ + 0x44, 0x89, 0x73, 0x91, 0x00, 0x63, 0x82, 0xa6, 0xf1, 0x27, 0xab, 0x1d,\ + 0x9a, 0xc2, 0xd8, 0xc0, 0xa5, 0x98, 0x72, 0x6b +}; + +#if 0 +/* Used for comparing after performance test */ +static unsigned char x448_apubkey[] = { + 0x9b, 0x08, 0xf7, 0xcc, 0x31, 0xb7, 0xe3, 0xe6, 0x7d, 0x22, 0xd5, 0xae,\ + 0xa1, 0x21, 0x07, 0x4a, 0x27, 0x3b, 0xd2, 0xb8, 0x3d, 0xe0, 0x9c, 0x63,\ + 0xfa, 0xa7, 0x3d, 0x2c, 0x22, 0xc5, 0xd9, 0xbb, 0xc8, 0x36, 0x64, 0x72,\ + 0x41, 0xd9, 0x53, 0xd4, 0x0c, 0x5b, 0x12, 0xda, 0x88, 0x12, 0x0d, 0x53,\ + 0x17, 0x7f, 0x80, 0xe5, 0x32, 0xc4, 0x1f, 0xa0 +}; +#endif + +static unsigned char x448_bpubkey[] = { + 0x3e, 0xb7, 0xa8, 0x29, 0xb0, 0xcd, 0x20, 0xf5, 0xbc, 0xfc, 0x0b, 0x59,\ + 0x9b, 0x6f, 0xec, 0xcf, 0x6d, 0xa4, 0x62, 0x71, 0x07, 0xbd, 0xb0, 0xd4,\ + 0xf3, 0x45, 0xb4, 0x30, 0x27, 0xd8, 0xb9, 0x72, 0xfc, 0x3e, 0x34, 0xfb,\ + 0x42, 0x32, 0xa1, 0x3c, 0xa7, 0x06, 0xdc, 0xb5, 0x7a, 0xec, 0x3d, 0xae,\ + 0x07, 0xbd, 0xc1, 0xc6, 0x7b, 0xf3, 0x36, 0x09 +}; + +#if 0 +/* Used for comparing after performance test */ +static unsigned char x448_absharekey[] = { + 0x07, 0xff, 0xf4, 0x18, 0x1a, 0xc6, 0xcc, 0x95, 0xec, 0x1c, 0x16, 0xa9,\ + 0x4a, 0x0f, 0x74, 0xd1, 0x2d, 0xa2, 0x32, 0xce, 0x40, 0xa7, 0x75, 0x52,\ + 0x28, 0x1d, 0x28, 0x2b, 0xb6, 0x0c, 0x0b, 0x56, 0xfd, 0x24, 0x64, 0xc3,\ + 0x35, 0x54, 0x39, 0x36, 0x52, 0x1c, 0x24, 0x40, 0x30, 0x85, 0xd5, 0x9a,\ + 0x44, 0x9a, 0x50, 0x37, 0x51, 0x4a, 0x87, 0x9d +}; +#endif + +/* *** big-endian *** */ +static unsigned char x448_aprikey_big[] = { + 0x6b, 0x72, 0x98, 0xa5, 0xc0, 0xd8, 0xc2, 0x9a, 0x1d, 0xab, 0x27, 0xf1,\ + 0xa6, 0x82, 0x63, 0x00, 0x91, 0x73, 0x89, 0x44, 0x97, 0x41, 0xa9, 0x74,\ + 0xf5, 0xba, 0xc9, 0xd9, 0x8d, 0xc2, 0x98, 0xd4, 0x65, 0x55, 0xbc, 0xe8,\ + 0xba, 0xe8, 0x9e, 0xee, 0xd4, 0x00, 0x58, 0x4b, 0xb0, 0x46, 0xcf, 0x75,\ + 0x57, 0x9f, 0x51, 0xd1, 0x25, 0x49, 0x8f, 0x9a +}; + +static unsigned char x448_apubkey_big[] = { + 0xa0, 0x1f, 0xc4, 0x32, 0xe5, 0x80, 0x7f, 0x17, 0x53, 0x0d, 0x12, 0x88,\ + 0xda, 0x12, 0x5b, 0x0c, 0xd4, 0x53, 0xd9, 0x41, 0x72, 0x64, 0x36, 0xc8,\ + 0xbb, 0xd9, 0xc5, 0x22, 0x2c, 0x3d, 0xa7, 0xfa, 0x63, 0x9c, 0xe0, 0x3d,\ + 0xb8, 0xd2, 0x3b, 0x27, 0x4a, 0x07, 0x21, 0xa1, 0xae, 0xd5, 0x22, 0x7d,\ + 0xe6, 0xe3, 0xb7, 0x31, 0xcc, 0xf7, 0x08, 0x9b +}; + +static unsigned char x448_bpubkey_big[] = { + 0x09, 0x36, 0xf3, 0x7b, 0xc6, 0xc1, 0xbd, 0x07, 0xae, 0x3d, 0xec, 0x7a,\ + 0xb5, 0xdc, 0x06, 0xa7, 0x3c, 0xa1, 0x32, 0x42, 0xfb, 0x34, 0x3e, 0xfc,\ + 0x72, 0xb9, 0xd8, 0x27, 0x30, 0xb4, 0x45, 0xf3, 0xd4, 0xb0, 0xbd, 0x07,\ + 0x71, 0x62, 0xa4, 0x6d, 0xcf, 0xec, 0x6f, 0x9b, 0x59, 0x0b, 0xfc, 0xbc,\ + 0xf5, 0x20, 0xcd, 0xb0, 0x29, 0xa8, 0xb7, 0x3e +}; + +static unsigned char x448_absharekey_big[] = { + 0x9d, 0x87, 0x4a, 0x51, 0x37, 0x50, 0x9a, 0x44, 0x9a, 0xd5, 0x85, 0x30,\ + 0x40, 0x24, 0x1c, 0x52, 0x36, 0x39, 0x54, 0x35, 0xc3, 0x64, 0x24, 0xfd,\ + 0x56, 0x0b, 0x0c, 0xb6, 0x2b, 0x28, 0x1d, 0x28, 0x52, 0x75, 0xa7, 0x40,\ + 0xce, 0x32, 0xa2, 0x2d, 0xd1, 0x74, 0x0f, 0x4a, 0xa9, 0x16, 0x1c, 0xec,\ + 0x95, 0xcc, 0xc6, 0x1a, 0x18, 0xf4, 0xff, 0x07 +}; +/*******i***************************************************************/ +static char dh_g_5[] = {0x05}; +static char dh_g_2[] = {0x02}; + +static char dh_p_768[] = { + 0xdd, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x01, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7 +}; + +static char dh_xa_768[] = { + 0xe0, 0x80, 0x86, 0x24, 0xe2, 0x20, 0x35, 0x97, 0xda, 0x0e, 0x68, 0x39, 0x01, 0xdd, 0x01, 0x87, + 0xa2, 0x47, 0xd2, 0x0d, 0xee, 0xfe, 0xdc, 0x5a, 0x37, 0x23, 0xeb, 0x3d, 0xe8, 0x1e, 0x39, 0x2d, + 0xbf, 0xa6, 0xe9, 0x17, 0x48, 0xe2, 0xea, 0xef, 0x1d, 0x2f, 0xe2, 0xaf, 0x3c, 0xbc, 0xae, 0xa7, + 0x42, 0x9b, 0xa5, 0x7d, 0x47, 0x8a, 0x20, 0xc5, 0xae, 0xa1, 0xe4, 0xe8, 0x1c, 0x05, 0xc0, 0x0a, + 0x05, 0xdc, 0x01, 0x74, 0xde, 0xad, 0xad, 0x07, 0xec, 0x6e, 0x6a, 0xc7, 0xee, 0x0f, 0xb8, 0xbe, + 0xaa, 0x46, 0x61, 0x8c, 0x12, 0x5a, 0xaf, 0x05, 0xff, 0x1b, 0x35, 0x6b, 0xe2, 0x3d, 0x48, 0x4f +}; + +#if 0 +static char dh_xb_768[] = { + 0x8b, 0xd9, 0xf8, 0x14, 0xe6, 0x42, 0x95, 0xbd, 0x9a, 0x96, 0xbe, 0xf4, 0x7d, 0x26, 0x5d, 0xa1, + 0x81, 0x9b, 0x1c, 0xec, 0xfe, 0xce, 0x9, 0x1d, 0xb7, 0x7a, 0xba, 0xca, 0x7f, 0x54, 0xee, 0x36, + 0x54, 0x65, 0x4a, 0xd0, 0x5c, 0x84, 0x8c, 0x3e, 0x1b, 0xfe, 0x91, 0x6f, 0x95, 0xb5, 0x76, 0xbf, + 0x61, 0x2a, 0x7, 0x23, 0x86, 0xb9, 0xe0, 0x19, 0x29, 0xcf, 0xea, 0x3a, 0x1, 0xbf, 0xee, 0x1b, + 0x5e, 0x3c, 0x4, 0xff, 0x1d, 0xcf, 0xa6, 0x56, 0xb3, 0x22, 0xbb, 0x45, 0x4b, 0x7f, 0x83, 0x87, + 0xef, 0x21, 0x5, 0xf7, 0x38, 0x1f, 0x6, 0x4d, 0x71, 0x0b, 0xe3, 0xe1, 0xb7, 0x7e, 0xae, 0x18 +}; +#endif + +static char dh_except_a_pubkey_768[] = { + 0xba, 0xe7, 0x3, 0x5b, 0xe4, 0x70, 0x8b, 0xe0, 0xe1, 0x92, 0x13, 0x86, 0x74, 0x4, 0xdc, 0x6a, + 0x0a, 0x2a, 0x20, 0xec, 0x6d, 0xbf, 0xf0, 0x46, 0xf7, 0x9, 0x2, 0xdb, 0x2f, 0x70, 0x11, 0xdd, + 0xb0, 0x13, 0xa2, 0xc1, 0x58, 0x74, 0x29, 0x19, 0x8d, 0x4a, 0x94, 0x80, 0x0b, 0xd7, 0x25, 0x85, + 0x10, 0x35, 0x97, 0x48, 0x6e, 0x70, 0x28, 0xae, 0x58, 0x97, 0x7d, 0xf2, 0x19, 0x27, 0x13, 0xab, + 0x47, 0x9b, 0x54, 0xdf, 0xc3, 0x5b, 0x5f, 0x5e, 0xb4, 0x64, 0x47, 0xce, 0x40, 0x3b, 0x0c, 0x4a, + 0x62, 0x52, 0xba, 0xc7, 0xf0, 0x36, 0x87, 0x9c, 0x79, 0x9a, 0x83, 0x11, 0x61, 0x0c, 0x1b, 0x6b +}; + +static char dh_except_b_pubkey_768[] = { + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x1, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7 +}; + +static char dh_share_key_768[] = { + 0x55, 0x9, 0x6b, 0x9c, 0xc6, 0x37, 0xa9, 0x9b, 0xdf, 0x67, 0x73, 0x7b, 0x46, 0xf9, 0x63, 0x47, + 0xcb, 0xa0, 0x57, 0x2a, 0xed, 0x97, 0x2f, 0xfe, 0x92, 0xf2, 0x20, 0x2c, 0x7e, 0xee, 0x7d, 0x11, + 0x78, 0xe6, 0xb9, 0x9, 0xd1, 0x94, 0xce, 0xd1, 0x5b, 0xf4, 0x44, 0xa9, 0xcb, 0x26, 0x2, 0x36, + 0x57, 0x2c, 0xa2, 0xbe, 0x37, 0xde, 0x86, 0x46, 0x20, 0x27, 0x9d, 0xa0, 0x2f, 0x4, 0xc1, 0xcd, + 0xff, 0x81, 0xe5, 0xe6, 0x2c, 0x9e, 0x39, 0x82, 0x31, 0x54, 0x33, 0xf8, 0xe7, 0xa0, 0xe5, 0x96, + 0xa4, 0x40, 0xc4, 0x44, 0xfe, 0x93, 0x66, 0xe2, 0xda, 0xaa, 0xb8, 0xfb, 0x2f, 0x3b, 0x8c, 0xce, +}; + +static char dh_p_1024[] = { + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x07, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x03, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x01, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7 +}; + +static char dh_xa_1024[] = { + 0x0f, 0x2a, 0x77, 0x25, 0x4b, 0xb3, 0xd3, 0x2d, 0xfd, 0x94, 0x8b, 0x53, 0x02, 0x21, 0x40, 0xd7, + 0x36, 0x76, 0xf3, 0xc8, 0xc0, 0x36, 0x3d, 0x23, 0xc9, 0xbd, 0x92, 0x51, 0xf2, 0x4b, 0x83, 0x15, + 0xe0, 0x80, 0x86, 0x24, 0xe2, 0x20, 0x35, 0x97, 0xda, 0x0e, 0x68, 0x39, 0x01, 0xdd, 0x01, 0x87, + 0xa2, 0x47, 0xd2, 0x0d, 0xee, 0xfe, 0xdc, 0x5a, 0x37, 0x23, 0xeb, 0x3d, 0xe8, 0x1e, 0x39, 0x2d, + 0xbf, 0xa6, 0xe9, 0x17, 0x48, 0xe2, 0xea, 0xef, 0x1d, 0x2f, 0xe2, 0xaf, 0x3c, 0xbc, 0xae, 0xa7, + 0x42, 0x9b, 0xa5, 0x7d, 0x47, 0x8a, 0x20, 0xc5, 0xae, 0xa1, 0xe4, 0xe8, 0x1c, 0x05, 0xc0, 0x0a, + 0x05, 0xdc, 0x01, 0x74, 0xde, 0xad, 0xad, 0x07, 0xec, 0x6e, 0x6a, 0xc7, 0xee, 0x0f, 0xb8, 0xbe, + 0xaa, 0x46, 0x61, 0x8c, 0x12, 0x5a, 0xaf, 0x05, 0xff, 0x1b, 0x35, 0x6b, 0xe2, 0x3d, 0x48, 0x4f +}; + +#if 0 +static char dh_xb_1024[] = { + 0x5e, 0x21, 0x0a, 0x9e, 0x3, 0xdd, 0x3f, 0xcc, 0x38, 0xf6, 0xa9, 0xa6, 0xf8, 0xfd, 0x15, 0x7d, + 0x67, 0x4e, 0x14, 0xae, 0x4d, 0xe2, 0x1f, 0x78, 0x77, 0xfb, 0x83, 0x5f, 0x48, 0xa8, 0xc8, 0x21, + 0x8b, 0xd9, 0xf8, 0x14, 0xe6, 0x42, 0x95, 0xbd, 0x9a, 0x96, 0xbe, 0xf4, 0x7d, 0x26, 0x5d, 0xa1, + 0x81, 0x9b, 0x1c, 0xec, 0xfe, 0xce, 0x9, 0x1d, 0xb7, 0x7a, 0xba, 0xca, 0x7f, 0x54, 0xee, 0x36, + 0x54, 0x65, 0x4a, 0xd0, 0x5c, 0x84, 0x8c, 0x3e, 0x1b, 0xfe, 0x91, 0x6f, 0x95, 0xb5, 0x76, 0xbf, + 0x61, 0x2a, 0x7, 0x23, 0x86, 0xb9, 0xe0, 0x19, 0x29, 0xcf, 0xea, 0x3a, 0x1, 0xbf, 0xee, 0x1b, + 0x5e, 0x3c, 0x4, 0xff, 0x1d, 0xcf, 0xa6, 0x56, 0xb3, 0x22, 0xbb, 0x45, 0x4b, 0x7f, 0x83, 0x87, + 0xef, 0x21, 0x5, 0xf7, 0x38, 0x1f, 0x6, 0x4d, 0x71, 0x0b, 0xe3, 0xe1, 0xb7, 0x7e, 0xae, 0x18 +}; +#endif + +static char dh_except_a_pubkey_1024[] = { + 0x5d, 0xa6, 0x7, 0x56, 0x93, 0x89, 0xe5, 0x0f, 0x2a, 0xb5, 0x67, 0x3a, 0xcf, 0xc3, 0x82, 0x83, + 0xf6, 0x88, 0x52, 0x0b, 0xfc, 0x6a, 0x5b, 0x1a, 0x57, 0x87, 0x86, 0xef, 0xda, 0x47, 0xdb, 0x4d, + 0xba, 0xe7, 0x3, 0x5b, 0xe4, 0x70, 0x8b, 0xe0, 0xe1, 0x92, 0x13, 0x86, 0x74, 0x4, 0xdc, 0x6a, + 0x0a, 0x2a, 0x20, 0xec, 0x6d, 0xbf, 0xf0, 0x46, 0xf7, 0x9, 0x2, 0xdb, 0x2f, 0x70, 0x11, 0xdd, + 0xb0, 0x13, 0xa2, 0xc1, 0x58, 0x74, 0x29, 0x19, 0x8d, 0x4a, 0x94, 0x80, 0x0b, 0xd7, 0x25, 0x85, + 0x10, 0x35, 0x97, 0x48, 0x6e, 0x70, 0x28, 0xae, 0x58, 0x97, 0x7d, 0xf2, 0x19, 0x27, 0x13, 0xab, + 0x47, 0x9b, 0x54, 0xdf, 0xc3, 0x5b, 0x5f, 0x5e, 0xb4, 0x64, 0x47, 0xce, 0x40, 0x3b, 0x0c, 0x4a, + 0x62, 0x52, 0xba, 0xc7, 0xf0, 0x36, 0x87, 0x9c, 0x79, 0x9a, 0x83, 0x11, 0x61, 0x0c, 0x1b, 0x6b +}; + +static char dh_except_b_pubkey_1024[] = { + 0x4a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x7, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x3, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x1, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7 +}; + +static char dh_share_key_1024[] = { + 0xcc, 0x48, 0x97, 0xe4, 0x21, 0x65, 0xa6, 0x55, 0xb8, 0xf3, 0xb2, 0x7b, 0x91, 0xd7, 0xca, 0xb9, + 0x17, 0x58, 0x31, 0x71, 0xc0, 0xc9, 0x69, 0x1e, 0xf0, 0x9e, 0x3f, 0xe2, 0x37, 0x4, 0x2d, 0xa8, + 0x55, 0x9, 0x6b, 0x9c, 0xc6, 0x37, 0xa9, 0x9b, 0xdf, 0x67, 0x73, 0x7b, 0x46, 0xf9, 0x63, 0x47, + 0xcb, 0xa0, 0x57, 0x2a, 0xed, 0x97, 0x2f, 0xfe, 0x92, 0xf2, 0x20, 0x2c, 0x7e, 0xee, 0x7d, 0x11, + 0x78, 0xe6, 0xb9, 0x9, 0xd1, 0x94, 0xce, 0xd1, 0x5b, 0xf4, 0x44, 0xa9, 0xcb, 0x26, 0x2, 0x36, + 0x57, 0x2c, 0xa2, 0xbe, 0x37, 0xde, 0x86, 0x46, 0x20, 0x27, 0x9d, 0xa0, 0x2f, 0x4, 0xc1, 0xcd, + 0xff, 0x81, 0xe5, 0xe6, 0x2c, 0x9e, 0x39, 0x82, 0x31, 0x54, 0x33, 0xf8, 0xe7, 0xa0, 0xe5, 0x96, + 0xa4, 0x40, 0xc4, 0x44, 0xfe, 0x93, 0x66, 0xe2, 0xda, 0xaa, 0xb8, 0xfb, 0x2f, 0x3b, 0x8c, 0xce, +}; + +static char dh_p_1536[] = { + 0xe3,0x7d,0xa7,0x4a,0xcc,0xef,0xce,0xa6,0xde,0x1d,0x3d,0xc5,0x2b,0xaa,0x6b,0x83, + 0xec,0x87,0x60,0xcd,0xc6,0xe4,0x16,0x0d,0xe7,0xb9,0x20,0x0e,0x10,0x50,0x35,0x22, + 0xd6,0xdb,0xbf,0x6,0xcc,0x7b,0x8e,0xe1,0x68,0x38,0x76,0x5f,0x0a,0x68,0xa8,0xfd, + 0x3f,0x40,0x51,0x46,0x45,0x64,0x53,0x22,0xcf,0x8,0xe2,0xef,0xd2,0x6f,0x28,0x84, + 0x14,0xb3,0xa6,0x24,0x49,0x6f,0x49,0x6c,0x0a,0x13,0xb6,0x78,0x4f,0xa4,0xd0,0xc4, + 0x20,0x6c,0x7,0x4c,0x6b,0xf7,0x8c,0x72,0x16,0x6c,0x99,0xd2,0x44,0x9e,0x63,0x5, + 0xfc,0x3a,0xa9,0x33,0x16,0x0b,0xc4,0x1a,0xf0,0xc7,0x25,0xcd,0xc6,0x3a,0x8e,0x66, + 0xa2,0xeb,0x70,0xb9,0x59,0xd9,0xb7,0xdd,0x68,0x45,0x26,0x20,0xfa,0x58,0x6f,0xd6, + 0x3f,0xd8,0xf2,0x52,0xd5,0x3a,0x16,0x7,0xdd,0xb4,0x63,0x0c,0xfe,0x8,0x67,0xd0, + 0x9f,0x8a,0xe0,0xe9,0x25,0xa0,0x0e,0x5,0x8e,0xe5,0x56,0xa6,0xc3,0x5b,0x0b,0xb5, + 0x41,0x33,0xd0,0xdb,0x89,0xbd,0x3b,0xaf,0x33,0x7e,0xae,0xff,0x20,0xef,0xa9,0x3c, + 0xd7,0xb5,0x45,0x61,0x50,0x76,0x60,0x89,0x6a,0xbb,0x9c,0x3e,0xcb,0xcb,0xdb,0x0b, +}; + +static char dh_xa_1536[] = { + 0x56,0x68,0x23,0x22,0x49,0x24,0xf2,0x21,0xee,0x5f,0x12,0x46,0xe2,0xea,0x69,0x93, + 0x0,0xf5,0x10,0x1d,0x4d,0x96,0x7b,0xa4,0x9d,0xab,0xbe,0xdf,0x8e,0xcc,0xa5,0x0e, + 0x84,0x12,0x4e,0x77,0xc0,0x46,0x6b,0x51,0x11,0x46,0x4f,0x73,0x1e,0x1c,0x1c,0xd1, + 0x3,0xea,0x0e,0x11,0xdb,0xa3,0xa6,0x14,0xdb,0xdc,0x3e,0xc5,0x7f,0x7d,0x7a,0x69, + 0xa1,0x38,0x70,0x95,0xa5,0x2d,0x47,0xa3,0x0f,0xcf,0xf9,0x7c,0x2,0x4e,0x52,0x4c, + 0xd6,0x5b,0x9e,0xf3,0x7f,0x64,0x70,0x13,0x59,0x8e,0x44,0x31,0x92,0x1b,0xb4,0xaa, + 0xf9,0x64,0xfd,0xb7,0x3c,0x81,0xc0,0xf9,0x66,0x5d,0xff,0x9,0x3e,0x26,0xaf,0x1a, + 0xc0,0xd2,0xd9,0x7c,0x0e,0x6f,0x81,0x12,0x82,0x90,0x1b,0x37,0xb7,0x1a,0x7e,0x36, + 0x79,0x15,0xb1,0xe1,0xd5,0x2d,0x72,0xd4,0x47,0xf7,0x30,0x3c,0x17,0xe1,0x76,0x15, + 0xbc,0x17,0xdc,0x9d,0xd9,0xfc,0xfd,0xb6,0xe6,0xbd,0x8e,0x47,0x8d,0xbb,0xa8,0x8a, + 0xe7,0xe7,0x57,0xf2,0xd8,0x80,0x4c,0xdd,0xe7,0xaf,0x29,0xee,0x40,0x4e,0x2,0xad, + 0xec,0xb3,0x18,0x8e,0x4b,0x2d,0xd2,0x28,0x4e,0x58,0x85,0x29,0xe3,0x93,0x1b,0xa7, +}; + +#if 0 +static char dh_xb_1536[] = { + 0x5c, 0xdf, 0x3, 0x2f, 0x18, 0xac, 0xbc, 0xeb, 0x95, 0xa2, 0x33, 0x70, 0x39, 0x13, 0x92, 0x7e, + 0x91, 0x19, 0x89, 0xd4, 0x0, 0xd1, 0xc5, 0x7e, 0x32, 0xb7, 0x4a, 0xd2, 0xff, 0x11, 0x7a, 0x9b, + 0x2, 0x84, 0xd0, 0x8e, 0x19, 0x91, 0x34, 0xc2, 0x5, 0xff, 0xe4, 0xf4, 0xd8, 0xcf, 0xc8, 0xa0, + 0xeb, 0x19, 0xb9, 0x69, 0x60, 0xcd, 0xa8, 0xda, 0x33, 0xbc, 0xa7, 0x80, 0x0, 0x92, 0x27, 0xe0, + 0xe7, 0x34, 0x77, 0x1f, 0xfd, 0x56, 0x0, 0x0c, 0x57, 0x0, 0x6d, 0x47, 0xe4, 0x32, 0xd7, 0x22, + 0x64, 0xa5, 0x33, 0x65, 0x33, 0x3e, 0x7c, 0x4e, 0x9d, 0xa6, 0xb7, 0x8b, 0xd7, 0xaa, 0x72, 0xe5, + 0x9d, 0xd5, 0xb4, 0x25, 0xcb, 0x30, 0x2, 0xfc, 0xb5, 0xae, 0xb3, 0x88, 0x67, 0x55, 0x0a, 0x7e, + 0x9d, 0xe8, 0x32, 0xfb, 0x50, 0x79, 0x4e, 0x9b, 0x21, 0x92, 0x25, 0x3, 0xa0, 0x15, 0x52, 0x3d, + 0x5e, 0x21, 0x0a, 0x9e, 0x3, 0xdd, 0x3f, 0xcc, 0x38, 0xf6, 0xa9, 0xa6, 0xf8, 0xfd, 0x15, 0x7d, + 0x67, 0x4e, 0x14, 0xae, 0x4d, 0xe2, 0x1f, 0x78, 0x77, 0xfb, 0x83, 0x5f, 0x48, 0xa8, 0xc8, 0x21, + 0x8b, 0xd9, 0xf8, 0x14, 0xe6, 0x42, 0x95, 0xbd, 0x9a, 0x96, 0xbe, 0xf4, 0x7d, 0x26, 0x5d, 0xa1, + 0x81, 0x9b, 0x1c, 0xec, 0xfe, 0xce, 0x9, 0x1d, 0xb7, 0x7a, 0xba, 0xca, 0x7f, 0x54, 0xee, 0x36, +}; +#endif + +static char dh_except_a_pubkey_1536[] = { + 0x97,0x1e,0x6d,0xf7,0xb1,0x2f,0xa7,0x82,0x9e,0x99,0x22,0xfb,0xf3,0x4e,0x2a,0x73, + 0xcc,0xd9,0x2b,0x10,0x1,0xfb,0xac,0xf1,0x81,0xfe,0x78,0x3d,0x23,0xb0,0xcf,0x5c, + 0x95,0x69,0x36,0xc0,0x99,0x6a,0xd2,0x9c,0xf0,0x85,0x8d,0xda,0x5d,0xba,0x8e,0x0f, + 0xa3,0xce,0xbe,0x9b,0xe8,0x3b,0xad,0x71,0xfd,0xfd,0x53,0x25,0xee,0x61,0x26,0x15, + 0x0a,0x46,0x9e,0xce,0x85,0xb1,0x5c,0xf1,0xa0,0x8f,0xe7,0x89,0xe3,0x4f,0x7c,0xea, + 0x18,0xd3,0xa9,0x44,0xce,0x35,0x9,0x86,0x80,0x8c,0x30,0x1,0xbc,0x6d,0xf6,0x6a, + 0x3a,0xa6,0xad,0xbe,0xfa,0x73,0x6b,0xb0,0x35,0x8c,0x63,0x80,0xb6,0x58,0x51,0x6e, + 0x4c,0x5d,0x4a,0xe9,0xa9,0x72,0x6,0x9f,0xa2,0x3e,0x64,0xaf,0x70,0x63,0xee,0x2a, + 0x5d,0x73,0xf3,0xdc,0xa3,0x32,0x0f,0x8,0x48,0xcf,0x13,0x80,0x0d,0xdb,0x91,0xdf, + 0x87,0x99,0xa4,0x8a,0x50,0xe9,0x75,0x43,0xfb,0x56,0xd7,0x89,0xc3,0x10,0x7e,0xd0, + 0xb7,0x46,0xd8,0x41,0x91,0xdf,0xb1,0x91,0x8e,0xc1,0x58,0xd7,0x7c,0x33,0x1e,0xb3, + 0xa3,0xda,0xcb,0xf5,0x0,0x76,0xe4,0xee,0x20,0xd6,0x9d,0x8a,0x28,0xa4,0xdb,0xf9, +}; + +static char dh_except_b_pubkey_1536[] = { + 0x44, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x9, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x4, 0xe8, 0x9a, 0xd2, 0x0, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x0, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x5, + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x7, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x3, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, +}; + +static char dh_share_key_1536[] = { + 0xaf, 0xd4, 0xf6, 0x45, 0x63, 0x21, 0x8d, 0x98, 0xc4, 0xab, 0x18, 0xd7, 0x2b, 0x3c, 0x1d, 0xde, + 0xe7, 0x1f, 0xe1, 0xc5, 0x79, 0x57, 0x60, 0x20, 0xfa, 0x99, 0xbd, 0x7b, 0xa2, 0x94, 0x0b, 0xa3, + 0xb4, 0xb3, 0x33, 0x4a, 0x2f, 0xd0, 0x17, 0x7, 0x2e, 0x70, 0x19, 0x84, 0x1f, 0x8e, 0xe9, 0x61, + 0xe5, 0x52, 0x3, 0x96, 0xea, 0xd8, 0xb6, 0x3, 0x9f, 0xc4, 0x3e, 0x23, 0x77, 0x17, 0x54, 0xfb, + 0x13, 0xf0, 0x3e, 0x9a, 0x27, 0x5d, 0x12, 0x99, 0x58, 0x8d, 0x41, 0x46, 0xd9, 0xc9, 0x29, 0xbd, + 0x40, 0xd1, 0x4f, 0xef, 0x63, 0x7b, 0x54, 0xe6, 0x59, 0x6d, 0xe2, 0x30, 0xe8, 0x2c, 0x2f, 0xf9, + 0x66, 0xa2, 0x12, 0xf5, 0x58, 0x61, 0xac, 0x43, 0xec, 0x7e, 0xf9, 0x2e, 0x27, 0x70, 0x35, 0x75, + 0xb4, 0x10, 0x29, 0xac, 0x0a, 0xab, 0x59, 0xb6, 0x68, 0x4c, 0x16, 0xaf, 0xf0, 0x4f, 0x21, 0xcd, + 0xcc, 0x48, 0x97, 0xe4, 0x21, 0x65, 0xa6, 0x55, 0xb8, 0xf3, 0xb2, 0x7b, 0x91, 0xd7, 0xca, 0xb9, + 0x17, 0x58, 0x31, 0x71, 0xc0, 0xc9, 0x69, 0x1e, 0xf0, 0x9e, 0x3f, 0xe2, 0x37, 0x4, 0x2d, 0xa8, + 0x55, 0x9, 0x6b, 0x9c, 0xc6, 0x37, 0xa9, 0x9b, 0xdf, 0x67, 0x73, 0x7b, 0x46, 0xf9, 0x63, 0x47, + 0xcb, 0xa0, 0x57, 0x2a, 0xed, 0x97, 0x2f, 0xfe, 0x92, 0xf2, 0x20, 0x2c, 0x7e, 0xee, 0x7d, 0x11, +}; + +static char dh_p_2048[] = { + 0xce, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x09, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x04, 0xe8, 0x9a, 0xd2, 0x00, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x00, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x05, + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x07, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x03, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x01, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7 +}; + +static char dh_xa_2048[] = { + 0x6b, 0x1f, 0xc4, 0x85, 0x98, 0xc3, 0x01, 0xda, 0x39, 0xf0, 0x1b, 0x76, 0x5d, 0x81, 0x1d, 0x1f, + 0xc9, 0x93, 0x95, 0xc1, 0xf8, 0xd1, 0x67, 0x2c, 0xd4, 0x0a, 0x67, 0xf0, 0x40, 0x86, 0x82, 0x7f, + 0x8f, 0x9d, 0x79, 0x04, 0xee, 0x4a, 0x54, 0xc9, 0x9c, 0x7f, 0xda, 0x15, 0x13, 0xc6, 0x95, 0xfb, + 0xfc, 0x7b, 0xe7, 0xd8, 0xde, 0x2a, 0xd8, 0xfd, 0xff, 0xdb, 0xa4, 0x7f, 0x4b, 0x37, 0x5d, 0x42, + 0xb6, 0x46, 0x4c, 0xbc, 0x34, 0x23, 0x99, 0x74, 0xf8, 0x80, 0x1b, 0xc1, 0x97, 0x34, 0xdf, 0x23, + 0x15, 0xa2, 0x8b, 0xec, 0xf3, 0x3e, 0x20, 0x93, 0x63, 0x88, 0x17, 0x70, 0x75, 0xbb, 0x9d, 0xb8, + 0x32, 0xb0, 0xae, 0xb5, 0x24, 0x6a, 0x86, 0xf6, 0xc1, 0x60, 0x41, 0xc4, 0xf4, 0x95, 0x6e, 0x10, + 0x2f, 0xd8, 0x58, 0x56, 0x42, 0x82, 0x71, 0x85, 0x19, 0xde, 0x91, 0xf0, 0x2f, 0x30, 0x0c, 0x63, + 0x0f, 0x2a, 0x77, 0x25, 0x4b, 0xb3, 0xd3, 0x2d, 0xfd, 0x94, 0x8b, 0x53, 0x02, 0x21, 0x40, 0xd7, + 0x36, 0x76, 0xf3, 0xc8, 0xc0, 0x36, 0x3d, 0x23, 0xc9, 0xbd, 0x92, 0x51, 0xf2, 0x4b, 0x83, 0x15, + 0xe0, 0x80, 0x86, 0x24, 0xe2, 0x20, 0x35, 0x97, 0xda, 0x0e, 0x68, 0x39, 0x01, 0xdd, 0x01, 0x87, + 0xa2, 0x47, 0xd2, 0x0d, 0xee, 0xfe, 0xdc, 0x5a, 0x37, 0x23, 0xeb, 0x3d, 0xe8, 0x1e, 0x39, 0x2d, + 0xbf, 0xa6, 0xe9, 0x17, 0x48, 0xe2, 0xea, 0xef, 0x1d, 0x2f, 0xe2, 0xaf, 0x3c, 0xbc, 0xae, 0xa7, + 0x42, 0x9b, 0xa5, 0x7d, 0x47, 0x8a, 0x20, 0xc5, 0xae, 0xa1, 0xe4, 0xe8, 0x1c, 0x05, 0xc0, 0x0a, + 0x05, 0xdc, 0x01, 0x74, 0xde, 0xad, 0xad, 0x07, 0xec, 0x6e, 0x6a, 0xc7, 0xee, 0x0f, 0xb8, 0xbe, + 0xaa, 0x46, 0x61, 0x8c, 0x12, 0x5a, 0xaf, 0x05, 0xff, 0x1b, 0x35, 0x6b, 0xe2, 0x3d, 0x48, 0x4f +}; + +#if 0 +static char dh_xb_2048[] = { + 0x5c, 0xdf, 0x3, 0x2f, 0x18, 0xac, 0xbc, 0xeb, 0x95, 0xa2, 0x33, 0x70, 0x39, 0x13, 0x92, 0x7e, + 0x91, 0x19, 0x89, 0xd4, 0x0, 0xd1, 0xc5, 0x7e, 0x32, 0xb7, 0x4a, 0xd2, 0xff, 0x11, 0x7a, 0x9b, + 0x2, 0x84, 0xd0, 0x8e, 0x19, 0x91, 0x34, 0xc2, 0x5, 0xff, 0xe4, 0xf4, 0xd8, 0xcf, 0xc8, 0xa0, + 0xeb, 0x19, 0xb9, 0x69, 0x60, 0xcd, 0xa8, 0xda, 0x33, 0xbc, 0xa7, 0x80, 0x0, 0x92, 0x27, 0xe0, + 0xe7, 0x34, 0x77, 0x1f, 0xfd, 0x56, 0x0, 0x0c, 0x57, 0x0, 0x6d, 0x47, 0xe4, 0x32, 0xd7, 0x22, + 0x64, 0xa5, 0x33, 0x65, 0x33, 0x3e, 0x7c, 0x4e, 0x9d, 0xa6, 0xb7, 0x8b, 0xd7, 0xaa, 0x72, 0xe5, + 0x9d, 0xd5, 0xb4, 0x25, 0xcb, 0x30, 0x2, 0xfc, 0xb5, 0xae, 0xb3, 0x88, 0x67, 0x55, 0x0a, 0x7e, + 0x9d, 0xe8, 0x32, 0xfb, 0x50, 0x79, 0x4e, 0x9b, 0x21, 0x92, 0x25, 0x3, 0xa0, 0x15, 0x52, 0x3d, + 0x5e, 0x21, 0x0a, 0x9e, 0x3, 0xdd, 0x3f, 0xcc, 0x38, 0xf6, 0xa9, 0xa6, 0xf8, 0xfd, 0x15, 0x7d, + 0x67, 0x4e, 0x14, 0xae, 0x4d, 0xe2, 0x1f, 0x78, 0x77, 0xfb, 0x83, 0x5f, 0x48, 0xa8, 0xc8, 0x21, + 0x8b, 0xd9, 0xf8, 0x14, 0xe6, 0x42, 0x95, 0xbd, 0x9a, 0x96, 0xbe, 0xf4, 0x7d, 0x26, 0x5d, 0xa1, + 0x81, 0x9b, 0x1c, 0xec, 0xfe, 0xce, 0x9, 0x1d, 0xb7, 0x7a, 0xba, 0xca, 0x7f, 0x54, 0xee, 0x36, + 0x54, 0x65, 0x4a, 0xd0, 0x5c, 0x84, 0x8c, 0x3e, 0x1b, 0xfe, 0x91, 0x6f, 0x95, 0xb5, 0x76, 0xbf, + 0x61, 0x2a, 0x7, 0x23, 0x86, 0xb9, 0xe0, 0x19, 0x29, 0xcf, 0xea, 0x3a, 0x1, 0xbf, 0xee, 0x1b, + 0x5e, 0x3c, 0x4, 0xff, 0x1d, 0xcf, 0xa6, 0x56, 0xb3, 0x22, 0xbb, 0x45, 0x4b, 0x7f, 0x83, 0x87, + 0xef, 0x21, 0x5, 0xf7, 0x38, 0x1f, 0x6, 0x4d, 0x71, 0x0b, 0xe3, 0xe1, 0xb7, 0x7e, 0xae, 0x18 +}; +#endif + +static char dh_except_a_pubkey_2048[] = { + 0xa5, 0x24, 0x63, 0x20, 0xb2, 0x56, 0x9a, 0x94, 0x97, 0xf7, 0x88, 0x41, 0x35, 0xeb, 0x52, 0x37, + 0xa4, 0xf2, 0x74, 0x1b, 0x38, 0xe4, 0x4c, 0x8b, 0x4b, 0xd2, 0xa5, 0xad, 0xb8, 0x2f, 0x7b, 0x5a, + 0xfd, 0xbc, 0x9c, 0xe0, 0xea, 0x9e, 0x82, 0x3, 0x62, 0xe2, 0xdc, 0x6c, 0x56, 0x9, 0x2, 0x28, + 0xb8, 0x2d, 0xb8, 0x46, 0xaf, 0x3a, 0xf4, 0x51, 0xf7, 0x4d, 0xc4, 0xd9, 0xa9, 0x1d, 0x67, 0x9d, + 0x2b, 0x18, 0x56, 0x86, 0x2a, 0x3, 0x19, 0xe9, 0x6, 0xeb, 0x4a, 0x6f, 0x2a, 0x40, 0x28, 0xbb, + 0x3e, 0x87, 0xc1, 0xce, 0x39, 0x6e, 0x3b, 0x1f, 0xb0, 0x9, 0x33, 0x67, 0x19, 0x0e, 0x1a, 0xb2, + 0xb3, 0x7d, 0xd3, 0xe6, 0x33, 0xf4, 0x7c, 0x82, 0x73, 0x7b, 0xb6, 0x16, 0x55, 0xff, 0x76, 0xaf, + 0x7f, 0xc2, 0x42, 0x51, 0xa9, 0xad, 0x1e, 0x72, 0xc9, 0x63, 0xab, 0x41, 0x5a, 0x26, 0x32, 0x39, + 0x5d, 0xa6, 0x7, 0x56, 0x93, 0x89, 0xe5, 0x0f, 0x2a, 0xb5, 0x67, 0x3a, 0xcf, 0xc3, 0x82, 0x83, + 0xf6, 0x88, 0x52, 0x0b, 0xfc, 0x6a, 0x5b, 0x1a, 0x57, 0x87, 0x86, 0xef, 0xda, 0x47, 0xdb, 0x4d, + 0xba, 0xe7, 0x3, 0x5b, 0xe4, 0x70, 0x8b, 0xe0, 0xe1, 0x92, 0x13, 0x86, 0x74, 0x4, 0xdc, 0x6a, + 0x0a, 0x2a, 0x20, 0xec, 0x6d, 0xbf, 0xf0, 0x46, 0xf7, 0x9, 0x2, 0xdb, 0x2f, 0x70, 0x11, 0xdd, + 0xb0, 0x13, 0xa2, 0xc1, 0x58, 0x74, 0x29, 0x19, 0x8d, 0x4a, 0x94, 0x80, 0x0b, 0xd7, 0x25, 0x85, + 0x10, 0x35, 0x97, 0x48, 0x6e, 0x70, 0x28, 0xae, 0x58, 0x97, 0x7d, 0xf2, 0x19, 0x27, 0x13, 0xab, + 0x47, 0x9b, 0x54, 0xdf, 0xc3, 0x5b, 0x5f, 0x5e, 0xb4, 0x64, 0x47, 0xce, 0x40, 0x3b, 0x0c, 0x4a, + 0x62, 0x52, 0xba, 0xc7, 0xf0, 0x36, 0x87, 0x9c, 0x79, 0x9a, 0x83, 0x11, 0x61, 0x0c, 0x1b, 0x6b +}; + +static char dh_except_b_pubkey_2048[] = { + 0x44, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x9, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x4, 0xe8, 0x9a, 0xd2, 0x0, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x0, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x5, + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x7, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x3, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x1, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7 +}; + +static char dh_share_key_2048[] = { + 0xaf, 0xd4, 0xf6, 0x45, 0x63, 0x21, 0x8d, 0x98, 0xc4, 0xab, 0x18, 0xd7, 0x2b, 0x3c, 0x1d, 0xde, + 0xe7, 0x1f, 0xe1, 0xc5, 0x79, 0x57, 0x60, 0x20, 0xfa, 0x99, 0xbd, 0x7b, 0xa2, 0x94, 0x0b, 0xa3, + 0xb4, 0xb3, 0x33, 0x4a, 0x2f, 0xd0, 0x17, 0x7, 0x2e, 0x70, 0x19, 0x84, 0x1f, 0x8e, 0xe9, 0x61, + 0xe5, 0x52, 0x3, 0x96, 0xea, 0xd8, 0xb6, 0x3, 0x9f, 0xc4, 0x3e, 0x23, 0x77, 0x17, 0x54, 0xfb, + 0x13, 0xf0, 0x3e, 0x9a, 0x27, 0x5d, 0x12, 0x99, 0x58, 0x8d, 0x41, 0x46, 0xd9, 0xc9, 0x29, 0xbd, + 0x40, 0xd1, 0x4f, 0xef, 0x63, 0x7b, 0x54, 0xe6, 0x59, 0x6d, 0xe2, 0x30, 0xe8, 0x2c, 0x2f, 0xf9, + 0x66, 0xa2, 0x12, 0xf5, 0x58, 0x61, 0xac, 0x43, 0xec, 0x7e, 0xf9, 0x2e, 0x27, 0x70, 0x35, 0x75, + 0xb4, 0x10, 0x29, 0xac, 0x0a, 0xab, 0x59, 0xb6, 0x68, 0x4c, 0x16, 0xaf, 0xf0, 0x4f, 0x21, 0xcd, + 0xcc, 0x48, 0x97, 0xe4, 0x21, 0x65, 0xa6, 0x55, 0xb8, 0xf3, 0xb2, 0x7b, 0x91, 0xd7, 0xca, 0xb9, + 0x17, 0x58, 0x31, 0x71, 0xc0, 0xc9, 0x69, 0x1e, 0xf0, 0x9e, 0x3f, 0xe2, 0x37, 0x4, 0x2d, 0xa8, + 0x55, 0x9, 0x6b, 0x9c, 0xc6, 0x37, 0xa9, 0x9b, 0xdf, 0x67, 0x73, 0x7b, 0x46, 0xf9, 0x63, 0x47, + 0xcb, 0xa0, 0x57, 0x2a, 0xed, 0x97, 0x2f, 0xfe, 0x92, 0xf2, 0x20, 0x2c, 0x7e, 0xee, 0x7d, 0x11, + 0x78, 0xe6, 0xb9, 0x9, 0xd1, 0x94, 0xce, 0xd1, 0x5b, 0xf4, 0x44, 0xa9, 0xcb, 0x26, 0x2, 0x36, + 0x57, 0x2c, 0xa2, 0xbe, 0x37, 0xde, 0x86, 0x46, 0x20, 0x27, 0x9d, 0xa0, 0x2f, 0x4, 0xc1, 0xcd, + 0xff, 0x81, 0xe5, 0xe6, 0x2c, 0x9e, 0x39, 0x82, 0x31, 0x54, 0x33, 0xf8, 0xe7, 0xa0, 0xe5, 0x96, + 0xa4, 0x40, 0xc4, 0x44, 0xfe, 0x93, 0x66, 0xe2, 0xda, 0xaa, 0xb8, 0xfb, 0x2f, 0x3b, 0x8c, 0xce, +}; + +static char dh_p_3072[] = { + 0xce, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x09, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x04, 0xe8, 0x9a, 0xd2, 0x00, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x00, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x05, + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x07, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x03, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x01, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7, + 0xce, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x09, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x04, 0xe8, 0x9a, 0xd2, 0x00, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x00, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x05, +}; + +static char dh_xa_3072[] = { + 0x6b, 0x1f, 0xc4, 0x85, 0x98, 0xc3, 0x01, 0xda, 0x39, 0xf0, 0x1b, 0x76, 0x5d, 0x81, 0x1d, 0x1f, + 0xc9, 0x93, 0x95, 0xc1, 0xf8, 0xd1, 0x67, 0x2c, 0xd4, 0x0a, 0x67, 0xf0, 0x40, 0x86, 0x82, 0x7f, + 0x8f, 0x9d, 0x79, 0x04, 0xee, 0x4a, 0x54, 0xc9, 0x9c, 0x7f, 0xda, 0x15, 0x13, 0xc6, 0x95, 0xfb, + 0xfc, 0x7b, 0xe7, 0xd8, 0xde, 0x2a, 0xd8, 0xfd, 0xff, 0xdb, 0xa4, 0x7f, 0x4b, 0x37, 0x5d, 0x42, + 0xb6, 0x46, 0x4c, 0xbc, 0x34, 0x23, 0x99, 0x74, 0xf8, 0x80, 0x1b, 0xc1, 0x97, 0x34, 0xdf, 0x23, + 0x15, 0xa2, 0x8b, 0xec, 0xf3, 0x3e, 0x20, 0x93, 0x63, 0x88, 0x17, 0x70, 0x75, 0xbb, 0x9d, 0xb8, + 0x32, 0xb0, 0xae, 0xb5, 0x24, 0x6a, 0x86, 0xf6, 0xc1, 0x60, 0x41, 0xc4, 0xf4, 0x95, 0x6e, 0x10, + 0x2f, 0xd8, 0x58, 0x56, 0x42, 0x82, 0x71, 0x85, 0x19, 0xde, 0x91, 0xf0, 0x2f, 0x30, 0x0c, 0x63, + 0x0f, 0x2a, 0x77, 0x25, 0x4b, 0xb3, 0xd3, 0x2d, 0xfd, 0x94, 0x8b, 0x53, 0x02, 0x21, 0x40, 0xd7, + 0x36, 0x76, 0xf3, 0xc8, 0xc0, 0x36, 0x3d, 0x23, 0xc9, 0xbd, 0x92, 0x51, 0xf2, 0x4b, 0x83, 0x15, + 0xe0, 0x80, 0x86, 0x24, 0xe2, 0x20, 0x35, 0x97, 0xda, 0x0e, 0x68, 0x39, 0x01, 0xdd, 0x01, 0x87, + 0xa2, 0x47, 0xd2, 0x0d, 0xee, 0xfe, 0xdc, 0x5a, 0x37, 0x23, 0xeb, 0x3d, 0xe8, 0x1e, 0x39, 0x2d, + 0xbf, 0xa6, 0xe9, 0x17, 0x48, 0xe2, 0xea, 0xef, 0x1d, 0x2f, 0xe2, 0xaf, 0x3c, 0xbc, 0xae, 0xa7, + 0x42, 0x9b, 0xa5, 0x7d, 0x47, 0x8a, 0x20, 0xc5, 0xae, 0xa1, 0xe4, 0xe8, 0x1c, 0x05, 0xc0, 0x0a, + 0x05, 0xdc, 0x01, 0x74, 0xde, 0xad, 0xad, 0x07, 0xec, 0x6e, 0x6a, 0xc7, 0xee, 0x0f, 0xb8, 0xbe, + 0xaa, 0x46, 0x61, 0x8c, 0x12, 0x5a, 0xaf, 0x05, 0xff, 0x1b, 0x35, 0x6b, 0xe2, 0x3d, 0x48, 0x4f, + 0x6b, 0x1f, 0xc4, 0x85, 0x98, 0xc3, 0x01, 0xda, 0x39, 0xf0, 0x1b, 0x76, 0x5d, 0x81, 0x1d, 0x1f, + 0xc9, 0x93, 0x95, 0xc1, 0xf8, 0xd1, 0x67, 0x2c, 0xd4, 0x0a, 0x67, 0xf0, 0x40, 0x86, 0x82, 0x7f, + 0x8f, 0x9d, 0x79, 0x04, 0xee, 0x4a, 0x54, 0xc9, 0x9c, 0x7f, 0xda, 0x15, 0x13, 0xc6, 0x95, 0xfb, + 0xfc, 0x7b, 0xe7, 0xd8, 0xde, 0x2a, 0xd8, 0xfd, 0xff, 0xdb, 0xa4, 0x7f, 0x4b, 0x37, 0x5d, 0x42, + 0xb6, 0x46, 0x4c, 0xbc, 0x34, 0x23, 0x99, 0x74, 0xf8, 0x80, 0x1b, 0xc1, 0x97, 0x34, 0xdf, 0x23, + 0x15, 0xa2, 0x8b, 0xec, 0xf3, 0x3e, 0x20, 0x93, 0x63, 0x88, 0x17, 0x70, 0x75, 0xbb, 0x9d, 0xb8, + 0x32, 0xb0, 0xae, 0xb5, 0x24, 0x6a, 0x86, 0xf6, 0xc1, 0x60, 0x41, 0xc4, 0xf4, 0x95, 0x6e, 0x10, + 0x2f, 0xd8, 0x58, 0x56, 0x42, 0x82, 0x71, 0x85, 0x19, 0xde, 0x91, 0xf0, 0x2f, 0x30, 0x0c, 0x63, +}; + +#if 0 +static char dh_xb_3072[] = { + 0x5c, 0xdf, 0x3, 0x2f, 0x18, 0xac, 0xbc, 0xeb, 0x95, 0xa2, 0x33, 0x70, 0x39, 0x13, 0x92, 0x7e, + 0x91, 0x19, 0x89, 0xd4, 0x0, 0xd1, 0xc5, 0x7e, 0x32, 0xb7, 0x4a, 0xd2, 0xff, 0x11, 0x7a, 0x9b, + 0x2, 0x84, 0xd0, 0x8e, 0x19, 0x91, 0x34, 0xc2, 0x5, 0xff, 0xe4, 0xf4, 0xd8, 0xcf, 0xc8, 0xa0, + 0xeb, 0x19, 0xb9, 0x69, 0x60, 0xcd, 0xa8, 0xda, 0x33, 0xbc, 0xa7, 0x80, 0x0, 0x92, 0x27, 0xe0, + 0xe7, 0x34, 0x77, 0x1f, 0xfd, 0x56, 0x0, 0x0c, 0x57, 0x0, 0x6d, 0x47, 0xe4, 0x32, 0xd7, 0x22, + 0x64, 0xa5, 0x33, 0x65, 0x33, 0x3e, 0x7c, 0x4e, 0x9d, 0xa6, 0xb7, 0x8b, 0xd7, 0xaa, 0x72, 0xe5, + 0x9d, 0xd5, 0xb4, 0x25, 0xcb, 0x30, 0x2, 0xfc, 0xb5, 0xae, 0xb3, 0x88, 0x67, 0x55, 0x0a, 0x7e, + 0x9d, 0xe8, 0x32, 0xfb, 0x50, 0x79, 0x4e, 0x9b, 0x21, 0x92, 0x25, 0x3, 0xa0, 0x15, 0x52, 0x3d, + 0x5e, 0x21, 0x0a, 0x9e, 0x3, 0xdd, 0x3f, 0xcc, 0x38, 0xf6, 0xa9, 0xa6, 0xf8, 0xfd, 0x15, 0x7d, + 0x67, 0x4e, 0x14, 0xae, 0x4d, 0xe2, 0x1f, 0x78, 0x77, 0xfb, 0x83, 0x5f, 0x48, 0xa8, 0xc8, 0x21, + 0x8b, 0xd9, 0xf8, 0x14, 0xe6, 0x42, 0x95, 0xbd, 0x9a, 0x96, 0xbe, 0xf4, 0x7d, 0x26, 0x5d, 0xa1, + 0x81, 0x9b, 0x1c, 0xec, 0xfe, 0xce, 0x9, 0x1d, 0xb7, 0x7a, 0xba, 0xca, 0x7f, 0x54, 0xee, 0x36, + 0x54, 0x65, 0x4a, 0xd0, 0x5c, 0x84, 0x8c, 0x3e, 0x1b, 0xfe, 0x91, 0x6f, 0x95, 0xb5, 0x76, 0xbf, + 0x61, 0x2a, 0x7, 0x23, 0x86, 0xb9, 0xe0, 0x19, 0x29, 0xcf, 0xea, 0x3a, 0x1, 0xbf, 0xee, 0x1b, + 0x5e, 0x3c, 0x4, 0xff, 0x1d, 0xcf, 0xa6, 0x56, 0xb3, 0x22, 0xbb, 0x45, 0x4b, 0x7f, 0x83, 0x87, + 0xef, 0x21, 0x5, 0xf7, 0x38, 0x1f, 0x6, 0x4d, 0x71, 0x0b, 0xe3, 0xe1, 0xb7, 0x7e, 0xae, 0x18, + 0x5c, 0xdf, 0x3, 0x2f, 0x18, 0xac, 0xbc, 0xeb, 0x95, 0xa2, 0x33, 0x70, 0x39, 0x13, 0x92, 0x7e, + 0x91, 0x19, 0x89, 0xd4, 0x0, 0xd1, 0xc5, 0x7e, 0x32, 0xb7, 0x4a, 0xd2, 0xff, 0x11, 0x7a, 0x9b, + 0x2, 0x84, 0xd0, 0x8e, 0x19, 0x91, 0x34, 0xc2, 0x5, 0xff, 0xe4, 0xf4, 0xd8, 0xcf, 0xc8, 0xa0, + 0xeb, 0x19, 0xb9, 0x69, 0x60, 0xcd, 0xa8, 0xda, 0x33, 0xbc, 0xa7, 0x80, 0x0, 0x92, 0x27, 0xe0, + 0xe7, 0x34, 0x77, 0x1f, 0xfd, 0x56, 0x0, 0x0c, 0x57, 0x0, 0x6d, 0x47, 0xe4, 0x32, 0xd7, 0x22, + 0x64, 0xa5, 0x33, 0x65, 0x33, 0x3e, 0x7c, 0x4e, 0x9d, 0xa6, 0xb7, 0x8b, 0xd7, 0xaa, 0x72, 0xe5, + 0x9d, 0xd5, 0xb4, 0x25, 0xcb, 0x30, 0x2, 0xfc, 0xb5, 0xae, 0xb3, 0x88, 0x67, 0x55, 0x0a, 0x7e, + 0x9d, 0xe8, 0x32, 0xfb, 0x50, 0x79, 0x4e, 0x9b, 0x21, 0x92, 0x25, 0x3, 0xa0, 0x15, 0x52, 0x3d, +}; +#endif + +static char dh_except_a_pubkey_3072[] = { + 0xa5, 0x24, 0x63, 0x20, 0xb2, 0x56, 0x9a, 0x94, 0x97, 0xf7, 0x88, 0x41, 0x35, 0xeb, 0x52, 0x37, + 0xa4, 0xf2, 0x74, 0x1b, 0x38, 0xe4, 0x4c, 0x8b, 0x4b, 0xd2, 0xa5, 0xad, 0xb8, 0x2f, 0x7b, 0x5a, + 0xfd, 0xbc, 0x9c, 0xe0, 0xea, 0x9e, 0x82, 0x3, 0x62, 0xe2, 0xdc, 0x6c, 0x56, 0x9, 0x2, 0x28, + 0xb8, 0x2d, 0xb8, 0x46, 0xaf, 0x3a, 0xf4, 0x51, 0xf7, 0x4d, 0xc4, 0xd9, 0xa9, 0x1d, 0x67, 0x9d, + 0x2b, 0x18, 0x56, 0x86, 0x2a, 0x3, 0x19, 0xe9, 0x6, 0xeb, 0x4a, 0x6f, 0x2a, 0x40, 0x28, 0xbb, + 0x3e, 0x87, 0xc1, 0xce, 0x39, 0x6e, 0x3b, 0x1f, 0xb0, 0x9, 0x33, 0x67, 0x19, 0x0e, 0x1a, 0xb2, + 0xb3, 0x7d, 0xd3, 0xe6, 0x33, 0xf4, 0x7c, 0x82, 0x73, 0x7b, 0xb6, 0x16, 0x55, 0xff, 0x76, 0xaf, + 0x7f, 0xc2, 0x42, 0x51, 0xa9, 0xad, 0x1e, 0x72, 0xc9, 0x63, 0xab, 0x41, 0x5a, 0x26, 0x32, 0x39, + 0x5d, 0xa6, 0x7, 0x56, 0x93, 0x89, 0xe5, 0x0f, 0x2a, 0xb5, 0x67, 0x3a, 0xcf, 0xc3, 0x82, 0x83, + 0xf6, 0x88, 0x52, 0x0b, 0xfc, 0x6a, 0x5b, 0x1a, 0x57, 0x87, 0x86, 0xef, 0xda, 0x47, 0xdb, 0x4d, + 0xba, 0xe7, 0x3, 0x5b, 0xe4, 0x70, 0x8b, 0xe0, 0xe1, 0x92, 0x13, 0x86, 0x74, 0x4, 0xdc, 0x6a, + 0x0a, 0x2a, 0x20, 0xec, 0x6d, 0xbf, 0xf0, 0x46, 0xf7, 0x9, 0x2, 0xdb, 0x2f, 0x70, 0x11, 0xdd, + 0xb0, 0x13, 0xa2, 0xc1, 0x58, 0x74, 0x29, 0x19, 0x8d, 0x4a, 0x94, 0x80, 0x0b, 0xd7, 0x25, 0x85, + 0x10, 0x35, 0x97, 0x48, 0x6e, 0x70, 0x28, 0xae, 0x58, 0x97, 0x7d, 0xf2, 0x19, 0x27, 0x13, 0xab, + 0x47, 0x9b, 0x54, 0xdf, 0xc3, 0x5b, 0x5f, 0x5e, 0xb4, 0x64, 0x47, 0xce, 0x40, 0x3b, 0x0c, 0x4a, + 0x62, 0x52, 0xba, 0xc7, 0xf0, 0x36, 0x87, 0x9c, 0x79, 0x9a, 0x83, 0x11, 0x61, 0x0c, 0x1b, 0x6b, + 0xa5, 0x24, 0x63, 0x20, 0xb2, 0x56, 0x9a, 0x94, 0x97, 0xf7, 0x88, 0x41, 0x35, 0xeb, 0x52, 0x37, + 0xa4, 0xf2, 0x74, 0x1b, 0x38, 0xe4, 0x4c, 0x8b, 0x4b, 0xd2, 0xa5, 0xad, 0xb8, 0x2f, 0x7b, 0x5a, + 0xfd, 0xbc, 0x9c, 0xe0, 0xea, 0x9e, 0x82, 0x3, 0x62, 0xe2, 0xdc, 0x6c, 0x56, 0x9, 0x2, 0x28, + 0xb8, 0x2d, 0xb8, 0x46, 0xaf, 0x3a, 0xf4, 0x51, 0xf7, 0x4d, 0xc4, 0xd9, 0xa9, 0x1d, 0x67, 0x9d, + 0x2b, 0x18, 0x56, 0x86, 0x2a, 0x3, 0x19, 0xe9, 0x6, 0xeb, 0x4a, 0x6f, 0x2a, 0x40, 0x28, 0xbb, + 0x3e, 0x87, 0xc1, 0xce, 0x39, 0x6e, 0x3b, 0x1f, 0xb0, 0x9, 0x33, 0x67, 0x19, 0x0e, 0x1a, 0xb2, + 0xb3, 0x7d, 0xd3, 0xe6, 0x33, 0xf4, 0x7c, 0x82, 0x73, 0x7b, 0xb6, 0x16, 0x55, 0xff, 0x76, 0xaf, + 0x7f, 0xc2, 0x42, 0x51, 0xa9, 0xad, 0x1e, 0x72, 0xc9, 0x63, 0xab, 0x41, 0x5a, 0x26, 0x32, 0x39, +}; + +static char dh_except_b_pubkey_3072[] = { + 0x44, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x9, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x4, 0xe8, 0x9a, 0xd2, 0x0, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x0, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x5, + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x7, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x3, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x1, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7, + 0x44, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x9, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x4, 0xe8, 0x9a, 0xd2, 0x0, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x0, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x5, +}; + +static char dh_share_key_3072[] = { + 0xaf, 0xd4, 0xf6, 0x45, 0x63, 0x21, 0x8d, 0x98, 0xc4, 0xab, 0x18, 0xd7, 0x2b, 0x3c, 0x1d, 0xde, + 0xe7, 0x1f, 0xe1, 0xc5, 0x79, 0x57, 0x60, 0x20, 0xfa, 0x99, 0xbd, 0x7b, 0xa2, 0x94, 0x0b, 0xa3, + 0xb4, 0xb3, 0x33, 0x4a, 0x2f, 0xd0, 0x17, 0x7, 0x2e, 0x70, 0x19, 0x84, 0x1f, 0x8e, 0xe9, 0x61, + 0xe5, 0x52, 0x3, 0x96, 0xea, 0xd8, 0xb6, 0x3, 0x9f, 0xc4, 0x3e, 0x23, 0x77, 0x17, 0x54, 0xfb, + 0x13, 0xf0, 0x3e, 0x9a, 0x27, 0x5d, 0x12, 0x99, 0x58, 0x8d, 0x41, 0x46, 0xd9, 0xc9, 0x29, 0xbd, + 0x40, 0xd1, 0x4f, 0xef, 0x63, 0x7b, 0x54, 0xe6, 0x59, 0x6d, 0xe2, 0x30, 0xe8, 0x2c, 0x2f, 0xf9, + 0x66, 0xa2, 0x12, 0xf5, 0x58, 0x61, 0xac, 0x43, 0xec, 0x7e, 0xf9, 0x2e, 0x27, 0x70, 0x35, 0x75, + 0xb4, 0x10, 0x29, 0xac, 0x0a, 0xab, 0x59, 0xb6, 0x68, 0x4c, 0x16, 0xaf, 0xf0, 0x4f, 0x21, 0xcd, + 0xcc, 0x48, 0x97, 0xe4, 0x21, 0x65, 0xa6, 0x55, 0xb8, 0xf3, 0xb2, 0x7b, 0x91, 0xd7, 0xca, 0xb9, + 0x17, 0x58, 0x31, 0x71, 0xc0, 0xc9, 0x69, 0x1e, 0xf0, 0x9e, 0x3f, 0xe2, 0x37, 0x4, 0x2d, 0xa8, + 0x55, 0x9, 0x6b, 0x9c, 0xc6, 0x37, 0xa9, 0x9b, 0xdf, 0x67, 0x73, 0x7b, 0x46, 0xf9, 0x63, 0x47, + 0xcb, 0xa0, 0x57, 0x2a, 0xed, 0x97, 0x2f, 0xfe, 0x92, 0xf2, 0x20, 0x2c, 0x7e, 0xee, 0x7d, 0x11, + 0x78, 0xe6, 0xb9, 0x9, 0xd1, 0x94, 0xce, 0xd1, 0x5b, 0xf4, 0x44, 0xa9, 0xcb, 0x26, 0x2, 0x36, + 0x57, 0x2c, 0xa2, 0xbe, 0x37, 0xde, 0x86, 0x46, 0x20, 0x27, 0x9d, 0xa0, 0x2f, 0x4, 0xc1, 0xcd, + 0xff, 0x81, 0xe5, 0xe6, 0x2c, 0x9e, 0x39, 0x82, 0x31, 0x54, 0x33, 0xf8, 0xe7, 0xa0, 0xe5, 0x96, + 0xa4, 0x40, 0xc4, 0x44, 0xfe, 0x93, 0x66, 0xe2, 0xda, 0xaa, 0xb8, 0xfb, 0x2f, 0x3b, 0x8c, 0xce, + 0xaf, 0xd4, 0xf6, 0x45, 0x63, 0x21, 0x8d, 0x98, 0xc4, 0xab, 0x18, 0xd7, 0x2b, 0x3c, 0x1d, 0xde, + 0xe7, 0x1f, 0xe1, 0xc5, 0x79, 0x57, 0x60, 0x20, 0xfa, 0x99, 0xbd, 0x7b, 0xa2, 0x94, 0x0b, 0xa3, + 0xb4, 0xb3, 0x33, 0x4a, 0x2f, 0xd0, 0x17, 0x7, 0x2e, 0x70, 0x19, 0x84, 0x1f, 0x8e, 0xe9, 0x61, + 0xe5, 0x52, 0x3, 0x96, 0xea, 0xd8, 0xb6, 0x3, 0x9f, 0xc4, 0x3e, 0x23, 0x77, 0x17, 0x54, 0xfb, + 0x13, 0xf0, 0x3e, 0x9a, 0x27, 0x5d, 0x12, 0x99, 0x58, 0x8d, 0x41, 0x46, 0xd9, 0xc9, 0x29, 0xbd, + 0x40, 0xd1, 0x4f, 0xef, 0x63, 0x7b, 0x54, 0xe6, 0x59, 0x6d, 0xe2, 0x30, 0xe8, 0x2c, 0x2f, 0xf9, + 0x66, 0xa2, 0x12, 0xf5, 0x58, 0x61, 0xac, 0x43, 0xec, 0x7e, 0xf9, 0x2e, 0x27, 0x70, 0x35, 0x75, + 0xb4, 0x10, 0x29, 0xac, 0x0a, 0xab, 0x59, 0xb6, 0x68, 0x4c, 0x16, 0xaf, 0xf0, 0x4f, 0x21, 0xcd, +}; + +static char dh_p_4096[] = { + 0xce, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x09, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x04, 0xe8, 0x9a, 0xd2, 0x00, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x00, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x05, + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x07, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x03, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x01, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7, + 0xce, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x09, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x04, 0xe8, 0x9a, 0xd2, 0x00, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x00, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x05, + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x07, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x03, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x01, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7 +}; + +static char dh_xa_4096[] = { + 0x6b, 0x1f, 0xc4, 0x85, 0x98, 0xc3, 0x01, 0xda, 0x39, 0xf0, 0x1b, 0x76, 0x5d, 0x81, 0x1d, 0x1f, + 0xc9, 0x93, 0x95, 0xc1, 0xf8, 0xd1, 0x67, 0x2c, 0xd4, 0x0a, 0x67, 0xf0, 0x40, 0x86, 0x82, 0x7f, + 0x8f, 0x9d, 0x79, 0x04, 0xee, 0x4a, 0x54, 0xc9, 0x9c, 0x7f, 0xda, 0x15, 0x13, 0xc6, 0x95, 0xfb, + 0xfc, 0x7b, 0xe7, 0xd8, 0xde, 0x2a, 0xd8, 0xfd, 0xff, 0xdb, 0xa4, 0x7f, 0x4b, 0x37, 0x5d, 0x42, + 0xb6, 0x46, 0x4c, 0xbc, 0x34, 0x23, 0x99, 0x74, 0xf8, 0x80, 0x1b, 0xc1, 0x97, 0x34, 0xdf, 0x23, + 0x15, 0xa2, 0x8b, 0xec, 0xf3, 0x3e, 0x20, 0x93, 0x63, 0x88, 0x17, 0x70, 0x75, 0xbb, 0x9d, 0xb8, + 0x32, 0xb0, 0xae, 0xb5, 0x24, 0x6a, 0x86, 0xf6, 0xc1, 0x60, 0x41, 0xc4, 0xf4, 0x95, 0x6e, 0x10, + 0x2f, 0xd8, 0x58, 0x56, 0x42, 0x82, 0x71, 0x85, 0x19, 0xde, 0x91, 0xf0, 0x2f, 0x30, 0x0c, 0x63, + 0x0f, 0x2a, 0x77, 0x25, 0x4b, 0xb3, 0xd3, 0x2d, 0xfd, 0x94, 0x8b, 0x53, 0x02, 0x21, 0x40, 0xd7, + 0x36, 0x76, 0xf3, 0xc8, 0xc0, 0x36, 0x3d, 0x23, 0xc9, 0xbd, 0x92, 0x51, 0xf2, 0x4b, 0x83, 0x15, + 0xe0, 0x80, 0x86, 0x24, 0xe2, 0x20, 0x35, 0x97, 0xda, 0x0e, 0x68, 0x39, 0x01, 0xdd, 0x01, 0x87, + 0xa2, 0x47, 0xd2, 0x0d, 0xee, 0xfe, 0xdc, 0x5a, 0x37, 0x23, 0xeb, 0x3d, 0xe8, 0x1e, 0x39, 0x2d, + 0xbf, 0xa6, 0xe9, 0x17, 0x48, 0xe2, 0xea, 0xef, 0x1d, 0x2f, 0xe2, 0xaf, 0x3c, 0xbc, 0xae, 0xa7, + 0x42, 0x9b, 0xa5, 0x7d, 0x47, 0x8a, 0x20, 0xc5, 0xae, 0xa1, 0xe4, 0xe8, 0x1c, 0x05, 0xc0, 0x0a, + 0x05, 0xdc, 0x01, 0x74, 0xde, 0xad, 0xad, 0x07, 0xec, 0x6e, 0x6a, 0xc7, 0xee, 0x0f, 0xb8, 0xbe, + 0xaa, 0x46, 0x61, 0x8c, 0x12, 0x5a, 0xaf, 0x05, 0xff, 0x1b, 0x35, 0x6b, 0xe2, 0x3d, 0x48, 0x4f, + 0x6b, 0x1f, 0xc4, 0x85, 0x98, 0xc3, 0x01, 0xda, 0x39, 0xf0, 0x1b, 0x76, 0x5d, 0x81, 0x1d, 0x1f, + 0xc9, 0x93, 0x95, 0xc1, 0xf8, 0xd1, 0x67, 0x2c, 0xd4, 0x0a, 0x67, 0xf0, 0x40, 0x86, 0x82, 0x7f, + 0x8f, 0x9d, 0x79, 0x04, 0xee, 0x4a, 0x54, 0xc9, 0x9c, 0x7f, 0xda, 0x15, 0x13, 0xc6, 0x95, 0xfb, + 0xfc, 0x7b, 0xe7, 0xd8, 0xde, 0x2a, 0xd8, 0xfd, 0xff, 0xdb, 0xa4, 0x7f, 0x4b, 0x37, 0x5d, 0x42, + 0xb6, 0x46, 0x4c, 0xbc, 0x34, 0x23, 0x99, 0x74, 0xf8, 0x80, 0x1b, 0xc1, 0x97, 0x34, 0xdf, 0x23, + 0x15, 0xa2, 0x8b, 0xec, 0xf3, 0x3e, 0x20, 0x93, 0x63, 0x88, 0x17, 0x70, 0x75, 0xbb, 0x9d, 0xb8, + 0x32, 0xb0, 0xae, 0xb5, 0x24, 0x6a, 0x86, 0xf6, 0xc1, 0x60, 0x41, 0xc4, 0xf4, 0x95, 0x6e, 0x10, + 0x2f, 0xd8, 0x58, 0x56, 0x42, 0x82, 0x71, 0x85, 0x19, 0xde, 0x91, 0xf0, 0x2f, 0x30, 0x0c, 0x63, + 0x0f, 0x2a, 0x77, 0x25, 0x4b, 0xb3, 0xd3, 0x2d, 0xfd, 0x94, 0x8b, 0x53, 0x02, 0x21, 0x40, 0xd7, + 0x36, 0x76, 0xf3, 0xc8, 0xc0, 0x36, 0x3d, 0x23, 0xc9, 0xbd, 0x92, 0x51, 0xf2, 0x4b, 0x83, 0x15, + 0xe0, 0x80, 0x86, 0x24, 0xe2, 0x20, 0x35, 0x97, 0xda, 0x0e, 0x68, 0x39, 0x01, 0xdd, 0x01, 0x87, + 0xa2, 0x47, 0xd2, 0x0d, 0xee, 0xfe, 0xdc, 0x5a, 0x37, 0x23, 0xeb, 0x3d, 0xe8, 0x1e, 0x39, 0x2d, + 0xbf, 0xa6, 0xe9, 0x17, 0x48, 0xe2, 0xea, 0xef, 0x1d, 0x2f, 0xe2, 0xaf, 0x3c, 0xbc, 0xae, 0xa7, + 0x42, 0x9b, 0xa5, 0x7d, 0x47, 0x8a, 0x20, 0xc5, 0xae, 0xa1, 0xe4, 0xe8, 0x1c, 0x05, 0xc0, 0x0a, + 0x05, 0xdc, 0x01, 0x74, 0xde, 0xad, 0xad, 0x07, 0xec, 0x6e, 0x6a, 0xc7, 0xee, 0x0f, 0xb8, 0xbe, + 0xaa, 0x46, 0x61, 0x8c, 0x12, 0x5a, 0xaf, 0x05, 0xff, 0x1b, 0x35, 0x6b, 0xe2, 0x3d, 0x48, 0x4f +}; + +#if 0 +static char dh_xb_4096[] = { + 0x5c, 0xdf, 0x3, 0x2f, 0x18, 0xac, 0xbc, 0xeb, 0x95, 0xa2, 0x33, 0x70, 0x39, 0x13, 0x92, 0x7e, + 0x91, 0x19, 0x89, 0xd4, 0x0, 0xd1, 0xc5, 0x7e, 0x32, 0xb7, 0x4a, 0xd2, 0xff, 0x11, 0x7a, 0x9b, + 0x2, 0x84, 0xd0, 0x8e, 0x19, 0x91, 0x34, 0xc2, 0x5, 0xff, 0xe4, 0xf4, 0xd8, 0xcf, 0xc8, 0xa0, + 0xeb, 0x19, 0xb9, 0x69, 0x60, 0xcd, 0xa8, 0xda, 0x33, 0xbc, 0xa7, 0x80, 0x0, 0x92, 0x27, 0xe0, + 0xe7, 0x34, 0x77, 0x1f, 0xfd, 0x56, 0x0, 0x0c, 0x57, 0x0, 0x6d, 0x47, 0xe4, 0x32, 0xd7, 0x22, + 0x64, 0xa5, 0x33, 0x65, 0x33, 0x3e, 0x7c, 0x4e, 0x9d, 0xa6, 0xb7, 0x8b, 0xd7, 0xaa, 0x72, 0xe5, + 0x9d, 0xd5, 0xb4, 0x25, 0xcb, 0x30, 0x2, 0xfc, 0xb5, 0xae, 0xb3, 0x88, 0x67, 0x55, 0x0a, 0x7e, + 0x9d, 0xe8, 0x32, 0xfb, 0x50, 0x79, 0x4e, 0x9b, 0x21, 0x92, 0x25, 0x3, 0xa0, 0x15, 0x52, 0x3d, + 0x5e, 0x21, 0x0a, 0x9e, 0x3, 0xdd, 0x3f, 0xcc, 0x38, 0xf6, 0xa9, 0xa6, 0xf8, 0xfd, 0x15, 0x7d, + 0x67, 0x4e, 0x14, 0xae, 0x4d, 0xe2, 0x1f, 0x78, 0x77, 0xfb, 0x83, 0x5f, 0x48, 0xa8, 0xc8, 0x21, + 0x8b, 0xd9, 0xf8, 0x14, 0xe6, 0x42, 0x95, 0xbd, 0x9a, 0x96, 0xbe, 0xf4, 0x7d, 0x26, 0x5d, 0xa1, + 0x81, 0x9b, 0x1c, 0xec, 0xfe, 0xce, 0x9, 0x1d, 0xb7, 0x7a, 0xba, 0xca, 0x7f, 0x54, 0xee, 0x36, + 0x54, 0x65, 0x4a, 0xd0, 0x5c, 0x84, 0x8c, 0x3e, 0x1b, 0xfe, 0x91, 0x6f, 0x95, 0xb5, 0x76, 0xbf, + 0x61, 0x2a, 0x7, 0x23, 0x86, 0xb9, 0xe0, 0x19, 0x29, 0xcf, 0xea, 0x3a, 0x1, 0xbf, 0xee, 0x1b, + 0x5e, 0x3c, 0x4, 0xff, 0x1d, 0xcf, 0xa6, 0x56, 0xb3, 0x22, 0xbb, 0x45, 0x4b, 0x7f, 0x83, 0x87, + 0xef, 0x21, 0x5, 0xf7, 0x38, 0x1f, 0x6, 0x4d, 0x71, 0x0b, 0xe3, 0xe1, 0xb7, 0x7e, 0xae, 0x18, + 0x5c, 0xdf, 0x3, 0x2f, 0x18, 0xac, 0xbc, 0xeb, 0x95, 0xa2, 0x33, 0x70, 0x39, 0x13, 0x92, 0x7e, + 0x91, 0x19, 0x89, 0xd4, 0x0, 0xd1, 0xc5, 0x7e, 0x32, 0xb7, 0x4a, 0xd2, 0xff, 0x11, 0x7a, 0x9b, + 0x2, 0x84, 0xd0, 0x8e, 0x19, 0x91, 0x34, 0xc2, 0x5, 0xff, 0xe4, 0xf4, 0xd8, 0xcf, 0xc8, 0xa0, + 0xeb, 0x19, 0xb9, 0x69, 0x60, 0xcd, 0xa8, 0xda, 0x33, 0xbc, 0xa7, 0x80, 0x0, 0x92, 0x27, 0xe0, + 0xe7, 0x34, 0x77, 0x1f, 0xfd, 0x56, 0x0, 0x0c, 0x57, 0x0, 0x6d, 0x47, 0xe4, 0x32, 0xd7, 0x22, + 0x64, 0xa5, 0x33, 0x65, 0x33, 0x3e, 0x7c, 0x4e, 0x9d, 0xa6, 0xb7, 0x8b, 0xd7, 0xaa, 0x72, 0xe5, + 0x9d, 0xd5, 0xb4, 0x25, 0xcb, 0x30, 0x2, 0xfc, 0xb5, 0xae, 0xb3, 0x88, 0x67, 0x55, 0x0a, 0x7e, + 0x9d, 0xe8, 0x32, 0xfb, 0x50, 0x79, 0x4e, 0x9b, 0x21, 0x92, 0x25, 0x3, 0xa0, 0x15, 0x52, 0x3d, + 0x5e, 0x21, 0x0a, 0x9e, 0x3, 0xdd, 0x3f, 0xcc, 0x38, 0xf6, 0xa9, 0xa6, 0xf8, 0xfd, 0x15, 0x7d, + 0x67, 0x4e, 0x14, 0xae, 0x4d, 0xe2, 0x1f, 0x78, 0x77, 0xfb, 0x83, 0x5f, 0x48, 0xa8, 0xc8, 0x21, + 0x8b, 0xd9, 0xf8, 0x14, 0xe6, 0x42, 0x95, 0xbd, 0x9a, 0x96, 0xbe, 0xf4, 0x7d, 0x26, 0x5d, 0xa1, + 0x81, 0x9b, 0x1c, 0xec, 0xfe, 0xce, 0x9, 0x1d, 0xb7, 0x7a, 0xba, 0xca, 0x7f, 0x54, 0xee, 0x36, + 0x54, 0x65, 0x4a, 0xd0, 0x5c, 0x84, 0x8c, 0x3e, 0x1b, 0xfe, 0x91, 0x6f, 0x95, 0xb5, 0x76, 0xbf, + 0x61, 0x2a, 0x7, 0x23, 0x86, 0xb9, 0xe0, 0x19, 0x29, 0xcf, 0xea, 0x3a, 0x1, 0xbf, 0xee, 0x1b, + 0x5e, 0x3c, 0x4, 0xff, 0x1d, 0xcf, 0xa6, 0x56, 0xb3, 0x22, 0xbb, 0x45, 0x4b, 0x7f, 0x83, 0x87, + 0xef, 0x21, 0x5, 0xf7, 0x38, 0x1f, 0x6, 0x4d, 0x71, 0x0b, 0xe3, 0xe1, 0xb7, 0x7e, 0xae, 0x18 +}; +#endif + +static char dh_except_a_pubkey_4096[] = { + 0xa5, 0x24, 0x63, 0x20, 0xb2, 0x56, 0x9a, 0x94, 0x97, 0xf7, 0x88, 0x41, 0x35, 0xeb, 0x52, 0x37, + 0xa4, 0xf2, 0x74, 0x1b, 0x38, 0xe4, 0x4c, 0x8b, 0x4b, 0xd2, 0xa5, 0xad, 0xb8, 0x2f, 0x7b, 0x5a, + 0xfd, 0xbc, 0x9c, 0xe0, 0xea, 0x9e, 0x82, 0x3, 0x62, 0xe2, 0xdc, 0x6c, 0x56, 0x9, 0x2, 0x28, + 0xb8, 0x2d, 0xb8, 0x46, 0xaf, 0x3a, 0xf4, 0x51, 0xf7, 0x4d, 0xc4, 0xd9, 0xa9, 0x1d, 0x67, 0x9d, + 0x2b, 0x18, 0x56, 0x86, 0x2a, 0x3, 0x19, 0xe9, 0x6, 0xeb, 0x4a, 0x6f, 0x2a, 0x40, 0x28, 0xbb, + 0x3e, 0x87, 0xc1, 0xce, 0x39, 0x6e, 0x3b, 0x1f, 0xb0, 0x9, 0x33, 0x67, 0x19, 0x0e, 0x1a, 0xb2, + 0xb3, 0x7d, 0xd3, 0xe6, 0x33, 0xf4, 0x7c, 0x82, 0x73, 0x7b, 0xb6, 0x16, 0x55, 0xff, 0x76, 0xaf, + 0x7f, 0xc2, 0x42, 0x51, 0xa9, 0xad, 0x1e, 0x72, 0xc9, 0x63, 0xab, 0x41, 0x5a, 0x26, 0x32, 0x39, + 0x5d, 0xa6, 0x7, 0x56, 0x93, 0x89, 0xe5, 0x0f, 0x2a, 0xb5, 0x67, 0x3a, 0xcf, 0xc3, 0x82, 0x83, + 0xf6, 0x88, 0x52, 0x0b, 0xfc, 0x6a, 0x5b, 0x1a, 0x57, 0x87, 0x86, 0xef, 0xda, 0x47, 0xdb, 0x4d, + 0xba, 0xe7, 0x3, 0x5b, 0xe4, 0x70, 0x8b, 0xe0, 0xe1, 0x92, 0x13, 0x86, 0x74, 0x4, 0xdc, 0x6a, + 0x0a, 0x2a, 0x20, 0xec, 0x6d, 0xbf, 0xf0, 0x46, 0xf7, 0x9, 0x2, 0xdb, 0x2f, 0x70, 0x11, 0xdd, + 0xb0, 0x13, 0xa2, 0xc1, 0x58, 0x74, 0x29, 0x19, 0x8d, 0x4a, 0x94, 0x80, 0x0b, 0xd7, 0x25, 0x85, + 0x10, 0x35, 0x97, 0x48, 0x6e, 0x70, 0x28, 0xae, 0x58, 0x97, 0x7d, 0xf2, 0x19, 0x27, 0x13, 0xab, + 0x47, 0x9b, 0x54, 0xdf, 0xc3, 0x5b, 0x5f, 0x5e, 0xb4, 0x64, 0x47, 0xce, 0x40, 0x3b, 0x0c, 0x4a, + 0x62, 0x52, 0xba, 0xc7, 0xf0, 0x36, 0x87, 0x9c, 0x79, 0x9a, 0x83, 0x11, 0x61, 0x0c, 0x1b, 0x6b, + 0xa5, 0x24, 0x63, 0x20, 0xb2, 0x56, 0x9a, 0x94, 0x97, 0xf7, 0x88, 0x41, 0x35, 0xeb, 0x52, 0x37, + 0xa4, 0xf2, 0x74, 0x1b, 0x38, 0xe4, 0x4c, 0x8b, 0x4b, 0xd2, 0xa5, 0xad, 0xb8, 0x2f, 0x7b, 0x5a, + 0xfd, 0xbc, 0x9c, 0xe0, 0xea, 0x9e, 0x82, 0x3, 0x62, 0xe2, 0xdc, 0x6c, 0x56, 0x9, 0x2, 0x28, + 0xb8, 0x2d, 0xb8, 0x46, 0xaf, 0x3a, 0xf4, 0x51, 0xf7, 0x4d, 0xc4, 0xd9, 0xa9, 0x1d, 0x67, 0x9d, + 0x2b, 0x18, 0x56, 0x86, 0x2a, 0x3, 0x19, 0xe9, 0x6, 0xeb, 0x4a, 0x6f, 0x2a, 0x40, 0x28, 0xbb, + 0x3e, 0x87, 0xc1, 0xce, 0x39, 0x6e, 0x3b, 0x1f, 0xb0, 0x9, 0x33, 0x67, 0x19, 0x0e, 0x1a, 0xb2, + 0xb3, 0x7d, 0xd3, 0xe6, 0x33, 0xf4, 0x7c, 0x82, 0x73, 0x7b, 0xb6, 0x16, 0x55, 0xff, 0x76, 0xaf, + 0x7f, 0xc2, 0x42, 0x51, 0xa9, 0xad, 0x1e, 0x72, 0xc9, 0x63, 0xab, 0x41, 0x5a, 0x26, 0x32, 0x39, + 0x5d, 0xa6, 0x7, 0x56, 0x93, 0x89, 0xe5, 0x0f, 0x2a, 0xb5, 0x67, 0x3a, 0xcf, 0xc3, 0x82, 0x83, + 0xf6, 0x88, 0x52, 0x0b, 0xfc, 0x6a, 0x5b, 0x1a, 0x57, 0x87, 0x86, 0xef, 0xda, 0x47, 0xdb, 0x4d, + 0xba, 0xe7, 0x3, 0x5b, 0xe4, 0x70, 0x8b, 0xe0, 0xe1, 0x92, 0x13, 0x86, 0x74, 0x4, 0xdc, 0x6a, + 0x0a, 0x2a, 0x20, 0xec, 0x6d, 0xbf, 0xf0, 0x46, 0xf7, 0x9, 0x2, 0xdb, 0x2f, 0x70, 0x11, 0xdd, + 0xb0, 0x13, 0xa2, 0xc1, 0x58, 0x74, 0x29, 0x19, 0x8d, 0x4a, 0x94, 0x80, 0x0b, 0xd7, 0x25, 0x85, + 0x10, 0x35, 0x97, 0x48, 0x6e, 0x70, 0x28, 0xae, 0x58, 0x97, 0x7d, 0xf2, 0x19, 0x27, 0x13, 0xab, + 0x47, 0x9b, 0x54, 0xdf, 0xc3, 0x5b, 0x5f, 0x5e, 0xb4, 0x64, 0x47, 0xce, 0x40, 0x3b, 0x0c, 0x4a, + 0x62, 0x52, 0xba, 0xc7, 0xf0, 0x36, 0x87, 0x9c, 0x79, 0x9a, 0x83, 0x11, 0x61, 0x0c, 0x1b, 0x6b +}; + +static char dh_except_b_pubkey_4096[] = { + 0x44, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x9, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x4, 0xe8, 0x9a, 0xd2, 0x0, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x0, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x5, + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x7, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x3, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x1, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7, + 0x44, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x9, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x4, 0xe8, 0x9a, 0xd2, 0x0, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x0, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x5, + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x7, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x3, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x1, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7 +}; + +static char dh_share_key_4096[] = { + 0xaf, 0xd4, 0xf6, 0x45, 0x63, 0x21, 0x8d, 0x98, 0xc4, 0xab, 0x18, 0xd7, 0x2b, 0x3c, 0x1d, 0xde, + 0xe7, 0x1f, 0xe1, 0xc5, 0x79, 0x57, 0x60, 0x20, 0xfa, 0x99, 0xbd, 0x7b, 0xa2, 0x94, 0x0b, 0xa3, + 0xb4, 0xb3, 0x33, 0x4a, 0x2f, 0xd0, 0x17, 0x7, 0x2e, 0x70, 0x19, 0x84, 0x1f, 0x8e, 0xe9, 0x61, + 0xe5, 0x52, 0x3, 0x96, 0xea, 0xd8, 0xb6, 0x3, 0x9f, 0xc4, 0x3e, 0x23, 0x77, 0x17, 0x54, 0xfb, + 0x13, 0xf0, 0x3e, 0x9a, 0x27, 0x5d, 0x12, 0x99, 0x58, 0x8d, 0x41, 0x46, 0xd9, 0xc9, 0x29, 0xbd, + 0x40, 0xd1, 0x4f, 0xef, 0x63, 0x7b, 0x54, 0xe6, 0x59, 0x6d, 0xe2, 0x30, 0xe8, 0x2c, 0x2f, 0xf9, + 0x66, 0xa2, 0x12, 0xf5, 0x58, 0x61, 0xac, 0x43, 0xec, 0x7e, 0xf9, 0x2e, 0x27, 0x70, 0x35, 0x75, + 0xb4, 0x10, 0x29, 0xac, 0x0a, 0xab, 0x59, 0xb6, 0x68, 0x4c, 0x16, 0xaf, 0xf0, 0x4f, 0x21, 0xcd, + 0xcc, 0x48, 0x97, 0xe4, 0x21, 0x65, 0xa6, 0x55, 0xb8, 0xf3, 0xb2, 0x7b, 0x91, 0xd7, 0xca, 0xb9, + 0x17, 0x58, 0x31, 0x71, 0xc0, 0xc9, 0x69, 0x1e, 0xf0, 0x9e, 0x3f, 0xe2, 0x37, 0x4, 0x2d, 0xa8, + 0x55, 0x9, 0x6b, 0x9c, 0xc6, 0x37, 0xa9, 0x9b, 0xdf, 0x67, 0x73, 0x7b, 0x46, 0xf9, 0x63, 0x47, + 0xcb, 0xa0, 0x57, 0x2a, 0xed, 0x97, 0x2f, 0xfe, 0x92, 0xf2, 0x20, 0x2c, 0x7e, 0xee, 0x7d, 0x11, + 0x78, 0xe6, 0xb9, 0x9, 0xd1, 0x94, 0xce, 0xd1, 0x5b, 0xf4, 0x44, 0xa9, 0xcb, 0x26, 0x2, 0x36, + 0x57, 0x2c, 0xa2, 0xbe, 0x37, 0xde, 0x86, 0x46, 0x20, 0x27, 0x9d, 0xa0, 0x2f, 0x4, 0xc1, 0xcd, + 0xff, 0x81, 0xe5, 0xe6, 0x2c, 0x9e, 0x39, 0x82, 0x31, 0x54, 0x33, 0xf8, 0xe7, 0xa0, 0xe5, 0x96, + 0xa4, 0x40, 0xc4, 0x44, 0xfe, 0x93, 0x66, 0xe2, 0xda, 0xaa, 0xb8, 0xfb, 0x2f, 0x3b, 0x8c, 0xce, + 0xaf, 0xd4, 0xf6, 0x45, 0x63, 0x21, 0x8d, 0x98, 0xc4, 0xab, 0x18, 0xd7, 0x2b, 0x3c, 0x1d, 0xde, + 0xe7, 0x1f, 0xe1, 0xc5, 0x79, 0x57, 0x60, 0x20, 0xfa, 0x99, 0xbd, 0x7b, 0xa2, 0x94, 0x0b, 0xa3, + 0xb4, 0xb3, 0x33, 0x4a, 0x2f, 0xd0, 0x17, 0x7, 0x2e, 0x70, 0x19, 0x84, 0x1f, 0x8e, 0xe9, 0x61, + 0xe5, 0x52, 0x3, 0x96, 0xea, 0xd8, 0xb6, 0x3, 0x9f, 0xc4, 0x3e, 0x23, 0x77, 0x17, 0x54, 0xfb, + 0x13, 0xf0, 0x3e, 0x9a, 0x27, 0x5d, 0x12, 0x99, 0x58, 0x8d, 0x41, 0x46, 0xd9, 0xc9, 0x29, 0xbd, + 0x40, 0xd1, 0x4f, 0xef, 0x63, 0x7b, 0x54, 0xe6, 0x59, 0x6d, 0xe2, 0x30, 0xe8, 0x2c, 0x2f, 0xf9, + 0x66, 0xa2, 0x12, 0xf5, 0x58, 0x61, 0xac, 0x43, 0xec, 0x7e, 0xf9, 0x2e, 0x27, 0x70, 0x35, 0x75, + 0xb4, 0x10, 0x29, 0xac, 0x0a, 0xab, 0x59, 0xb6, 0x68, 0x4c, 0x16, 0xaf, 0xf0, 0x4f, 0x21, 0xcd, + 0xcc, 0x48, 0x97, 0xe4, 0x21, 0x65, 0xa6, 0x55, 0xb8, 0xf3, 0xb2, 0x7b, 0x91, 0xd7, 0xca, 0xb9, + 0x17, 0x58, 0x31, 0x71, 0xc0, 0xc9, 0x69, 0x1e, 0xf0, 0x9e, 0x3f, 0xe2, 0x37, 0x4, 0x2d, 0xa8, + 0x55, 0x9, 0x6b, 0x9c, 0xc6, 0x37, 0xa9, 0x9b, 0xdf, 0x67, 0x73, 0x7b, 0x46, 0xf9, 0x63, 0x47, + 0xcb, 0xa0, 0x57, 0x2a, 0xed, 0x97, 0x2f, 0xfe, 0x92, 0xf2, 0x20, 0x2c, 0x7e, 0xee, 0x7d, 0x11, + 0x78, 0xe6, 0xb9, 0x9, 0xd1, 0x94, 0xce, 0xd1, 0x5b, 0xf4, 0x44, 0xa9, 0xcb, 0x26, 0x2, 0x36, + 0x57, 0x2c, 0xa2, 0xbe, 0x37, 0xde, 0x86, 0x46, 0x20, 0x27, 0x9d, 0xa0, 0x2f, 0x4, 0xc1, 0xcd, + 0xff, 0x81, 0xe5, 0xe6, 0x2c, 0x9e, 0x39, 0x82, 0x31, 0x54, 0x33, 0xf8, 0xe7, 0xa0, 0xe5, 0x96, + 0xa4, 0x40, 0xc4, 0x44, 0xfe, 0x93, 0x66, 0xe2, 0xda, 0xaa, 0xb8, 0xfb, 0x2f, 0x3b, 0x8c, 0xce, +}; + +#if 0 +static char rsa_e_2048[] = { + 0xaf, 0xd4, 0xf6, 0x45, 0x63, 0x21, 0x8d, 0x98, 0xc4, 0xab, 0x18, 0xd7, 0x2b, 0x3c, 0x1d, 0xde, + 0xe7, 0x1f, 0xe1, 0xc5, 0x79, 0x57, 0x60, 0x20, 0xfa, 0x99, 0xbd, 0x7b, 0xa2, 0x94, 0x0b, 0xa3, + 0xb4, 0xb3, 0x33, 0x4a, 0x2f, 0xd0, 0x17, 0x7, 0x2e, 0x70, 0x19, 0x84, 0x1f, 0x8e, 0xe9, 0x61, + 0xe5, 0x52, 0x3, 0x96, 0xea, 0xd8, 0xb6, 0x3, 0x9f, 0xc4, 0x3e, 0x23, 0x77, 0x17, 0x54, 0xfb, + 0x13, 0xf0, 0x3e, 0x9a, 0x27, 0x5d, 0x12, 0x99, 0x58, 0x8d, 0x41, 0x46, 0xd9, 0xc9, 0x29, 0xbd, + 0x40, 0xd1, 0x4f, 0xef, 0x63, 0x7b, 0x54, 0xe6, 0x59, 0x6d, 0xe2, 0x30, 0xe8, 0x2c, 0x2f, 0xf9, + 0x66, 0xa2, 0x12, 0xf5, 0x58, 0x61, 0xac, 0x43, 0xec, 0x7e, 0xf9, 0x2e, 0x27, 0x70, 0x35, 0x75, + 0xb4, 0x10, 0x29, 0xac, 0x0a, 0xab, 0x59, 0xb6, 0x68, 0x4c, 0x16, 0xaf, 0xf0, 0x4f, 0x21, 0xcd, + 0xcc, 0x48, 0x97, 0xe4, 0x21, 0x65, 0xa6, 0x55, 0xb8, 0xf3, 0xb2, 0x7b, 0x91, 0xd7, 0xca, 0xb9, + 0x17, 0x58, 0x31, 0x71, 0xc0, 0xc9, 0x69, 0x1e, 0xf0, 0x9e, 0x3f, 0xe2, 0x37, 0x4, 0x2d, 0xa8, + 0x55, 0x09, 0x6b, 0x9c, 0xc6, 0x37, 0xa9, 0x9b, 0xdf, 0x67, 0x73, 0x7b, 0x46, 0xf9, 0x63, 0x47, + 0xcb, 0xa0, 0x57, 0x2a, 0xed, 0x97, 0x2f, 0xfe, 0x92, 0xf2, 0x20, 0x2c, 0x7e, 0xee, 0x7d, 0x11, + 0x78, 0xe6, 0xb9, 0x9, 0xd1, 0x94, 0xce, 0xd1, 0x5b, 0xf4, 0x44, 0xa9, 0xcb, 0x26, 0x2, 0x36, + 0x57, 0x2c, 0xa2, 0xbe, 0x37, 0xde, 0x86, 0x46, 0x20, 0x27, 0x9d, 0xa0, 0x2f, 0x4, 0xc1, 0xcd, + 0xff, 0x81, 0xe5, 0xe6, 0x2c, 0x9e, 0x39, 0x82, 0x31, 0x54, 0x33, 0xf8, 0xe7, 0xa0, 0xe5, 0x96, + 0xa4, 0x40, 0xc4, 0x44, 0xfe, 0x93, 0x66, 0xe2, 0xda, 0xaa, 0xb8, 0xfb, 0x2f, 0x3b, 0x8c, 0xce, +}; + +static char rsa_p_2048[] = { + 0xce, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x09, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x04, 0xe8, 0x9a, 0xd2, 0x00, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x00, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x05, + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x07, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x03, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x01, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7 +}; + +static char rsa_q_2048[] = { + 0x44, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x9, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x4, 0xe8, 0x9a, 0xd2, 0x0, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x0, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x5, + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x7, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x3, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x1, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7 +}; +#endif + +/******************************************* ECDH ********************************************/ +static char ecdh_a_secp128k1[] = { + 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc +}; + +static char ecdh_b_secp128k1[] = { + 0xe8, 0x75, 0x79, 0xc1, 0x10, 0x79, 0xf4, 0x3d, 0xd8, 0x24, 0x99, 0x3c, 0x2c, 0xee, 0x5e, 0xd3 +}; + +static char ecdh_p_secp128k1[] = { + 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +static char ecdh_n_secp128k1[] = { + 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x75, 0xa3, 0x0d, 0x1b, 0x90, 0x38, 0xa1, 0x15 +}; + +static char ecdh_g_secp128k1[] = { + 0x16, 0x1f, 0xf7, 0x52, 0x8b, 0x89, 0x9b, 0x2d, 0x0c, 0x28, 0x60, 0x7c, 0xa5, 0x2c, 0x5b, 0x86, + 0xcf, 0x5a, 0xc8, 0x39, 0x5b, 0xaf, 0xeb, 0x13, 0xc0, 0x2d, 0xa2, 0x92, 0xdd, 0xed, 0x7a, 0x83 +}; + +static char ecdh_da_secp128k1[] = { + 0xfe, 0x4e, 0xc2, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x78, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static char ecdh_cp_pubkey_secp128k1[] = { + 0x04, + 0xcc, 0x40, 0x99, 0x3b, 0xcd, 0x0b, 0xcf, 0xcb, 0x9a, 0x96, 0x08, 0x56, 0xc2, 0x96, 0x2c, 0xe1, + 0xdf, 0x69, 0x2a, 0x71, 0xaf, 0x96, 0xe2, 0xeb, 0x5a, 0x26, 0x7f, 0xd3, 0x7a, 0xe8, 0x70, 0xf3 +}; + +static char ecdh_except_b_pubkey_secp128k1[] = { + 0x04, + 0xcc, 0x40, 0x99, 0x3b, 0xcd, 0x0b, 0xcf, 0xcb, 0x9a, 0x96, 0x08, 0x56, 0xc2, 0x96, 0x2c, 0xe1, + 0xdf, 0x69, 0x2a, 0x71, 0xaf, 0x96, 0xe2, 0xeb, 0x5a, 0x26, 0x7f, 0xd3, 0x7a, 0xe8, 0x70, 0xf3 +}; + +static char ecdh_cp_sharekey_secp128k1[] = { + 0x68, 0x55, 0x71, 0xa4, 0xd7, 0x51, 0x49, 0xa8, 0x78, 0xa8, 0x3a, 0xc1, 0x3f, 0xb3, 0x8c, 0xcb +}; + +/* ecc sign or verf*/ +static char ecc_except_kinv_secp128k1[] = { + 0xfe, 0x4e, 0xc2, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x78, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static char ecc_except_e_secp128k1[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x4 +}; + +#if 0 +static char ecc_cp_sign_secp128k1[] = { + 0x30, 0x25, 0x02, 0x11, 0x00, 0xcc, 0x40, 0x99, 0x3b, 0xcd, 0x0b, 0xcf, 0xcb, 0x9a, 0x96, 0x08, + 0x56, 0xc2, 0x96, 0x2c, 0xe1, 0x02, 0x10, 0x00, 0x82, 0x2f, 0x85, 0xdc, 0xaf, 0xbe, 0x2a, 0x8a, + 0x72, 0xc2, 0x1b, 0xcd, 0x8a, 0xd5, 0x71 +}; +#endif + +static char ecdh_a_secp192k1[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static char ecdh_b_secp192k1[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03 +}; + +static char ecdh_p_secp192k1[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xee, 0x37 +}; + +static char ecdh_n_secp192k1[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x26, 0xf2, 0xfc, 0x17, + 0x0f, 0x69, 0x46, 0x6a, 0x74, 0xde, 0xfd, 0x8d +}; + +static char ecdh_g_secp192k1[] = { + 0xdb, 0x4f, 0xf1, 0x0e, 0xc0, 0x57, 0xe9, 0xae, 0x26, 0xb0, 0x7d, 0x02, 0x80, 0xb7, 0xf4, 0x34, + 0x1d, 0xa5, 0xd1, 0xb1, 0xea, 0xe0, 0x6c, 0x7d, + 0x9b, 0x2f, 0x2f, 0x6d, 0x9c, 0x56, 0x28, 0xa7, 0x84, 0x41, 0x63, 0xd0, 0x15, 0xbe, 0x86, 0x34, + 0x40, 0x82, 0xaa, 0x88, 0xd9, 0x5e, 0x2f, 0x9d +}; + +static char ecdh_da_secp192k1[] = { + 0x2b, 0x58, 0xc2, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x58, 0xc2, 0x5e, 0x00, 0x00, 0x00, 0x00, + 0x67, 0x6a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static char ecdh_cp_pubkey_secp192k1[] = { + 0x04, + 0xec, 0x0e, 0x64, 0xac, 0x04, 0x2a, 0x88, 0x86, 0xed, 0xc1, 0xf2, 0x50, 0x0f, 0xe1, 0x27, 0x63, + 0x86, 0x63, 0x9e, 0xb2, 0x82, 0x21, 0x6e, 0x3f, 0x48, 0x59, 0x76, 0xb9, 0x4e, 0xd9, 0xe2, 0x02, + 0xb4, 0xdb, 0xfc, 0x8f, 0x49, 0xe7, 0x24, 0x9b, 0xbe, 0x33, 0xee, 0xc8, 0xcc, 0x9e, 0x00, 0x9a +}; + +static char ecdh_cp_sharekey_secp192k1[] = { + 0x79, 0xd3, 0x1c, 0x98, 0xfb, 0xd2, 0xb6, 0x7c, 0x60, 0x4b, 0x6e, 0x4c, 0xa9, 0x95, 0xcb, 0xac, + 0xb0, 0xf9, 0x05, 0xed, 0x9a, 0xcb, 0x2e, 0x5b +}; + +static char ecdh_except_b_pubkey_secp192k1[] = { + 0x04, + 0xec, 0x0e, 0x64, 0xac, 0x04, 0x2a, 0x88, 0x86, 0xed, 0xc1, 0xf2, 0x50, 0x0f, 0xe1, 0x27, 0x63, + 0x86, 0x63, 0x9e, 0xb2, 0x82, 0x21, 0x6e, 0x3f, 0x48, 0x59, 0x76, 0xb9, 0x4e, 0xd9, 0xe2, 0x02, + 0xb4, 0xdb, 0xfc, 0x8f, 0x49, 0xe7, 0x24, 0x9b, 0xbe, 0x33, 0xee, 0xc8, 0xcc, 0x9e, 0x00, 0x9a +}; + +/* ecc sign or verf*/ +static char ecc_except_kinv_secp192k1[] = { + 0x71, 0x71, 0xb4, 0x5b, 0x79, 0x51, 0x94, 0x70, 0x53, 0xf9, 0x77, 0x02, 0x64, 0xef, 0xc4, 0xdb, + 0x64, 0xfc, 0xbe, 0x4e, 0x44, 0x4a, 0xc6, 0x54 +}; + +static char ecc_except_e_secp192k1[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04 +}; + + +static char ecdh_a_secp256k1[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static char ecdh_b_secp256k1[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07 +}; + +static char ecdh_p_secp256k1[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f +}; + +static char ecdh_n_secp256k1[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, + 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41 +}; + +static char ecdh_g_secp256k1[] = { + 0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B, 0x07, + 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9, 0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98, + 0x48, 0x3a, 0xda, 0x77, 0x26, 0xa3, 0xc4, 0x65, 0x5d, 0xa4, 0xfb, 0xfc, 0x0e, 0x11, 0x08, 0xa8, + 0xfd, 0x17, 0xb4, 0x48, 0xa6, 0x85, 0x54, 0x19, 0x9c, 0x47, 0xd0, 0x8f, 0xfb, 0x10, 0xd4, 0xb8 +}; + +static char ecdh_da_secp256k1[] = { + 0x71, 0x71, 0xb4, 0x5b, 0x79, 0x51, 0x94, 0x70, 0x53, 0xf9, 0x77, 0x02, 0x64, 0xef, 0xc4, 0xdb, + 0x64, 0xfc, 0xbe, 0x4e, 0x44, 0x4a, 0xc6, 0x54, 0x71, 0x69, 0x2e, 0x4a, 0x46, 0xa7, 0x2d, 0xa3 +}; + +#if 0 +static char ecdh_db_secp256k1[] = { + 0xe2, 0x74, 0x69, 0xc8, 0x17, 0x6c, 0x0d, 0xca, 0xdd, 0x9e, 0xf6, 0x2f, 0x30, 0x9f, 0xad, 0xf3, + 0xdd, 0x16, 0xcc, 0x0c, 0xb1, 0xd0, 0x7b, 0xf4, 0xde, 0x9d, 0xf2, 0x5d, 0x22, 0x03, 0xce, 0x41 +}; +#endif + +static char ecdh_cp_pubkey_secp256k1[] = { + 0x04, + 0x68, 0xae, 0x87, 0x7c, 0x45, 0xb3, 0x8b, 0xa8, 0xa8, 0x8e, 0x4b, 0xe5, 0x1f, 0x4e, 0xe6, 0x89, + 0x67, 0x73, 0x71, 0x96, 0x92, 0x2e, 0x57, 0x07, 0xc4, 0x30, 0xa5, 0xcf, 0x9f, 0x58, 0xb0, 0x6f, + 0x26, 0xd3, 0x58, 0xa4, 0xb6, 0xfc, 0xb6, 0x4b, 0x0f, 0x63, 0xd9, 0xa6, 0xa0, 0x1b, 0xba, 0x10, + 0x10, 0xa4, 0xab, 0x28, 0x6e, 0xab, 0x51, 0x34, 0xac, 0x3d, 0x2b, 0x39, 0xf1, 0xd7, 0x21, 0x48 +}; + +static char ecdh_except_b_pubkey_secp256k1[] = { + 0x04, + 0x90, 0x34, 0x99, 0xc8, 0x9e, 0x32, 0xdb, 0xcd, 0x24, 0x4e, 0x31, 0x51, 0x1c, 0x83, 0x4b, 0xf7, + 0x68, 0xf0, 0xbb, 0xa3, 0x91, 0x38, 0xa8, 0xf1, 0xab, 0x76, 0x36, 0xcd, 0x23, 0x3f, 0x57, 0x3b, + 0x22, 0x1a, 0x3f, 0x2e, 0x40, 0x8b, 0xe2, 0x7b, 0xd4, 0x91, 0xe4, 0xf2, 0x36, 0x00, 0xbe, 0xae, + 0x9c, 0xf2, 0xfc, 0xb4, 0xb9, 0x8b, 0x5b, 0xa7, 0x39, 0x88, 0xf2, 0x3b, 0xe2, 0xe5, 0xab, 0x1b +}; + +static char ecdh_cp_sharekey_secp256k1[] = { + 0xd8, 0x9d, 0x1e, 0x25, 0xa2, 0x5, 0xd8, 0xad, 0x0f, 0x1c, 0x7a, 0x44, 0xd4, 0xe6, 0x96, 0xc2, + 0xd3, 0xbc, 0x05, 0xa1, 0x8d, 0x4a, 0x2, 0x11, 0x0e, 0x93, 0xcd, 0xb9, 0x56, 0xd6, 0x44, 0x1c, +}; + +/* ecc sign or verf*/ +static char ecc_except_kinv_secp256k1[] = { + 0x71, 0x71, 0xb4, 0x5b, 0x79, 0x51, 0x94, 0x70, 0x53, 0xf9, 0x77, 0x02, 0x64, 0xef, 0xc4, 0xdb, + 0x64, 0xfc, 0xbe, 0x4e, 0x44, 0x4a, 0xc6, 0x54, 0x71, 0x69, 0x2e, 0x4a, 0x46, 0xa7, 0x2d, 0xa3 +}; + +static char ecc_except_e_secp256k1[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04 +}; + +static char ecc_cp_sign_secp256k1[] = { + 0x30,0x45,0x02,0x20,0x68,0xae,0x87,0x7c,0x45,0xb3,0x8b,0xa8,0xa8,0x8e,0x4b,0xe5, + 0x1f,0x4e,0xe6,0x89,0x67,0x73,0x71,0x96,0x92,0x2e,0x57,0x07,0xc4,0x30,0xa5,0xcf, + 0x9f,0x58,0xb0,0x6f,0x02,0x21,0x00,0xdb,0x14,0xac,0x48,0x0d,0x0a,0xe9,0xe4,0x1d, + 0x8d,0xca,0x47,0xb6,0x0e,0x44,0xf6,0xfb,0xde,0x86,0x9b,0x38,0x76,0x98,0x67,0x12, + 0x7f,0x1d,0x09,0x97,0xab,0xc2,0xcb +}; + +static char ecdh_a_secp320k1[] = { + 0x3e, 0xe3, 0x0b, 0x56, 0x8f, 0xba, 0xb0, 0xf8, 0x83, 0xcc, 0xeb, 0xd4, 0x6d, 0x3f, 0x3b, 0xb8, + 0xa2, 0xa7, 0x35, 0x13, 0xf5, 0xeb, 0x79, 0xda, 0x66, 0x19, 0x0e, 0xb0, 0x85, 0xff, 0xa9, 0xf4, + 0x92, 0xf3, 0x75, 0xa9, 0x7d, 0x86, 0x0e, 0xb4 +}; + +static char ecdh_b_secp320k1[] = { + 0x52, 0x08, 0x83, 0x94, 0x9d, 0xfd, 0xbc, 0x42, 0xd3, 0xad, 0x19, 0x86, 0x40, 0x68, 0x8a, 0x6f, + 0xe1, 0x3f, 0x41, 0x34, 0x95, 0x54, 0xb4, 0x9a, 0xcc, 0x31, 0xdc, 0xcd, 0x88, 0x45, 0x39, 0x81, + 0x6f, 0x5e, 0xb4, 0xac, 0x8f, 0xb1, 0xf1, 0xa6 +}; + +static char ecdh_p_secp320k1[] = { + 0xd3, 0x5e, 0x47, 0x20, 0x36, 0xbc, 0x4f, 0xb7, 0xe1, 0x3c, 0x78, 0x5e, 0xd2, 0x01, 0xe0, 0x65, + 0xf9, 0x8f, 0xcf, 0xa6, 0xf6, 0xf4, 0x0d, 0xef, 0x4f, 0x92, 0xb9, 0xec, 0x78, 0x93, 0xec, 0x28, + 0xfc, 0xd4, 0x12, 0xb1, 0xf1, 0xb3, 0x2e, 0x27 +}; + +static char ecdh_n_secp320k1[] = { + 0xd3, 0x5e, 0x47, 0x20, 0x36, 0xbc, 0x4f, 0xb7, 0xe1, 0x3c, 0x78, 0x5e, 0xd2, 0x01, 0xe0, 0x65, + 0xf9, 0x8f, 0xcf, 0xa5, 0xb6, 0x8f, 0x12, 0xa3, 0x2d, 0x48, 0x2e, 0xc7, 0xee, 0x86, 0x58, 0xe9, + 0x86, 0x91, 0x55, 0x5b, 0x44, 0xc5, 0x93, 0x11 +}; + +static char ecdh_g_secp320k1[] = { + 0x43, 0xbd, 0x7e, 0x9a, 0xfb, 0x53, 0xd8, 0xb8, 0x52, 0x89, 0xbc, 0xc4, 0x8e, 0xe5, 0xbf, 0xe6, + 0xf2, 0x01, 0x37, 0xd1, 0x0a, 0x08, 0x7e, 0xb6, 0xe7, 0x87, 0x1e, 0x2a, 0x10, 0xa5, 0x99, 0xc7, + 0x10, 0xaf, 0x8d, 0x0d, 0x39, 0xe2, 0x06, 0x11, + 0x14, 0xfd, 0xd0, 0x55, 0x45, 0xec, 0x1c, 0xc8, 0xab, 0x40, 0x93, 0x24, 0x7f, 0x77, 0x27, 0x5e, + 0x07, 0x43, 0xff, 0xed, 0x11, 0x71, 0x82, 0xea, 0xa9, 0xc7, 0x78, 0x77, 0xaa, 0xac, 0x6a, 0xc7, + 0xd3, 0x52, 0x45, 0xd1, 0x69, 0x2e, 0x8e, 0xe1, +}; + +static char ecdh_da_secp320k1[] = { + 0x6a, 0x5b, 0xc2, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x21, 0x8e, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x31, 0x00, 0xa0, 0xff, 0xff, 0x00, 0x00, 0x6a, 0x5b, 0xc2, 0x5e, 0x00, 0x00, 0x00, 0x00, + 0x21, 0x8e, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static char ecdh_cp_pubkey_secp320k1[] = { + 0x04, + 0x5f, 0x25, 0x77, 0xa9, 0xb5, 0x0a, 0x6f, 0xd3, 0xcb, 0x43, 0x93, 0xe0, 0xb7, 0x41, 0x3b, 0x56, + 0xc3, 0xfe, 0x1e, 0x5c, 0xb9, 0x32, 0x3a, 0x74, 0x68, 0xf8, 0x69, 0xea, 0xcf, 0x5b, 0x82, 0xd2, + 0x38, 0x8c, 0x96, 0x87, 0x97, 0xc3, 0x89, 0x9d, 0x13, 0x02, 0x40, 0xba, 0x88, 0xfa, 0x0c, 0x5a, + 0x64, 0x52, 0x7c, 0x36, 0xbd, 0xa6, 0x92, 0xb7, 0x6f, 0xb1, 0xd5, 0x81, 0xdb, 0xd5, 0x78, 0x96, + 0x50, 0x6a, 0x48, 0xec, 0x75, 0x04, 0x01, 0x3e, 0x86, 0x07, 0x74, 0x5b, 0xa7, 0x72, 0x44, 0x27 +}; + +static char ecdh_except_b_pubkey_secp320k1[] = { + 0x04, + 0x5f, 0x25, 0x77, 0xa9, 0xb5, 0x0a, 0x6f, 0xd3, 0xcb, 0x43, 0x93, 0xe0, 0xb7, 0x41, 0x3b, 0x56, + 0xc3, 0xfe, 0x1e, 0x5c, 0xb9, 0x32, 0x3a, 0x74, 0x68, 0xf8, 0x69, 0xea, 0xcf, 0x5b, 0x82, 0xd2, + 0x38, 0x8c, 0x96, 0x87, 0x97, 0xc3, 0x89, 0x9d, 0x13, 0x02, 0x40, 0xba, 0x88, 0xfa, 0x0c, 0x5a, + 0x64, 0x52, 0x7c, 0x36, 0xbd, 0xa6, 0x92, 0xb7, 0x6f, 0xb1, 0xd5, 0x81, 0xdb, 0xd5, 0x78, 0x96, + 0x50, 0x6a, 0x48, 0xec, 0x75, 0x04, 0x01, 0x3e, 0x86, 0x07, 0x74, 0x5b, 0xa7, 0x72, 0x44, 0x27 +}; + +static char ecdh_cp_sharekey_secp320k1[] = { + 0x69, 0x8a, 0x70, 0x4e, 0xf8, 0x4a, 0x9a, 0x80, 0xe8, 0x48, 0xc9, 0xb9, 0xac, 0x2a, 0x74, 0xf0, + 0xe5, 0x29, 0x60, 0x6d, 0xf3, 0x4e, 0x01, 0xa6, 0x20, 0x37, 0xc2, 0x0f, 0xba, 0x98, 0x91, 0x3b, + 0xc2, 0x75, 0xa3, 0xc6, 0x75, 0x90, 0x79, 0xb4 +}; + +/* ecc sign or verf*/ +static char ecc_except_kinv_secp320k1[] = { + 0x71, 0x71, 0xb4, 0x5b, 0x79, 0x51, 0x94, 0x70, 0x53, 0xf9, 0x77, 0x02, 0x64, 0xef, 0xc4, 0xdb, + 0x64, 0xfc, 0xbe, 0x4e, 0x44, 0x4a, 0xc6, 0x54, 0x71, 0x69, 0x2e, 0x4a, 0x46, 0xa7, 0x2d, 0xa3 +}; + +static char ecc_except_e_secp320k1[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04 +}; + + +static char ecdh_a_secp384k1[] = { + 0x7b, 0xc3, 0x82, 0xc6, 0x3d, 0x8c, 0x15, 0x0c, 0x3c, 0x72, 0x08, 0x0a, 0xce, 0x05, 0xaf, 0xa0, + 0xc2, 0xbe, 0xa2, 0x8e, 0x4f, 0xb2, 0x27, 0x87, 0x13, 0x91, 0x65, 0xef, 0xba, 0x91, 0xf9, 0x0f, + 0x8a, 0xa5, 0x81, 0x4a, 0x50, 0x3a, 0xd4, 0xeb, 0x04, 0xa8, 0xc7, 0xdd, 0x22, 0xce, 0x28, 0x26 +}; + +static char ecdh_b_secp384k1[] = { + 0x04, 0xa8, 0xc7, 0xdd, 0x22, 0xce, 0x28, 0x26, 0x8b, 0x39, 0xb5, 0x54, 0x16, 0xf0, 0x44, 0x7c, + 0x2f, 0xb7, 0x7d, 0xe1, 0x07, 0xdc, 0xd2, 0xa6, 0x2e, 0x88, 0x0e, 0xa5, 0x3e, 0xeb, 0x62, 0xd5, + 0x7c, 0xb4, 0x39, 0x02, 0x95, 0xdb, 0xc9, 0x94, 0x3a, 0xb7, 0x86, 0x96, 0xfa, 0x50, 0x4c, 0x11 +}; + +static char ecdh_p_secp384k1[] = { + 0x8c, 0xb9, 0x1e, 0x82, 0xa3, 0x38, 0x6d, 0x28, 0x0f, 0x5d, 0x6f, 0x7e, 0x50, 0xe6, 0x41, 0xdf, + 0x15, 0x2f, 0x71, 0x09, 0xed, 0x54, 0x56, 0xb4, 0x12, 0xb1, 0xda, 0x19, 0x7f, 0xb7, 0x11, 0x23, + 0xac, 0xd3, 0xa7, 0x29, 0x90, 0x1d, 0x1a, 0x71, 0x87, 0x47, 0x00, 0x13, 0x31, 0x07, 0xec, 0x53 +}; + +static char ecdh_n_secp384k1[] = { + 0x8c, 0xb9, 0x1e, 0x82, 0xa3, 0x38, 0x6d, 0x28, 0x0f, 0x5d, 0x6f, 0x7e, 0x50, 0xe6, 0x41, 0xdf, + 0x15, 0x2f, 0x71, 0x09, 0xed, 0x54, 0x56, 0xb3, 0x1f, 0x16, 0x6e, 0x6c, 0xac, 0x04, 0x25, 0xa7, + 0xcf, 0x3a, 0xb6, 0xaf, 0x6b, 0x7f, 0xc3, 0x10, 0x3b, 0x88, 0x32, 0x02, 0xe9, 0x04, 0x65, 0x65 +}; + +static char ecdh_g_secp384k1[] = { + 0x1d, 0x1c, 0x64, 0xf0, 0x68, 0xcf, 0x45, 0xff, 0xa2, 0xa6, 0x3a, 0x81, 0xb7, 0xc1, 0x3f, 0x6b, + 0x88, 0x47, 0xa3, 0xe7, 0x7e, 0xf1, 0x4f, 0xe3, 0xdb, 0x7f, 0xca, 0xfe, 0x0c, 0xbd, 0x10, 0xe8, + 0xe8, 0x26, 0xe0, 0x34, 0x36, 0xd6, 0x46, 0xaa, 0xef, 0x87, 0xb2, 0xe2, 0x47, 0xd4, 0xaf, 0x1e, + 0x8a, 0xbe, 0x1d, 0x75, 0x20, 0xf9, 0xc2, 0xa4, 0x5c, 0xb1, 0xeb, 0x8e, 0x95, 0xcf, 0xd5, 0x52, + 0x62, 0xb7, 0x0b, 0x29, 0xfe, 0xec, 0x58, 0x64, 0xe1, 0x9c, 0x05, 0x4f, 0xf9, 0x91, 0x29, 0x28, + 0x0e, 0x46, 0x46, 0x21, 0x77, 0x91, 0x81, 0x11, 0x42, 0x82, 0x03, 0x41, 0x26, 0x3c, 0x53, 0x15 +}; + +static char ecdh_da_secp384k1[] = { + 0x6d, 0x94, 0x28, 0x03, 0xf0, 0xf2, 0xa9, 0x37, 0x2c, 0x3d, 0x5f, 0x1e, 0xc9, 0x04, 0xc8, 0x41, + 0x9b, 0xe1, 0xf6, 0x8f, 0x75, 0xf4, 0x66, 0x57, 0x64, 0xa4, 0xc0, 0x0e, 0xd4, 0x6c, 0x69, 0x5d, + 0x13, 0x07, 0xb5, 0x9c, 0x09, 0xe7, 0xca, 0x0b, 0xd4, 0x87, 0x50, 0x66, 0x2e, 0x03, 0xf8, 0xcc +}; + +static char ecdh_except_b_pubkey_secp384k1[] = { + 0x04, + 0x7c, 0x73, 0x80, 0x31, 0xc6, 0xff, 0x43, 0x03, 0x85, 0x12, 0x9a, 0x4c, 0xd2, 0xf7, 0x69, 0x99, + 0xeb, 0xb1, 0x1a, 0xb3, 0x6c, 0xc2, 0x93, 0x20, 0x1b, 0xaa, 0xaf, 0x94, 0x29, 0x1b, 0x0a, 0x5d, + 0x51, 0x0f, 0x0d, 0x91, 0xfa, 0x31, 0x28, 0x15, 0x66, 0xa9, 0x14, 0xd8, 0xdc, 0xe0, 0x84, 0x8f, + 0x1e, 0x9e, 0xb3, 0xbf, 0x96, 0x8c, 0x2e, 0x87, 0x26, 0xe9, 0x31, 0xdd, 0xf4, 0xae, 0xbf, 0xc0, + 0x34, 0x58, 0xbc, 0xe7, 0xa1, 0x72, 0xca, 0x20, 0x4f, 0xd3, 0xc9, 0xff, 0x17, 0xa1, 0xe4, 0xd1, + 0x14, 0x4a, 0x03, 0xf2, 0xca, 0xf8, 0xae, 0xfe, 0xd8, 0xaf, 0x19, 0xb3, 0x3e, 0x99, 0xa1, 0x36 +}; + +static char ecdh_cp_pubkey_secp384k1[] = { + 0x04, + 0x7c, 0x73, 0x80, 0x31, 0xc6, 0xff, 0x43, 0x03, 0x85, 0x12, 0x9a, 0x4c, 0xd2, 0xf7, 0x69, 0x99, + 0xeb, 0xb1, 0x1a, 0xb3, 0x6c, 0xc2, 0x93, 0x20, 0x1b, 0xaa, 0xaf, 0x94, 0x29, 0x1b, 0x0a, 0x5d, + 0x51, 0x0f, 0x0d, 0x91, 0xfa, 0x31, 0x28, 0x15, 0x66, 0xa9, 0x14, 0xd8, 0xdc, 0xe0, 0x84, 0x8f, + 0x1e, 0x9e, 0xb3, 0xbf, 0x96, 0x8c, 0x2e, 0x87, 0x26, 0xe9, 0x31, 0xdd, 0xf4, 0xae, 0xbf, 0xc0, + 0x34, 0x58, 0xbc, 0xe7, 0xa1, 0x72, 0xca, 0x20, 0x4f, 0xd3, 0xc9, 0xff, 0x17, 0xa1, 0xe4, 0xd1, + 0x14, 0x4a, 0x03, 0xf2, 0xca, 0xf8, 0xae, 0xfe, 0xd8, 0xaf, 0x19, 0xb3, 0x3e, 0x99, 0xa1, 0x36 +}; + +static char ecdh_cp_sharekey_secp384k1[] = { + 0x4a, 0xf1, 0x91, 0x3d, 0x08, 0x60, 0xb0, 0xbd, 0xd3, 0x01, 0xd0, 0xe1, 0xf8, 0x11, 0xfe, 0xb5, + 0xa9, 0xdb, 0x3e, 0x5f, 0x2a, 0x31, 0x53, 0xeb, 0x58, 0x44, 0xf1, 0x19, 0x7f, 0xab, 0x9a, 0x34, + 0xf1, 0x50, 0x02, 0x63, 0xae, 0xd6, 0xa9, 0x28, 0xfc, 0xf3, 0x7d, 0xd4, 0x5e, 0x52, 0xfe, 0x33 +}; + +/* ecc sign or verf*/ +static char ecc_except_kinv_secp384k1[] = { + 0x71, 0x71, 0xb4, 0x5b, 0x79, 0x51, 0x94, 0x70, 0x53, 0xf9, 0x77, 0x02, 0x64, 0xef, 0xc4, 0xdb, + 0x64, 0xfc, 0xbe, 0x4e, 0x44, 0x4a, 0xc6, 0x54, 0x71, 0x69, 0x2e, 0x4a, 0x46, 0xa7, 0x2d, 0xa3 +}; + +static char ecc_except_e_secp384k1[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04 +}; + + +static char ecdh_a_secp521k1[] = { + 0x01, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc +}; + +static char ecdh_b_secp521k1[] = { + 0x00, 0xe6, 0x15, 0x1c, 0x79, 0x17, 0x8d, 0x1b, 0x5c, 0xfa, + 0xbc, 0x7e, 0x53, 0x82, 0xb9, 0x33, 0xbc, 0x16, 0x2c, 0x9f, 0x27, 0xed, 0x6d, 0x79, 0x34, 0xf2, + 0xba, 0x07, 0x92, 0x9e, 0x96, 0xea, 0xe9, 0xdd, 0xb5, 0xae, 0x57, 0x7a, 0x54, 0xe1, 0x3c, 0x71, + 0xa9, 0x6e, 0x3e, 0x3d, 0x88, 0xaf, 0x92, 0x77, 0xe8, 0xe6, 0x61, 0xfe, 0xed, 0x39, 0xbd, 0x11, + 0x19, 0x25, 0x3f, 0x09, 0x4e, 0x71, 0x25, 0xcc +}; + +static char ecdh_p_secp521k1[] = { + 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +static char ecdh_n_secp521k1[] = { + 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x51, 0x86, 0x87, 0x83, 0xbf, 0x2f, 0x96, 0x6b, + 0x7f, 0xcc, 0x01, 0x48, 0xf7, 0x09, 0xa5, 0xd0, 0x3b, 0xb5, 0xc9, 0xb8, 0x89, 0x9c, 0x47, 0xae, + 0xbb, 0x6f, 0xb7, 0x1e, 0x91, 0x38, 0x64, 0x09 +}; + +static char ecdh_g_secp521k1[] = { + 0x00, 0xc6, + 0x85, 0x8e, 0x06, 0xb7, 0x04, 0x04, 0xe9, 0xcd, 0x9e, 0x3e, 0xcb, 0x66, 0x23, 0x95, 0xb4, 0x42, + 0x9c, 0x64, 0x81, 0x39, 0x05, 0x3f, 0xb5, 0x21, 0xf8, 0x28, 0xaf, 0x60, 0x6b, 0x4d, 0x3d, 0xba, + 0xa1, 0x4b, 0x5e, 0x77, 0xef, 0xe7, 0x59, 0x28, 0xfe, 0x1d, 0xc1, 0x27, 0xa2, 0xff, 0xa8, 0xde, + 0x33, 0x48, 0xb3, 0xc1, 0x85, 0x6a, 0x42, 0x9b, 0xf9, 0x7e, 0x7e, 0x31, 0xc2, 0xe5, 0xbd, 0x66, + + 0x01, 0x18, 0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b, 0xc0, 0x04, + 0x5c, 0x8a, 0x5f, 0xb4, 0x2c, 0x7d, 0x1b, 0xd9, 0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b, 0x44, 0x68, + 0x17, 0xaf, 0xbd, 0x17, 0x27, 0x3e, 0x66, 0x2c, 0x97, 0xee, 0x72, 0x99, 0x5e, 0xf4, 0x26, 0x40, + 0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad, 0x07, 0x61, 0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72, 0xc2, 0x40, + 0x88, 0xbe, 0x94, 0x76, 0x9f, 0xd1, 0x66, 0x50 +}; + +static char ecdh_da_secp521k1[] = { + 0x00, 0xe6, 0x15, 0x1c, 0x79, 0x17, 0x8d, 0x1b, 0x5c, 0xfa, + 0xbc, 0x7e, 0x53, 0x82, 0xb9, 0x33, 0xbc, 0x16, 0x2c, 0x9f, 0x27, 0xed, 0x6d, 0x79, 0x34, 0xf2, + 0xba, 0x07, 0x92, 0x9e, 0x96, 0xea, 0xe9, 0xdd, 0xb5, 0xae, 0x57, 0x7a, 0x54, 0xe1, 0x3c, 0x71, + 0xa9, 0x6e, 0x3e, 0x3d, 0x88, 0xaf, 0x92, 0x77, 0xe8, 0xe6, 0x61, 0xfe, 0xed, 0x39, 0xbd, 0x11, + 0x19, 0x25, 0x3f, 0x09, 0x4e, 0x71, 0x25, 0xcc +}; + +static char ecdh_except_b_pubkey_secp521k1[] = { + 0x04, + 0x01, 0x16, 0x0a, 0x52, 0xaa, 0x18, 0x96, 0x56, 0xf6, 0x27, 0xd1, 0x59, 0xbd, 0x7d, 0x0f, 0x57, + 0xfd, 0x34, 0xfa, 0x52, 0x1b, 0x04, 0xbd, 0x9a, 0x90, 0xd5, 0x8d, 0xad, 0x41, 0x32, 0x80, 0x14, + 0x6e, 0x73, 0x58, 0x83, 0x98, 0xeb, 0xb0, 0x6b, 0xb5, 0x63, 0x8e, 0xa1, 0x06, 0x04, 0x86, 0x94, + 0x9e, 0x34, 0x53, 0xf4, 0x93, 0x37, 0x1c, 0xbc, 0xbb, 0x7b, 0x4c, 0x97, 0x87, 0x32, 0x92, 0xf2, + 0x36, 0xdd, 0x01, 0x30, 0xa1, 0xa7, 0x68, 0x5a, 0x3e, 0x40, 0xe9, 0xbf, 0x3d, 0x2a, 0x1b, 0xbf, + 0x09, 0xa0, 0x51, 0xe8, 0x1d, 0x23, 0x27, 0x9c, 0x70, 0xb2, 0x18, 0x42, 0x02, 0x09, 0x02, 0x66, + 0xc7, 0xdb, 0x1a, 0xec, 0xe5, 0x20, 0x68, 0x31, 0x31, 0x6e, 0x70, 0xbe, 0x09, 0x72, 0x79, 0x42, + 0xe2, 0x3b, 0x3b, 0xd3, 0x0a, 0xe4, 0x9c, 0x34, 0x4c, 0x61, 0x74, 0x7c, 0xed, 0xe1, 0x84, 0x89, + 0x4b, 0xf4, 0xd5, 0xc3 +}; + +static char ecdh_cp_pubkey_secp521k1[] = { + 0x04, + 0x01, 0x16, 0x0a, 0x52, 0xaa, 0x18, 0x96, 0x56, 0xf6, 0x27, 0xd1, 0x59, 0xbd, 0x7d, 0x0f, 0x57, + 0xfd, 0x34, 0xfa, 0x52, 0x1b, 0x04, 0xbd, 0x9a, 0x90, 0xd5, 0x8d, 0xad, 0x41, 0x32, 0x80, 0x14, + 0x6e, 0x73, 0x58, 0x83, 0x98, 0xeb, 0xb0, 0x6b, 0xb5, 0x63, 0x8e, 0xa1, 0x06, 0x04, 0x86, 0x94, + 0x9e, 0x34, 0x53, 0xf4, 0x93, 0x37, 0x1c, 0xbc, 0xbb, 0x7b, 0x4c, 0x97, 0x87, 0x32, 0x92, 0xf2, + 0x36, 0xdd, 0x01, 0x30, 0xa1, 0xa7, 0x68, 0x5a, 0x3e, 0x40, 0xe9, 0xbf, 0x3d, 0x2a, 0x1b, 0xbf, + 0x09, 0xa0, 0x51, 0xe8, 0x1d, 0x23, 0x27, 0x9c, 0x70, 0xb2, 0x18, 0x42, 0x02, 0x09, 0x02, 0x66, + 0xc7, 0xdb, 0x1a, 0xec, 0xe5, 0x20, 0x68, 0x31, 0x31, 0x6e, 0x70, 0xbe, 0x09, 0x72, 0x79, 0x42, + 0xe2, 0x3b, 0x3b, 0xd3, 0x0a, 0xe4, 0x9c, 0x34, 0x4c, 0x61, 0x74, 0x7c, 0xed, 0xe1, 0x84, 0x89, + 0x4b, 0xf4, 0xd5, 0xc3 +}; + +static char ecdh_cp_sharekey_secp521k1[] = { + 0x01, 0xaf, 0x53, 0x84, 0x60, 0x59, 0x79, 0x64, 0x09, 0x5f, 0x2b, 0x4e, 0x82, 0xc4, 0x79, 0x21, + 0x55, 0x9c, 0xb0, 0x2f, 0x7d, 0xd4, 0x2f, 0x5d, 0xca, 0xfc, 0x4f, 0x70, 0x28, 0x6e, 0x2b, 0x13, + 0x2e, 0x5f, 0xf0, 0x1f, 0x50, 0x87, 0xf5, 0x82, 0x2f, 0xa7, 0x31, 0x5b, 0xfd, 0x5c, 0x0e, 0xef, + 0xaf, 0x5c, 0x80, 0x53, 0x48, 0xed, 0xcf, 0x14, 0xdc, 0x91, 0xc5, 0xc9, 0x1b, 0xff, 0xa8, 0x16, + 0x42, 0xa8 +}; + +/* ecc sign or verf*/ +static char ecc_except_kinv_secp521k1[] = { + 0x71, 0x71, 0xb4, 0x5b, 0x79, 0x51, 0x94, 0x70, 0x53, 0xf9, 0x77, 0x02, 0x64, 0xef, 0xc4, 0xdb, + 0x64, 0xfc, 0xbe, 0x4e, 0x44, 0x4a, 0xc6, 0x54, 0x71, 0x69, 0x2e, 0x4a, 0x46, 0xa7, 0x2d, 0xa3 +}; + +static char ecc_except_e_secp521k1[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04 +}; + +/* sm2 sign/verf*/ +static char sm2_plaintext[] = { + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, +}; + +static char sm2_digest[] = { /* "message digest" */ + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, +}; + +static char sm2_id[] = { /* "ALICE123@YAHOO.COM" */ + 0x41, 0x4c, 0x49, 0x43, 0x45, 0x31, 0x32, 0x33, 0x40, 0x59, 0x41, 0x48, 0x4f, 0x4f, + 0x2e, 0x43, 0x4f, 0x4d +}; + +static char sm2_priv[] = { + 0x39, 0x45, 0x20, 0x8F, 0x7B, 0x21, 0x44, 0xB1, 0x3F, 0x36, 0xE3, 0x8A, 0xC6, 0xD3, 0x9F, 0x95, + 0x88, 0x93, 0x93, 0x69, 0x28, 0x60, 0xB5, 0x1A, 0x42, 0xFB, 0x81, 0xEF, 0x4D, 0xF7, 0xC5, 0xB8, +}; + +static char sm2_pubkey[] = { + 0x04, + 0x09, 0xF9, 0xDF, 0x31, 0x1E, 0x54, 0x21, 0xA1, 0x50, 0xDD, 0x7D, 0x16, 0x1E, 0x4B, 0xC5, 0xC6, + 0x72, 0x17, 0x9F, 0xAD, 0x18, 0x33, 0xFC, 0x07, 0x6B, 0xB0, 0x8F, 0xF3, 0x56, 0xF3, 0x50, 0x20, + 0xCC, 0xEA, 0x49, 0x0C, 0xE2, 0x67, 0x75, 0xA5, 0x2D, 0xC6, 0xEA, 0x71, 0x8C, 0xC1, 0xAA, 0x60, + 0x0A, 0xED, 0x05, 0xFB, 0xF3, 0x5E, 0x08, 0x4A, 0x66, 0x32, 0xF6, 0x07, 0x2D, 0xA9, 0xAD, 0x13, +}; + +static char sm2_k[64] = { + 0x7c, 0x47, 0x81, 0x10, 0x54, 0xc6, 0xf9, 0x96, 0x13, 0xa5, 0x78, 0xeb, 0x84, 0x53, 0x70, 0x6c, + 0xcb, 0x96, 0x38, 0x4f, 0xe7, 0xdf, 0x5c, 0x17, 0x16, 0x71, 0xe7, 0x60, 0xbf, 0xa8, 0xbe, 0x3a, +}; + +static char sm2_cp_sign[] = { + /* r */ + 0x40, 0xF1, 0xEC, 0x59, 0xF7, 0x93, 0xD9, 0xF4, 0x9E, 0x09, 0xDC, 0xEF, 0x49, 0x13, 0x0D, 0x41, + 0x94, 0xF7, 0x9F, 0xB1, 0xEE, 0xD2, 0xCA, 0xA5, 0x5B, 0xAC, 0xDB, 0x49, 0xC4, 0xE7, 0x55, 0xD1, + + /* s */ + 0x6F, 0xC6, 0xDA, 0xC3, 0x2C, 0x5D, 0x5C, 0xF1, 0x0C, 0x77, 0xDF, 0xB2, 0x0F, 0x7C, 0x2E, 0xB6, + 0x67, 0xA4, 0x57, 0x87, 0x2F, 0xB0, 0x9E, 0xC5, 0x63, 0x27, 0xA6, 0x7E, 0xC7, 0xDE, 0xEB, 0xE7, +}; + +static char sm2_cp_c[] = { + /* c1 x */ + 0x54, 0xa0, 0x03, 0xdd, 0xc9, 0x1c, 0x0b, 0x4e, 0xd6, 0xb8, 0x4c, 0xbc, 0x8d, 0xe6, 0x98, 0xeb, + 0x98, 0x01, 0x06, 0x1c, 0x3c, 0x19, 0xd5, 0x65, 0x1d, 0x29, 0xe4, 0xd0, 0xed, 0xf2, 0x8e, 0x43, + /* c1 y */ + 0x5a, 0x85, 0x93, 0x6a, 0xf4, 0xd9, 0x7d, 0xef, 0x09, 0xd6, 0x37, 0xf2, 0x78, 0x78, 0x78, 0xa3, + 0x2f, 0xd5, 0xe9, 0x6e, 0x1f, 0x0e, 0x9a, 0x10, 0x1f, 0x19, 0x96, 0xe5, 0x2b, 0xf1, 0x63, 0xd9, + /* c3 */ + 0x03, 0xaa, 0x38, 0x9b, 0x54, 0x4a, 0x2d, 0xdb, 0xbe, 0x0d, 0xf8, 0x83, 0x5e, 0xd2, 0xa3, 0x35, + 0xa1, 0xbf, 0x1c, 0xfd, 0x9b, 0x37, 0x3f, 0x3d, 0xf3, 0x94, 0x21, 0xfb, 0xcf, 0x3b, 0xfa, 0xc3, + /* c2 */ + 0x38, 0x9d, 0x38, 0x5b, 0x92, 0xe7, 0x26, 0x56, 0x56, 0x2c, 0x5d, 0x45, 0x1f, 0x7a, +}; +#endif diff --git a/uadk/v1/test/hisi_hpre_test/hpre_test_tools.c b/uadk/v1/test/hisi_hpre_test/hpre_test_tools.c new file mode 100644 index 0000000..d966a9e --- /dev/null +++ b/uadk/v1/test/hisi_hpre_test/hpre_test_tools.c @@ -0,0 +1,1977 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +#include +#include +#include +#define __USE_GNU +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../../wd.h" +#include "../../drv/hisi_qm_udrv.h" +#include "../../wd_bmm.h" +#include "../../wd_rsa.h" +#include "../../wd_dh.h" +#include "test_hisi_hpre.h" + + +#define BLK_NUM_TIMES(x,y) ((y) * 100 / (x)) +#define BLK_NUM_VALUE 87 + +struct thread_info +{ + struct wd_queue q; + pthread_t thread_id; + time_t p_time; +}; + + +/*** +函数功能: + dh 业务 +***/ + +#define BN_ULONG unsigned long +#define DH_GENERATOR_2 2 +#define DH_GENERATOR_5 5 +#define HPRE_TST_PRT printf + +struct big_number { + BN_ULONG *n; + int latest; + int size_d; + int flag_neg; + int flags; +}; + +/* stub structures */ +struct rsa_st { + int xxx; +}; + +struct dh_st { + int xxx; +}; + +struct bn_gencb_st { + int xxx; +}; +typedef struct dh_st DH; +typedef struct big_number BIGNUM; +typedef struct bn_gencb_st BN_GENCB; +/* +struct hpre_queue_mempool { + struct wd_queue *q; + void *base; + unsigned int *bitmap; + unsigned int block_size; + unsigned int block_num; + unsigned int mem_size; + unsigned int block_align_size; + unsigned int free_num; + unsigned int fail_times; + unsigned long long index; + sem_t sem; + int dev; +}; +*/ +static int key_bits = 2048; +static int openssl_check; + +char* s2b(char* s) { + int i; + for(i = 0; i < 128; i++) { + printf("%x ", s[i]); + } + printf("\n"); +} + +char* s2c(char* a, char* b) { + int i; + for(i = 0; i < 128; i++) { + printf("%d %x %x\n", i, a[i], b[i]); + if(a[i] != b[i]) + printf("error: No. %d failed\n", i); + } + printf("\n"); +} +static int hpre_bn_format(void *buff, int len, int buf_len) +{ + int i = buf_len - 1; + int j = 0; + unsigned char *buf = buff; + + if (!buf || len <= 0) { + HPRE_TST_PRT("%s params err!\n", __func__); + return -1; + } + if (len == buf_len) + return 0; + + if (len < buf_len) + return -1; + + for (j = len - 1; j >= 0; j--, i--) { + if (i >= 0) + buf[j] = buf[i]; + else + buf[j] = 0; + } + return 0; +} + +static int test_hpre_bin_to_crypto_bin(char *dst, char *src, int para_size) +{ + int i = 0, j = 0, cnt = 0; + + if (!dst || !src || para_size <= 0) { + HPRE_TST_PRT("%s params err!\n", __func__); + return -WD_EINVAL; + } + while (!src[j]) + j++; + if (j == 0 && src == dst) + return WD_SUCCESS; + for (i = 0, cnt = j; i < para_size; j++, i++) { + if (i < para_size - cnt) + dst[i] = src[j]; + else + dst[i] = 0; + } + + return WD_SUCCESS; +} + +int hpre_dh_test(void *c, struct hpre_queue_mempool *pool) +{ + DH *a = NULL, *b = NULL; + int ret, generator = DH_GENERATOR_5; + struct wcrypto_dh_op_data opdata_a; + struct wcrypto_dh_op_data opdata_b; + const BIGNUM *ap = NULL, *ag = NULL, + *apub_key = NULL, *apriv_key = NULL; + const BIGNUM *bp = NULL, *bg = NULL, + *bpub_key = NULL, *bpriv_key = NULL; + unsigned char *ap_bin = NULL, *ag_bin = NULL, + *apub_key_bin = NULL, *apriv_key_bin = NULL; + unsigned char *bp_bin = NULL, *bg_bin = NULL, + *bpub_key_bin = NULL, *bpriv_key_bin = NULL; + unsigned char *abuf = NULL; + unsigned char *bbuf = NULL; + struct wd_dtb g; + __u32 gbytes; + void *tag = NULL; + int key_size, key_bits, i; + + if (!pool) { + HPRE_TST_PRT("pool null!\n"); + return -1; + } + + a = DH_new(); + b = DH_new(); + if (!a || !b) { + HPRE_TST_PRT("New DH fail!\n"); + return -1; + } + if (wcrypto_dh_is_g2(c)) + generator = DH_GENERATOR_2; + + key_bits = wcrypto_dh_key_bits(c); + key_size = key_bits >> 3; + + /* Alice generates DH parameters */ + ret = DH_generate_parameters_ex(a, key_bits, generator, NULL); + if (!ret) { + HPRE_TST_PRT("DH_generate_parameters_ex fail!\n"); + goto dh_err; + } + DH_get0_pqg(a, &ap, NULL, &ag); + bp = BN_dup(ap); + bg = BN_dup(ag); + if (!bp || !bg) { + HPRE_TST_PRT("bn dump fail!\n"); + ret = -1; + goto dh_err; + } + /* Set the same parameters on Bob as Alice :) */ + DH_set0_pqg(b, (BIGNUM *)bp, NULL, (BIGNUM *)bg); + if (!DH_generate_key(a)) { + HPRE_TST_PRT("a DH_generate_key fail!\n"); + ret = -1; + goto dh_err; + } + DH_get0_key(a, &apub_key, &apriv_key); + ag_bin = wd_alloc_blk(pool); + if (!ag_bin) { + HPRE_TST_PRT("pool alloc ag_bin fail!\n"); + goto dh_err; + } + memset(ag_bin, 0, key_size * 2); + apriv_key_bin = wd_alloc_blk(pool); + if (!apriv_key_bin) { + HPRE_TST_PRT("pool alloc apriv_key_bin fail!\n"); + goto dh_err; + } + memset(apriv_key_bin, 0, key_size * 2); + + /* The hpre_UM tells us key_addr contains xa and p, + * their addr should be together + */ + ap_bin= apriv_key_bin + key_size; + + gbytes = BN_bn2bin(ag, ag_bin); + g.data = (char*)ag_bin; + g.dsize = key_size; + g.bsize = gbytes; + opdata_a.pbytes = BN_bn2bin(ap, ap_bin); + opdata_a.xbytes = BN_bn2bin(apriv_key, apriv_key_bin); + ret = wcrypto_set_dh_g(c, &g); + if (ret) { + HPRE_TST_PRT("Alice wcrypto_set_dh_g fail!\n"); + goto dh_err; + } + opdata_a.x_p = apriv_key_bin; + opdata_a.pri = wd_alloc_blk(pool); + if (!opdata_a.pri) { + HPRE_TST_PRT("pool alloc opdata_a.pri fail!\n"); + goto dh_err; + } + memset(opdata_a.pri, 0, key_size * 2); + + opdata_a.op_type = WCRYPTO_DH_PHASE1; + + /* Alice computes public key */ + ret = wcrypto_do_dh(c, &opdata_a, tag); + if (ret) { + HPRE_TST_PRT("a wcrypto_do_dh fail!\n"); + goto dh_err; + } + printf("a p1 =>\n"); + s2b(opdata_a.pri); + + if (openssl_check) { + apub_key_bin = malloc(key_size); + if (!apub_key_bin) { + HPRE_TST_PRT("malloc apub_key_bin fail!\n"); + ret = -ENOMEM; + goto dh_err; + } + ret = BN_bn2bin(apub_key, apub_key_bin); + if (!ret) { + HPRE_TST_PRT("apub_key bn 2 bin fail!\n"); + goto dh_err; + } + ret = hpre_bn_format(apub_key_bin, key_size, key_size); + if (ret) { + HPRE_TST_PRT("hpre_bn_format bpub_key bin fail!\n"); + goto dh_err; + } + + for (i = key_size - 1; apub_key_bin[i] == 0 && i >= 0; i--) { + ret = test_hpre_bin_to_crypto_bin(opdata_a.pri, opdata_a.pri, key_size); + if (ret) { + HPRE_TST_PRT("dh out share key format fail!\n"); + goto dh_err; + } + ret = 0; + break; + } + + if (memcmp(apub_key_bin, opdata_a.pri, key_size)) { + HPRE_TST_PRT("Alice HPRE DH key gen pub mismatch!\n"); + ret = -EINVAL; + goto dh_err; + } + } + if (!DH_generate_key(b)) { + HPRE_TST_PRT("b DH_generate_key fail!\n"); + ret = -1; + goto dh_err; + } + DH_get0_key(b, &bpub_key, &bpriv_key); + bg_bin = wd_alloc_blk(pool); + if (!bg_bin) { + HPRE_TST_PRT("pool alloc bg_bin fail!\n"); + ret = -1; + goto dh_err; + } + memset(bg_bin, 0, key_size * 2); + + bpriv_key_bin= wd_alloc_blk(pool); + if (!bpriv_key_bin) { + HPRE_TST_PRT("pool alloc bpriv_key_bin fail!\n"); + ret = -1; + goto dh_err; + } + memset(bpriv_key_bin, 0, key_size * 2); + bp_bin = bpriv_key_bin + key_size; + gbytes = BN_bn2bin(bg, bg_bin); + g.data = (char*)bg_bin; + g.bsize = gbytes; + g.dsize = key_size; + printf("key bits: %d\n", key_bits); + printf("key size: %d\n", key_size); + + ret = wcrypto_set_dh_g(c, &g); + if (ret) { + HPRE_TST_PRT("bob wcrypto_set_dh_g fail!\n"); + goto dh_err; + } + opdata_b.pbytes = BN_bn2bin(bp, bp_bin); + opdata_b.xbytes = BN_bn2bin(bpriv_key, bpriv_key_bin); + opdata_b.x_p = bpriv_key_bin; + opdata_b.pri = wd_alloc_blk(pool); + if (!opdata_b.pri) { + HPRE_TST_PRT("pool alloc opdata_b.pri fail!\n"); + ret = -1; + goto dh_err; + } + memset(opdata_b.pri, 0, key_size * 2); + opdata_b.op_type = WCRYPTO_DH_PHASE1; + + /* Bob computes public key */ + ret = wcrypto_do_dh(c, &opdata_b, tag); + if (ret) { + HPRE_TST_PRT("b wcrypto_do_dh fail!\n"); + goto dh_err; + } + printf("b p1 =>\n"); + s2b(opdata_b.pri); + if (openssl_check) { + bpub_key_bin = malloc(key_size); + if (!bpub_key_bin) { + HPRE_TST_PRT("malloc bpub_key_bin fail!\n"); + ret = -1; + goto dh_err; + } + ret = BN_bn2bin(bpub_key, bpub_key_bin); + if (!ret) { + HPRE_TST_PRT("bpub_key bn 2 bin fail!\n"); + goto dh_err; + } + ret = hpre_bn_format(bpub_key_bin, key_size, key_size); + if (ret) { + HPRE_TST_PRT("hpre_bn_format bpub_key bin fail!\n"); + goto dh_err; + } + + for (i = key_size - 1; bpub_key_bin[i] == 0 && i >= 0; i--) { + ret = test_hpre_bin_to_crypto_bin(opdata_b.pri, opdata_b.pri, key_size); + if (ret) { + HPRE_TST_PRT("dh out share key format fail!\n"); + goto dh_err; + } + ret = 0; + break; + } + + if (memcmp(bpub_key_bin, opdata_b.pri, key_size)) { + HPRE_TST_PRT("Bob HPRE DH key gen pub mismatch!\n"); + ret = -EINVAL; + goto dh_err; + } + } + /* Alice computes private key with OpenSSL */ + abuf = malloc(key_size); + if (!abuf) { + HPRE_TST_PRT("malloc abuf fail!\n"); + ret = -ENOMEM; + goto dh_err; + } + memset(abuf, 0, key_size); + if (openssl_check) { + ret = DH_compute_key(abuf, bpub_key, a); + if (!ret) { + HPRE_TST_PRT("DH_compute_key fail!\n"); + ret = -1; + goto dh_err; + } + } + + /* Alice computes private key with HW accelerator */ + memset(ag_bin, 0, key_size * 2); + memset(apriv_key_bin, 0, key_size * 2); + ap_bin = apriv_key_bin + key_size; + memset(opdata_a.pri, 0, key_size * 2); + + opdata_a.pvbytes = BN_bn2bin(bpub_key, ag_bin); + opdata_a.pv = ag_bin;/* bob's public key here */ + opdata_a.pbytes = BN_bn2bin(ap, ap_bin); + opdata_a.xbytes = BN_bn2bin(apriv_key, apriv_key_bin); + opdata_a.x_p = apriv_key_bin; + opdata_a.pri = wd_alloc_blk(pool); + if (!opdata_a.pri) { + HPRE_TST_PRT("pool alloc opdata_a.pri fail!\n"); + ret = -1; + goto dh_err; + } + memset(opdata_a.pri, 0, key_size * 2); + opdata_a.op_type = WCRYPTO_DH_PHASE2; + + /* Alice computes private key with HPRE */ + ret = wcrypto_do_dh(c, &opdata_a, tag); + if (ret) { + HPRE_TST_PRT("a wcrypto_do_dh fail!\n"); + goto dh_err; + } + //printf("a p2 =>\n"); + //s2b(opdata_a.pri); + if (openssl_check) { + ret = hpre_bn_format(abuf, key_size, key_size); + if (ret) { + HPRE_TST_PRT("hpre_bn_format bpub_key bin fail!\n"); + goto dh_err; + } + + for (i = key_size - 1; abuf[i] == 0 && i >= 0; i--) { + ret = test_hpre_bin_to_crypto_bin(opdata_a.pri, opdata_a.pri, key_size); + if (ret) { + HPRE_TST_PRT("dh out share key format fail!\n"); + goto dh_err; + } + ret = 0; + break; + } + + if (memcmp(abuf, opdata_a.pri, key_size)) { + HPRE_TST_PRT("Alice HPRE DH gen privkey mismatch!\n"); + ret = -EINVAL; + goto dh_err; + } + } + /* Bob computes private key with OpenSSL */ + bbuf = malloc(key_size); + if (!bbuf) { + HPRE_TST_PRT("malloc abuf fail!\n"); + ret = -ENOMEM; + goto dh_err; + } + memset(abuf, 0, key_size); + if (openssl_check) { + ret = DH_compute_key(bbuf, apub_key, b); + if (!ret) { + HPRE_TST_PRT("DH_compute_key fail!\n"); + ret = -1; + goto dh_err; + } + } + + /* Bob computes private key with HW accelerator */ + memset(bg_bin, 0, key_size * 2); + memset(bpriv_key_bin, 0, key_size * 2); + bp_bin = bpriv_key_bin + key_size; + memset(opdata_b.pri, 0, key_size * 2); + + opdata_b.pvbytes = BN_bn2bin(apub_key, bg_bin); + opdata_b.pv = bg_bin;/* bob's public key here */ + opdata_b.pbytes = BN_bn2bin(bp, bp_bin); + opdata_b.xbytes = BN_bn2bin(bpriv_key, bpriv_key_bin); + opdata_b.x_p = bpriv_key_bin; + opdata_b.pri = wd_alloc_blk(pool); + if (!opdata_b.pri) { + HPRE_TST_PRT("pool alloc opdata_a.pri fail!\n"); + ret = -1; + goto dh_err; + } + memset(opdata_b.pri, 0, key_size * 2); + opdata_b.op_type = WCRYPTO_DH_PHASE2; + + /* Bob computes private key with HPRE */ + ret = wcrypto_do_dh(c, &opdata_b, tag); + if (ret) { + HPRE_TST_PRT("b wcrypto_do_dh fail!\n"); + goto dh_err; + } + //printf("b p2 =>\n"); + s2c(opdata_a.pri, opdata_b.pri); + HPRE_TST_PRT("HPRE DH generate key sucessfully!\n"); + dh_err: + DH_free(a); + DH_free(b); + if (ag_bin) + wd_free_blk(pool, ag_bin); + if (apriv_key_bin) + wd_free_blk(pool, apriv_key_bin); + if (opdata_a.pri) + wd_free_blk(pool, opdata_a.pri); + + if (bg_bin) + wd_free_blk(pool, bg_bin); + if (bpriv_key_bin) + wd_free_blk(pool, bpriv_key_bin); + if (opdata_b.pri) + wd_free_blk(pool, opdata_b.pri); + + if (apub_key_bin) + free(apub_key_bin); + if (bpub_key_bin) + free(bpub_key_bin); + if (abuf) + free(abuf); + return ret; +} +int do_dh(struct wd_queue *q) +{ + int ret; + printf("\tinfo: init dh setup\n"); + struct wcrypto_dh_ctx_setup dh_setup; + memset(&dh_setup, 0, sizeof(dh_setup)); + printf("\tinfo: assign dh setup\n"); + dh_setup.key_bits = 1024; + dh_setup.br.alloc = (void *)wd_alloc_blk; + dh_setup.br.free = (void *)wd_free_blk; + dh_setup.br.iova_map = (void *)wd_blk_iova_map; + dh_setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + + printf("info: init pool\n"); + void *pool = NULL; + printf("\tinfo: assign pool\n"); + printf("\tinfo: init wsetup\n"); + struct wd_blkpool_setup wsetup; + memset(&wsetup, 0, sizeof(wsetup)); + printf("\tinfo: assign wsetup\n"); + wsetup.block_size = 2048 >> 2; + wsetup.block_num = 1024; + wsetup.align_size = 64; + pool = wd_blkpool_create(q, &wsetup); + unsigned int num = 0; + sleep(1); + if (wd_get_free_blk_num(pool, &num) == WD_SUCCESS) + printf("pool num = %u\n", num); + sleep(1); + if (wd_blk_alloc_failures(pool, &num) == WD_SUCCESS) + printf("pool fail num = %u\n", num); + dh_setup.br.usr = pool; + + printf("info: create dh ctx\n"); + void *ctx = NULL; + ctx = wcrypto_create_dh_ctx(q, &dh_setup); + + ret = hpre_dh_test(ctx, pool); + + printf("info: delete dh ctx\n"); + wcrypto_del_dh_ctx(ctx); + + printf("info: uninit pool\n"); + wd_blkpool_destroy(pool); + + return ret; +} + + +/*** +函数功能: + 在指定设备上申请单个队列,并给队列预留指定大小的内存; +参数说明: + dev - 指定申请队列的设备 + alg_type - 申请队列的算法类型 + m_size - 队列预留内存大小 +***/ +int hpre_dev_queue_req(char *dev, char *alg_type, unsigned long m_size) +{ + void *addr; + int ret = 0; + struct wd_queue q; + unsigned long memory_size; + + memset((void *)&q, 0, sizeof(q)); + q.capa.alg = alg_type; + snprintf(q.dev_path, sizeof(q.dev_path), "%s", dev); + printf("queue path:%s\n", q.dev_path); + //申请队列 + ret = wd_request_queue(&q); + if(ret) + { + printf("wd request queue fail!\n"); + return ret; + } + printf("wd request queue success,return:%d\n",ret); + memory_size = m_size; + //给队列预留内存 + addr = wd_reserve_memory(&q, memory_size); + if(!addr) + { + wd_release_queue(&q); + printf("wd reserve memory fail!\n"); + return 1; + } + printf("wd reserve memory success!\n"); + memset(addr, 0, memory_size); + //释放队列,会释放所有资源,包括预留内存; + wd_release_queue(&q); + return 0; +} + +/*** + +***/ +int application_release_multiple_queue(char *dev, char *alg_type, unsigned int q_num) +{ + int i, ret = 0; + struct wd_queue *q; + + q = malloc(q_num * sizeof(struct wd_queue)); + if (!q) + return 1; + memset((void *)q, 0, q_num * sizeof(struct wd_queue)); + + for (i = 0; i < q_num; i++) { + q[i].capa.alg = alg_type; + snprintf(q[i].dev_path, sizeof(q[i].dev_path), "%s", dev); + ret = wd_request_queue(&q[i]); + if (ret) { + printf("error: fail q => %d\n", i); + return ret; + } + wd_get_node_id(&q[i]); + } + + for (i = 0; i < q_num; i++) { + wd_release_queue(&q[i]); + } + + printf("application_release_multiple_queue test end!\n"); + return 0; +} + +/*** + +***/ +int hpre_dev_queue_share(char *dev, char * share_dev, char *alg_type, unsigned long m_size) +{ + void *addr=NULL; + int ret = 0; + struct wd_queue q; + struct wd_queue target_q; + unsigned long memory_size; + + memset((void *)&q, 0, sizeof(q)); + q.capa.alg = alg_type; + snprintf(q.dev_path, sizeof(q.dev_path), "%s", dev); + printf("queue path:%s\n", q.dev_path); + + ret = wd_request_queue(&q); + if(ret) + { + printf("wd request queue fail!\n"); + return 1; + } + printf("wd request queue success!\n"); + memory_size = m_size; + addr = wd_reserve_memory(&q, memory_size); + if(!addr) + { + wd_release_queue(&q); + printf("wd reserve memory fail!\n"); + return 1; + } + printf("wd reserve memory success!\n"); + memset(addr, 0, memory_size); + + memset((void *)&target_q, 0, sizeof(target_q)); + target_q.capa.alg = alg_type; + snprintf(target_q.dev_path, sizeof(target_q.dev_path), "%s", share_dev); + printf("target queue path:%s\n", target_q.dev_path); + + ret = wd_request_queue(&target_q); + if(ret) + { + wd_release_queue(&q); + printf("wd request target_q queue fail!\n"); + return 1; + } + printf("wd request target_q queue success!\n"); + //target_q队列共享q队列预留内存; + ret = wd_share_reserved_memory(&q, &target_q); + if(ret) + { + wd_release_queue(&q); + wd_release_queue(&target_q); + printf("wd target_q queue share reserved memory fail!\n"); + return 1; + } + printf("wd target_q queue share reserved memory success!\n"); + wd_release_queue(&target_q); + wd_release_queue(&q); + + return 0; +} +/*** + +***/ +int hpre_node_queue_share(char *dev, unsigned int node, unsigned int share_node, char *alg_type, unsigned long m_size) +{ + void *addr=NULL; + int ret = 0; + struct wd_queue q; + struct wd_queue target_q; + unsigned long memory_size; + + memset((void *)&q, 0, sizeof(q)); + q.capa.alg = alg_type; + snprintf(q.dev_path, sizeof(q.dev_path), "%s", dev); + printf("queue path:%s\n", q.dev_path); + q.node_mask = node; + + ret = wd_request_queue(&q); + if(ret) + { + printf("wd request queue fail!\n"); + return 1; + } + printf("wd request queue success!\n"); + memory_size = m_size; + addr = wd_reserve_memory(&q, memory_size); + if(!addr) + { + wd_release_queue(&q); + printf("wd reserve memory fail!\n"); + return 1; + } + printf("wd reserve memory success!\n"); + memset(addr, 0, memory_size); + + memset((void *)&target_q, 0, sizeof(target_q)); + target_q.capa.alg = alg_type; + target_q.node_mask = node; + + ret = wd_request_queue(&target_q); + if(ret) + { + wd_release_queue(&q); + printf("wd request target_q queue fail!\n"); + return 1; + } + printf("wd request target_q queue success!\n"); + //target_q队列共享q队列预留内存; + ret = do_dh(&q); + if(ret) + { + printf("do dh on q fail!\n"); + return 1; + } + ret = do_dh(&target_q); + if(ret) + { + printf("do dh on target q fail!\n"); + return 1; + } + + ret = wd_share_reserved_memory(&q, &target_q); + + if(ret) + { + wd_release_queue(&q); + wd_release_queue(&target_q); + printf("wd target_q queue share reserved memory fail!\n"); + return 1; + } + printf("wd target_q queue share reserved memory success!\n"); + ret = do_dh(&q); + if(ret) + { + printf("do dh on share q fail!\n"); + return 1; + } + ret = do_dh(&target_q); + if(ret) + { + printf("do dh on share target q fail!\n"); + return 1; + } + + wd_release_queue(&target_q); + wd_release_queue(&q); + + return 0; +} +/*** + +***/ +int hpre_dev_queue_interact_share(char *dev, char * share_dev, char *alg_type, unsigned long m_size) +{ + void *addr=NULL; + int ret = 0; + struct wd_queue q; + struct wd_queue target_q; + unsigned long memory_size; + + memset((void *)&q, 0, sizeof(q)); + q.capa.alg = alg_type; + snprintf(q.dev_path, sizeof(q.dev_path), "%s", dev); + printf("queue path:%s\n", q.dev_path); + + ret = wd_request_queue(&q); + if(ret) + { + printf("wd request queue fail!\n"); + return ret; + } + printf("wd request queue success!\n"); + memory_size = m_size; + addr = wd_reserve_memory(&q, memory_size); + if(!addr) + { + wd_release_queue(&q); + printf("wd reserve memory fail!\n"); + return 1; + } + printf("wd reserve memory success!\n"); + memset(addr, 0, memory_size); + + memset((void *)&target_q, 0, sizeof(target_q)); + target_q.capa.alg = alg_type; + snprintf(target_q.dev_path, sizeof(target_q.dev_path), "%s", share_dev); + printf("target queue path:%s\n", target_q.dev_path); + + ret = wd_request_queue(&target_q); + if(ret) + { + wd_release_queue(&q); + printf("wd request target_q queue fail!\n"); + return 1; + } + printf("wd request target_q queue success!\n"); + addr = wd_reserve_memory(&target_q, memory_size); + if(!addr) + { + wd_release_queue(&q); + wd_release_queue(&target_q); + printf("wd reserve memory fail!\n"); + return 1; + } + printf("wd reserve memory success!\n"); + memset(addr, 0, memory_size); + + //target_q + ret = wd_share_reserved_memory(&q, &target_q); + if(ret) + { + wd_release_queue(&q); + wd_release_queue(&target_q); + printf("wd target_q queue share reserved memory fail!\n"); + return 1; + } + printf("wd target_q queue share reserved memory success!\n"); + + wd_release_queue(&target_q); + wd_release_queue(&q); + + return 0; +} + +/*** + +***/ +int hpre_dev_queue_cross_proc_share(char *dev, char *alg_type, unsigned long m_size) +{ + void *addr=NULL; + int ret = 0; + pid_t pid; + struct wd_queue q; + struct wd_queue target_q; + unsigned long memory_size=0; + + pid = fork(); + if(pid < 0) + { + printf("Creation process failed, pid:%d\n",pid); + return 1; + } + else if(pid == 0) + { + printf("child process:%d\n", pid); + memset((void *)&q, 0, sizeof(q)); + q.capa.alg = alg_type; + snprintf(q.dev_path, sizeof(q.dev_path), "%s", dev); + printf("queue path:%s\n", q.dev_path); + + ret = wd_request_queue(&q); + if(ret) + { + printf("request queue fail!\n"); + exit(1); + } + printf("wd request queue success!\n"); + memory_size = m_size; + addr = wd_reserve_memory(&q, memory_size); + if(!addr) + { + wd_release_queue(&q); + printf("queue reserve memory fail!\n"); + exit(2); + } + printf("queue reserve memory success!\n"); + memset(addr, 0, memory_size); + exit(0); + } + printf("parent process:%d\n", pid); + pid_t wpid; + int status = -1; + wpid = waitpid(pid, &status, WUNTRACED | WCONTINUED); + if( wpid < 0) + { + printf("exited, status=%d\n", WEXITSTATUS(status)); + return(status); + } + + memset((void *)&target_q, 0, sizeof(target_q)); + target_q.capa.alg = alg_type; + snprintf(target_q.dev_path, sizeof(target_q.dev_path), "%s", dev); + printf("target queue path:%s\n", target_q.dev_path); + + ret = wd_request_queue(&target_q); + if(ret) + { + wd_release_queue(&q); + printf("wd request target_q queue fail!\n"); + return 1; + } + printf("wd request target_q queue success!\n"); + ret = wd_share_reserved_memory(&q, &target_q); + if(ret) + { + wd_release_queue(&target_q); + wd_release_queue(&q); + printf("wd target_q queue share reserved memory fail!\n"); + return 1; + } + printf("wd target_q queue share reserved memory success!\n"); + + wd_release_queue(&target_q); + wd_release_queue(&q); + + return 0; +} + +/*** + +***/ +void *create_queue(void *arg) +{ + int ret = 0; + struct thread_info *tinfo = arg; + ret = wd_request_queue(&tinfo ->q); + if(ret) + { + printf("wd request queue fail!\n"); + return NULL; + } + printf("wd request queue success\n"); + + sleep(tinfo ->p_time); + return NULL; +} +/*** + +***/ +int hpre_mult_thread_request_queue(char *dev, char *alg_type, int p_num, time_t p_time) +{ + int i = 0; + void *ret = NULL; + struct thread_info *tinfo; + + printf("pthread_num:%d, times:%ld\n", p_num, p_time); + tinfo = calloc(p_num, sizeof(struct thread_info)); + if(NULL == tinfo) + { + printf("calloc fail...\n"); + return 1; + } + + for(i = 0; i blk_num) + { + pool = wd_blkpool_create(&q, &wsetup); + if (!pool) + { + printf("%s(): create ctx pool fail!\n", __func__); + wd_release_queue(&q); + return 1; + } + printf("%s(): create ctx pool success!\n", __func__); + + wd_get_free_blk_num(pool, &blk_count); + if(blk_count != wsetup.block_num) + { + printf("Memory block release failed, blk count:%u\n", blk_count); + wd_release_queue(&q); + return 1; + } + wd_blkpool_destroy(pool); + blk_count+=1; + } + wd_release_queue(&q); + + return 0; +} + +int hpre_blkpool_interface_fault(void) +{ + unsigned int blk_count = 0; + void *blk = NULL; + struct wd_blkpool *pool = NULL; + + if (wd_get_free_blk_num(pool, &blk_count) == WD_SUCCESS) { + printf("wd_get_free_blk_num fail...\n"); + return -WD_EINVAL; + } + + if (wd_blk_alloc_failures(pool , &blk_count) == WD_SUCCESS) { + printf("wd_blk_alloc_failures fail...\n"); + return 1; + } + blk = wd_blk_iova_map(pool, blk); + if(NULL != blk) + { + printf("wd_blk_dma_map fail...\n"); + return 1; + } + blk = wd_alloc_blk(pool); + if(NULL != blk) + { + printf("wd_alloc_blk...\n"); + return 1; + } + + wd_free_blk(pool, blk); + wd_blkpool_destroy(pool); + + return 0; +} + +int hpre_node_mask(char *dev, unsigned int node, char *alg) +{ + int ret; + + struct wd_queue q; + printf("info: init q %s\n", alg); + + printf("info: assign q\n"); + memset((void *)&q, 0, sizeof(q)); + printf(" | q alg => %s |\n", alg); + q.capa.alg = alg; + printf(" | q dev => %s |\n", dev); + snprintf(q.dev_path, sizeof(q.dev_path), "%s", dev); + printf(" | q node => %d |\n", node); + q.node_mask = node; + + printf("info: request q\n"); + ret = wd_request_queue(&q); + if (ret) { + printf("error: request q fail\n"); + return ret; + } + printf("info: check q\n"); + static int t; + t = wd_get_node_id(&q); + printf(" | q node => %d |\n", t); + t = wd_get_available_dev_num(alg); + printf(" | q dev num => %d |\n", t); + + printf("info: release q\n"); + wd_release_queue(&q); + return ret; +} + +typedef struct thread_data{ + int threadid; + char *dev; + unsigned int node; + char *alg; +}THDATA,*PTHDATA; + +int hpre_node_mask_do(char *dev, unsigned int node, char *alg) +{ + int ret; + + struct wd_queue q; + memset((void *)&q, 0, sizeof(q)); + q.capa.alg = alg; + snprintf(q.dev_path, sizeof(q.dev_path), "%s", dev); + q.node_mask = node; + ret = wd_request_queue(&q); + if (ret) { + printf("error: request q fail\n"); + return ret; + } + wd_get_node_id(&q); + wd_get_available_dev_num(alg); + wd_release_queue(&q); + return ret; +} +void *hpre_node_mask_thread(void *pthreadid) +{ + PTHDATA tid = (PTHDATA)pthreadid; + + printf("info: thread %d\n dev %s\n node %d\n alg %s\n", tid->threadid, tid->dev, tid->node, tid->alg); + hpre_node_mask_do(tid->dev, tid->node, tid->alg); + // return 0; +} + +/*** +argv[1] - 表示运行业务的类型 +***/ +int main(int arc, char *argv[]) +{ + int ret = 0; + int count = 0; + int queue_num = 0; + int pthread_num = 0; + time_t p_time = 0; + char dev[256]={0}; + char share_dev[256]={0}; + char algorithm_type[10]={0}; + unsigned int blk_size=0; + unsigned int blk_num=0; + unsigned int align_size=0; + unsigned long memory_size=0; + + if(!strcmp(argv[1], "available-dev")) + { + /*** + argv[2] - 表示算法类型 + ***/ + //查询算法的可用设备 + snprintf(algorithm_type, sizeof(algorithm_type), "%s", argv[2]); + count = wd_get_available_dev_num(algorithm_type); + printf("algorithm dev:%d\n",count); + + return count; + } + else if(!strcmp(argv[1], "queue-req")) + { + /*** + argv[2] - 表示算法类型 + argv[3] - 表示申请队列设备 + argv[4] - 表示申请队列的预留内存大小 + ***/ + //申请单个队列,并给队列预留内存 + snprintf(algorithm_type, sizeof(algorithm_type), "%s", argv[2]); + snprintf(dev, sizeof(dev), "%s", argv[3]); + memory_size = strtoul(argv[4], NULL, 10); + ret = hpre_dev_queue_req(dev, algorithm_type, memory_size); + if(0 != ret) + { + return 1; + } + } + else if(!strcmp(argv[1], "mult-queue")) + { + /*** + argv[2] - 表示算法类型 + argv[3] - 表示申请队列设 + argv[4] - 表示队列数量 + ***/ + //申请多个队列 + snprintf(algorithm_type, sizeof(algorithm_type), "%s", argv[2]); + snprintf(dev, sizeof(dev), "%s", argv[3]); + queue_num = strtoul(argv[4], NULL, 10); + ret = application_release_multiple_queue(dev, algorithm_type, queue_num); + if(0 != ret) + { + return 1; + } + } + else if(!strcmp(argv[1], "queue-share")) + { + /*** + argv[2] - 表示算法类型 + argv[3] - 表示申请队列设备 + argv[4] - 表示共享预留内存的设备 + argv[5] - 表示申请队列的预留内存大小 + ***/ + //申请单个队列,预留内存,与其它队列共享预留内存 + snprintf(algorithm_type, sizeof(algorithm_type), "%s", argv[2]); + snprintf(dev, sizeof(dev), "%s", argv[3]); + snprintf(share_dev, sizeof(share_dev), "%s", argv[4]); + memory_size = strtoul(argv[5], NULL, 10); + + ret = hpre_dev_queue_share(dev, share_dev, algorithm_type, memory_size); + if(0 != ret) + { + return 1; + } + } + else if(!strcmp(argv[1], "node-queue-share")) + { + /*** + argv[2] - 表示算法类型 + argv[3] - 表示申请队列设备 + argv[4] - 表示设备node + argv[5] - 表示共享内存设备node + argv[6] - 表示申请队列的预留内存大小 + ***/ + //申请单个队列,预留内存,与其它队列共享预留内存 + snprintf(algorithm_type, sizeof(algorithm_type), "%s", argv[2]); + snprintf(dev, sizeof(dev), "%s", argv[3]); + unsigned int node=0; + node = strtoul(argv[4], NULL, 16); + unsigned int share_node=0; + share_node = strtoul(argv[5], NULL, 16); + memory_size = strtoul(argv[6], NULL, 10); + + ret = hpre_node_queue_share(dev, node, share_node, algorithm_type, memory_size); + if(0 != ret) + { + return 1; + } + } + else if(!strcmp(argv[1], "queue-interact-share")) + { + /*** + argv[2] - 表示算法类型 + argv[3] - 表示申请队列设备 + argv[4] - 表示共享预留内存的设备 + argv[5] - 表示申请队列的预留内存大小 + ***/ + //队列预留内存后作为共享的目标队列 + snprintf(algorithm_type, sizeof(algorithm_type), "%s", argv[2]); + snprintf(dev, sizeof(dev), "%s", argv[3]); + snprintf(share_dev, sizeof(share_dev), "%s", argv[4]); + memory_size = strtoul(argv[5], NULL, 10); + + ret = hpre_dev_queue_interact_share(dev, share_dev, algorithm_type, memory_size); + if(0 != ret) + { + return 1; + } + } + else if(!strcmp(argv[1], "queue-cross-proc-share")) + { + /*** + argv[2] - 表示算法类型 + argv[3] - 表示申请队列设备 + argv[4] - 表示申请队列的预留内存大小 + ***/ + //跨进程进行队列共享 + snprintf(algorithm_type, sizeof(algorithm_type), "%s", argv[2]); + snprintf(dev, sizeof(dev), "%s", argv[3]); + memory_size = strtoul(argv[4], NULL, 10); + ret = hpre_dev_queue_cross_proc_share(dev, algorithm_type, memory_size); + if(0 != ret) + { + return 1; + } + } + else if(!strcmp(argv[1], "mult-thread-queue")) + { + /*** + argv[2] - 表示算法类型 + argv[3] - 表示申请队列设备 + argv[4] - 线程数 + argv[5] - 线程睡眠时间 + ***/ + //多线程申请多队列 + snprintf(algorithm_type, sizeof(algorithm_type), "%s", argv[2]); + snprintf(dev, sizeof(dev), "%s", argv[3]); + pthread_num = strtoul(argv[4], NULL, 10); + p_time = strtoul(argv[5], NULL, 10); + + ret = hpre_mult_thread_request_queue(dev, algorithm_type, pthread_num, p_time); + if(0 != ret) + { + return 1; + } + } + else if(!strcmp(argv[1], "hpre-blk")) + { + /*** + argv[2] - 表示申请队列的设备 + argv[3] - 块内存大小 + argv[4] - 块内存个数 + argv[5] - 块内存对齐 + ***/ + + //申请队列->创建内存池->申请内存块->映射内存块->释放内存块->注销内存池->释放队列 + snprintf(dev, sizeof(dev), "%s", argv[2]); + blk_size = strtoul(argv[3], NULL, 10); + blk_num = strtoul(argv[4], NULL, 10); + align_size = strtoul(argv[5], NULL, 10); + + ret = hpre_blkpool_operating(dev, blk_size, blk_num, align_size); + if(0 != ret) + { + return 1; + } + } + else if(!strcmp(argv[1], "hpre-blk-alloc")) + { + /*** + argv[2] - 表示申请队列的设备 + ***/ + //申请队列->创建内存池->申请内存块->再次申请内存块 + snprintf(dev, sizeof(dev), "%s", argv[2]); + + ret = hpre_blkpool_alloc(dev); + if(0 != ret) + { + return 1; + } + } + else if(!strcmp(argv[1], "hpre-blk-free")) + { + /*** + argv[2] - 表示申请队列的设备 + ***/ + //申请队列->创建内存池->申请内存块->释放内存块->再次释放内存块 + snprintf(dev, sizeof(dev), "%s", argv[2]); + + ret = hpre_blkpool_free(dev); + if(0 != ret) + { + return 1; + } + } + else if(!strcmp(argv[1], "hpre-blk-des")) + { + /*** + argv[2] - 表示申请队列的设备 + ***/ + //内存块未被释放,检查是否可以注销内存池 + snprintf(dev, sizeof(dev), "%s", argv[2]); + + ret = hpre_blkpool_des(dev); + if(0 != ret) + { + return 1; + } + } + else if(!strcmp(argv[1], "hpre-blk-thread")) + { + /*** + argv[2] - 表示申请队列的设备 + argv[3] - 内存块大小 + argv[4] - 内存块个数 + argv[5] - 内存对齐 + ***/ + //创建内存池,多线程申请块内存并释放块内存 + snprintf(dev, sizeof(dev), "%s", argv[2]); + blk_size = strtoul(argv[3], NULL, 10); + blk_num = strtoul(argv[4], NULL, 10); + align_size = strtoul(argv[5], NULL, 10); + + ret = hpre_blkpool_thread(dev, blk_size, blk_num, align_size); + if(0 != ret) + { + return 1; + } + } + else if(!strcmp(argv[1], "hpre-blk-create-des")) + { + /*** + argv[2] - 表示申请队列的设备 + argv[3] - 内存块大小 + argv[4] - 内存块个数 + argv[5] - 内存对齐 + ***/ + //重复创建内存池和释放内存池 + snprintf(dev, sizeof(dev), "%s", argv[2]); + blk_size = strtoul(argv[3], NULL, 10); + blk_num = strtoul(argv[4], NULL, 10); + align_size = strtoul(argv[5], NULL, 10); + + ret = hpre_blkpool_create_des(dev, blk_size, blk_num, align_size); + if(0 != ret) + { + return 1; + } + } + else if(!strcmp(argv[1], "hpre-blk-interface-fault")) + { + //接口容错测试 + ret = hpre_blkpool_interface_fault(); + if(0 != ret) + { + return 1; + } + } + else if(!strcmp(argv[1], "hpre-node-mask")) + { + /*** + argv[2] - dev + argv[3] - node + argv[4] - alg + blk_num = strtoul(argv[4], NULL, 10); + align_size = strtoul(argv[5], NULL, 10); + ***/ + snprintf(dev, sizeof(dev), "%s", argv[2]); + unsigned int node=0; + node = strtoul(argv[3], NULL, 10); + char alg[256]={0}; + snprintf(alg, sizeof(alg), "%s", argv[4]); + + ret = hpre_node_mask(dev, node, alg); + if(0 != ret) + { + return 1; + } + } + + else if(!strcmp(argv[1], "hpre-node-mask-thread")) + { + /*** + argv[2] - dev + argv[3] - node + argv[4] - alg + argv[5] - thread + blk_num = strtoul(argv[4], NULL, 10); + align_size = strtoul(argv[5], NULL, 10); + ***/ + snprintf(dev, sizeof(dev), "%s", argv[2]); + unsigned int node=0; + node = strtoul(argv[3], NULL, 10); + char alg[256]={0}; + snprintf(alg, sizeof(alg), "%s", argv[4]); + unsigned int NUM_Threads=0; + NUM_Threads = strtoul(argv[5], NULL, 10); + pthread_t Pthread[NUM_Threads]; + THDATA index[NUM_Threads]; + static int i; + static int cnt; + while(1){ + usleep(1); + for (i = 0; i < NUM_Threads; i++) + { + index[i].threadid = i; + index[i].dev = dev; + index[i].node = node; + index[i].alg = alg; + ret = pthread_create(&Pthread[i], NULL, hpre_node_mask_thread, (void *)&index[i]); + if (0 != ret) + { + printf("error: creating failed!\n"); + } + } + if(cnt > 63) + break; + cnt++; + + //pthread_join(&Pthread[i], NULL); + } + pthread_exit(NULL); + } + return 0; +} + diff --git a/uadk/v1/test/hisi_hpre_test/test_hisi_hpre.c b/uadk/v1/test/hisi_hpre_test/test_hisi_hpre.c new file mode 100644 index 0000000..d205f7a --- /dev/null +++ b/uadk/v1/test/hisi_hpre_test/test_hisi_hpre.c @@ -0,0 +1,10055 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +//#define DEBUG + +#include +#include +#include +#define __USE_GNU +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hpre_test_sample.h" +#include "test_hisi_hpre.h" +#include "../../wd.h" +#include "../../wd_ecc.h" +#include "../../wd_rsa.h" +#include "../../wd_dh.h" +#include "../../wd_bmm.h" +#include "../../wd_util.h" + +#define HPRE_TST_PRT printf +#define BN_ULONG unsigned long +#define RSA_NO_PADDING 3 +#define HPRE_TST_MAX_Q 1 +#define HPRE_PADDING_SZ 16 +#define TEST_MAX_THRD 128 +#define MAX_TRY_TIMES 10000 +#define LOG_INTVL_NUM 8 +#define WD_RSA_CTX_MSG_NUM 64 +#define WD_DH_CTX_MSG_NUM 64 +#define DH_GENERATOR_2 2 +#define DH_GENERATOR_5 5 +#define TEST_CNT 10 +#define EVP_PKEY_CTRL_MD 1 + +typedef unsigned int u32; + +pthread_mutex_t mute; + +struct big_number { + BN_ULONG *n; + int latest; + int size_d; + int flag_neg; + int flags; +}; + +typedef struct { + int nid; + const char *comment; +} EC_builtin_curve; + +/* stub structures */ +struct rsa_st { + int xxx; +}; + +struct dh_st { + int xxx; +}; + +struct bn_gencb_st { + int xxx; +}; + +struct test_hpre_pthread_dt { + int cpu_id; + enum alg_op_type op_type; + int thread_num; + void *pool; + void *q; + struct timeval start_tval; + u32 send_task_num; + u32 recv_task_num; +}; + +struct ec_key_st { + int xxx; +}; + +struct ec_point_st { + int xxx; +}; + +struct ec_group_st { + int xxx; +}; + +struct ec_method_st { + int xxx; +}; + +struct ec_sig_st { + int xxx; +}; + +struct evp_md_st { + int xxx; +}; + +struct evp_md_ctx_st { + int xxx; +}; + +struct bn_ctx_st { + int xxx; +}; + +typedef struct rand_meth_st { + int (*seed)(const void *buf, int num); + int (*bytes)(unsigned char *buf, int num); + void (*cleanup)(void); + int (*add)(const void *buf, int num, double entropy); + int (*pseudorand)(unsigned char *buf, int num); + int (*status)(void); +} RAND_METHOD; +/* stub definitions */ +typedef struct rsa_st RSA; +typedef struct dh_st DH; +typedef struct big_number BIGNUM; +typedef struct bn_gencb_st BN_GENCB; + +typedef struct ec_key_st EC_KEY; +typedef struct ec_point_st EC_POINT; +typedef struct ec_group_st EC_GROUP; +typedef struct ec_method_st EC_METHOD; +typedef struct ec_sig_st ECDSA_SIG; +typedef struct evp_md_st EVP_MD; +typedef struct evp_md_ctx_st EVP_MD_CTX; +typedef struct rand_meth_st RAND_METHOD; +typedef struct bn_ctx_st BN_CTX; + +enum dh_check_index { + DH_INVALID, + DH_ALICE_PUBKEY, + DH_BOB_PUBKEY, + DH_ALICE_PRIVKEY +}; + +struct rsa_async_tag { + void *ctx; + int thread_id; + int cnt; + struct test_hpre_pthread_dt *thread_info; +}; + +struct dh_user_tag_info { + u32 op; + int pid; + int thread_id; + void *test_ctx; + void *thread_data; +}; + +struct async_test_openssl_param { + RSA *rsa; + BIGNUM *p; + BIGNUM *q; + BIGNUM *e; + BIGNUM *n; + BIGNUM *d; + BIGNUM *dp; + BIGNUM *dq; + BIGNUM *qinv; + void *ssl_verify_result; + void *ssl_sign_result; + void *plantext; + int size; +}; + +struct ecc_curve_tbl { + const char *name; + unsigned int nid; + unsigned int curve_id; +}; + +enum ecc_rand_item { + RAND_NON, + RAND_CB, + RAND_PARAM +}; + +enum ecc_hash_item { + HASH_NON, + HASH_SM3, + HASH_SHA1, + HASH_SHA224, + HASH_SHA256, + HASH_SHA384, + HASH_SHA512, + HASH_MD4, + HASH_MD5 +}; + +enum ecc_msg_item { + MSG_DIGEST, + MSG_SHORT_PTEXT, + MSG_LONG_PTEXT +}; + +static int key_bits = 2048; +static int openssl_check; +static int only_soft; +static int performance_test = 1; +static int t_times = 10; +static int t_seconds = 0; +static int with_log; +static int is_system_test; +static int ctx_num_per_q = 1; +static int q_num = 1; +static char *g_mode = "-crt"; +static volatile int asyn_thread_exit = 0; +static char *ecc_curve_name = "secp256k1"; +static int set_msg = MSG_SHORT_PTEXT; +static int set_rand = RAND_CB; +static int set_hash = HASH_SM3; +static unsigned long int set_plaintext_len = 4096; +static unsigned int set_randparam_len = 256; +static __thread u32 g_is_set_prikey; // ecdh used +static __thread u32 g_is_set_pubkey; // ecc used +static pthread_t system_test_thrds[TEST_MAX_THRD]; +static struct test_hpre_pthread_dt test_thrds_data[TEST_MAX_THRD]; +static struct async_test_openssl_param ssl_params; + +static bool is_exit(struct test_hpre_pthread_dt *pdata); + +static char *rsa_op_str[WCRYPTO_RSA_GENKEY + 1] = { + "invalid_op", + "rsa_sign", + "rsa_verify", + "rsa_keygen", +}; + +static char *dh_op_str[WCRYPTO_DH_PHASE2] = { + "ph1", + "ph2" +}; + +static char *rsa_op_str_perf[WCRYPTO_RSA_GENKEY + 1] = { + "invalid_op", + "sign", + "verify", + "gen", +}; + +struct ecc_curve_tbl ecc_curve_tbls[] = { + {"secp128R1", 706, WCRYPTO_SECP128R1}, + {"secp192K1", 711, WCRYPTO_SECP192K1}, + {"secp256K1", 714, WCRYPTO_SECP256K1}, + {"brainpoolP320R1", 929, WCRYPTO_BRAINPOOLP320R1}, + {"brainpoolP384R1", 931, WCRYPTO_BRAINPOOLP384R1}, + {"secp521R1", 716, WCRYPTO_SECP521R1}, + {"null", 0, 0}, + +}; + +enum dh_test_item { + TEST_ITEM_INVALID, + SW_GENERATE_KEY, + SW_COMPUTE_KEY, + HW_GENERATE_KEY, + HW_COMPUTE_KEY, +}; + +struct hpre_dh_test_ctx_setup { + void *x; + void *p; + void *g; + void *except_pub_key; + void *cp_pub_key; + void *cp_share_key; + u32 x_size; + u32 p_size; + u32 g_size; + u32 cp_pub_key_size; + u32 cp_share_key_size; + u32 except_pub_key_size; + u32 op_type; + u32 generator; + u32 key_bits; + u32 key_from; //0 - Openssl 1 - Designed + void *pool; + void *q; + void *ctx; +}; + +struct hpre_dh_sw_opdata { + BIGNUM *except_pub_key; + unsigned char *pub_key; + u32 pub_key_size; + unsigned char *share_key; + u32 share_key_size; +}; + +struct hpre_dh_test_ctx { + void *priv; + void *opdata; + unsigned char *cp_share_key; + u32 cp_share_key_size; + unsigned char *cp_pub_key; + u32 cp_pub_key_size; + u32 op; + u32 key_size; + void *pool; +}; + +struct hpre_rsa_test_key_in { + void *e; + void *p; + void *q; + u32 e_size; + u32 p_size; + u32 q_size; + void *data[]; +}; + +#define X25519_KEYLEN 32 +#define X448_KEYLEN 56 +#define ED448_KEYLEN 57 +#define MAX_KEYLEN ED448_KEYLEN + +/* **************** x25519/x448 *******************/ +#define NID_X25519 1034 +#define NID_X448 1035 +# define EVP_PKEY_X25519 NID_X25519 +# define EVP_PKEY_X448 NID_X448 + +# define EVP_PKEY_SM2 1172 + + +typedef struct { + unsigned char pubkey[MAX_KEYLEN]; + unsigned char *privkey; +} ECX_KEY; + +struct evp_pkey_ctx_st; +typedef struct evp_pkey_ctx_st EVP_PKEY_CTX; + +struct evp_pkey_asn1_method_st { + int pkey_id; + int pkey_base_id; + unsigned long pkey_flags; +}; +typedef struct evp_pkey_asn1_method_st EVP_PKEY_ASN1_METHOD; + +struct engine_st { +}; + +typedef struct engine_st ENGINE; +//typedef _Atomic int CRYPTO_REF_COUNT; +typedef int CRYPTO_REF_COUNT; + +struct x_pkey_st { + int t; + int save_type; + CRYPTO_REF_COUNT count; + const EVP_PKEY_ASN1_METHOD *ameth; + ENGINE *e; + ENGINE *pmeth_e; + union { + void *ptr; + //struct ec_key_st *ec; /* for ECC */ + ECX_KEY *ecx; /* for X25519, X448 */ + } pkey; + int param; +}; + +typedef struct x_pkey_st EVP_PKEY; + +struct evp_pkey_method_st; +typedef struct evp_pkey_method_st EVP_PKEY_METHOD; + +struct evp_pkey_ctx_st { + /* Method associated with this operation */ + const EVP_PKEY_METHOD *pmeth; + /* Engine that implements this method or NULL if builtin */ + ENGINE *engine; + /* Key: may be NULL */ + EVP_PKEY *pkey; + /* Peer key for key agreement, may be NULL */ + EVP_PKEY *peerkey; + /* Actual operation */ + int operation; + /* Algorithm specific data */ + void *data; + /* Application specific data */ + void *app_data; + /* Keygen callback */ + //EVP_PKEY_gen_cb *pkey_gencb; + /* implementation specific keygen data */ + int *keygen_info; + int keygen_info_count; +} /* EVP_PKEY_CTX */ ; + +struct evp_pkey_method_st { + int pkey_id; + int flags; + int (*init) (EVP_PKEY_CTX *ctx); + int (*copy) (EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src); + void (*cleanup) (EVP_PKEY_CTX *ctx); + int (*paramgen_init) (EVP_PKEY_CTX *ctx); + int (*paramgen) (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey); + int (*keygen_init) (EVP_PKEY_CTX *ctx); + int (*keygen) (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey); + int (*sign_init) (EVP_PKEY_CTX *ctx); + int (*sign) (EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, + const unsigned char *tbs, size_t tbslen); + int (*verify_init) (EVP_PKEY_CTX *ctx); + int (*verify) (EVP_PKEY_CTX *ctx, + const unsigned char *sig, size_t siglen, + const unsigned char *tbs, size_t tbslen); + int (*verify_recover_init) (EVP_PKEY_CTX *ctx); + int (*verify_recover) (EVP_PKEY_CTX *ctx, + unsigned char *rout, size_t *routlen, + const unsigned char *sig, size_t siglen); + int (*signctx_init); // (EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx); + int (*signctx); /* (EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, + EVP_MD_CTX *mctx); */ + int (*verifyctx_init); // (EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx); + int (*verifyctx); /* (EVP_PKEY_CTX *ctx, const unsigned char *sig, int siglen, + EVP_MD_CTX *mctx); */ + int (*encrypt_init) (EVP_PKEY_CTX *ctx); + int (*encrypt) (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen); + int (*decrypt_init) (EVP_PKEY_CTX *ctx); + int (*decrypt) (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen); + int (*derive_init) (EVP_PKEY_CTX *ctx); + int (*derive) (EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen); + int (*ctrl) (EVP_PKEY_CTX *ctx, int type, int p1, void *p2); + int (*ctrl_str) (EVP_PKEY_CTX *ctx, const char *type, const char *value); + int (*digestsign); /*(EVP_MD_CTX *ctx, unsigned char *sig, size_t *siglen, + const unsigned char *tbs, size_t tbslen); */ + int (*digestverify); /* (EVP_MD_CTX *ctx, const unsigned char *sig, + size_t siglen, const unsigned char *tbs, + size_t tbslen); */ + int (*check) (EVP_PKEY *pkey); + int (*public_check) (EVP_PKEY *pkey); + int (*param_check) (EVP_PKEY *pkey); + + int (*digest_custom); // (EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx); +} /* EVP_PKEY_METHOD */ ; + +EVP_PKEY *EVP_PKEY_new(void); +EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type); + +int RAND_priv_bytes(unsigned char *buf, int num); +/* **************** x25519/x448 *******************/ + +/******************** ECC *********************/ +enum ecc_test_item { + ECC_TEST_ITEM_INVALID, + ECDH_SW_GENERATE, + ECDH_SW_COMPUTE, + ECDH_HW_GENERATE, + ECDH_HW_COMPUTE, + ECC_SW_SIGN, + ECC_SW_VERF, + ECC_HW_SIGN, + ECC_HW_VERF, + SM2_SW_SIGN, + SM2_SW_VERF, + SM2_HW_SIGN, + SM2_HW_VERF, + SM2_HW_ENC, + SM2_HW_DEC, + SM2_SW_ENC, + SM2_SW_DEC, + SM2_SW_KG, + SM2_HW_KG, + ECC_TEST_ITEM_MAX +}; + +struct ecc_test_ctx_setup { + void *d; // prikey + void *except_pub_key; // use in ecdh phase 2 + void *cp_pub_key; // use in ecdh phase 1 + void *cp_share_key; // use in ecdh phase 2 + void *digest; //ecdsa sign in + void *kinv; //ecdsa sign in + void *rp; //ecdsa sign in + void *sign; // ecdsa sign out or verf in + void *cp_sign; // use in ecdsa sign compare + void *priv_key; // use in ecdsa sign + void *pub_key; // use in ecdsa verf + void *plaintext; //sm2 + void *userid; //sm2 + void *cp_c; //sm2 ciphertext + u32 d_size; + u32 cp_pub_key_size; + u32 cp_share_key_size; + u32 except_pub_key_size; + u32 digest_size; + u32 kinv_size; + u32 rp_size; + u32 sign_size; + u32 cp_sign_size; + u32 priv_key_size; + u32 pub_key_size; + u32 plaintext_size; + u32 userid_size; + u32 cp_c_size; + u32 op_type; + u32 key_bits; + u32 key_from; //0 - Openssl 1 - Designed + u32 nid; //openssl ecc nid + u32 curve_id; // WD ecc curve_id + void *pool; + void *q; + void *ctx; +}; + +struct ecc_test_ctx { + void *priv; + void *priv1; // openssl key handle used in hpre sign and openssl verf + void *opdata; + unsigned char *cp_share_key; + u32 cp_share_key_size; + unsigned char *cp_pub_key; + u32 cp_pub_key_size; + u32 op; + u32 key_size; + void *pool; + /* ecdsa sign*/ +#define MAX_SIGN_LENS 200 + unsigned char cp_sign[MAX_SIGN_LENS]; + size_t cp_sign_size; +#define MAX_ENC_LENS 8192 + unsigned char cp_enc[MAX_ENC_LENS]; + size_t cp_enc_size; + /* ecdsa verf*/ + u32 cp_verf_result; + __u8 is_x25519_x448; + struct ecc_test_ctx_setup setup; +}; + +struct ecdh_sw_opdata { + EC_POINT *except_pub_key; + unsigned char *pub_key; + u32 pub_key_size; + unsigned char *share_key; + u32 share_key_size; + + /* ecdsa sign / verf */ + unsigned char *except_e; + u32 except_e_size; + BIGNUM *except_kinv; + BIGNUM *except_rp; + unsigned char *sign; // sign out or verf in + u32 sign_size; + +}; + +static char *ecc_op_str[ECC_TEST_ITEM_MAX] = { + "invalid_op", + "xdh sw gen", + "xdh sw compute", + "xdh hw gen", + "xdh hw compute", + "ecc sw sign", + "ecc sw verf", + "ecc hw sign", + "ecc hw verf", + "sm2 sw sign", + "sm2 sw verf", + "sm2 hw sign", + "sm2 hw verf", + "sm2 hw enc", + "sm2 hw dec", + "sm2 sw enc", + "sm2 sw dec", + "sm2 sw kg", + "sm2 hw kg", +}; + +static __thread struct hpre_rsa_test_key_in *rsa_key_in = NULL; + +void CRYPTO_free(void *ptr, const char *file, int line); + +# define OPENSSL_free(addr) CRYPTO_free(addr, __FILE__, __LINE__) + +/* OpenSSL RSA and BN APIs */ +BIGNUM *BN_new(void); +int BN_bn2bin(const BIGNUM *a, unsigned char *to); +BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret); +void BN_free(BIGNUM *a); +BIGNUM *BN_dup(const BIGNUM *a); +RSA *RSA_new(void); +void RSA_free(RSA *rsa); +int BN_set_word(BIGNUM *a, BN_ULONG w); +int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb); +void RSA_get0_key(const RSA *r, + const BIGNUM **n, const BIGNUM **e, const BIGNUM **d); +void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q); +void RSA_get0_crt_params(const RSA *r, + const BIGNUM **dmp1, const BIGNUM **dmq1, + const BIGNUM **iqmp); +int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, + BIGNUM *iqmp); +int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d); +int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q); +int RSA_public_encrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +int RSA_private_decrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +DH *DH_new(void); +void DH_free(DH *r); +int DH_generate_parameters_ex(DH *dh, int prime_len, int generator, + BN_GENCB *cb); +void DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, + const BIGNUM **g); +int DH_generate_key(DH *dh); +void DH_get0_key(const DH *dh, const BIGNUM **pub_key, + const BIGNUM **priv_key); +int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g); +int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key); +int DH_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh); +void *_hpre_sys_test_thread(void *data); + +EC_KEY *EC_KEY_new(void); +int EC_KEY_set_group(EC_KEY *key, EC_GROUP *group); +void EC_KEY_free(EC_KEY *key); +EC_KEY *EC_KEY_new_by_curve_name(int nid); +int EC_KEY_generate_key(EC_KEY *key); +int ERR_load_CRYPTO_strings(void); +int ERR_load_SSL_strings(void); +EC_GROUP *EC_GROUP_new_by_curve_name(int nid); +int ecdh_compute_key(void *test_ctx, void *tag); +int ECDH_compute_key(void *out, size_t outlen, EC_POINT *pub_key, + EC_KEY *ecdh, + void *(*KDF) (void *in, size_t inlen, + void *out, size_t *outlen)); +EC_POINT *EC_GROUP_get0_generator(EC_GROUP *group); +int DHparams_print_fp(FILE *fp, DH *x); +int EC_KEY_set_private_key(EC_KEY *key, BIGNUM *priv_key); +EC_POINT *EC_POINT_bn2point(EC_GROUP *, BIGNUM *, + EC_POINT *, void *); +EC_POINT *EC_POINT_dup(EC_POINT *a, EC_GROUP *group); +EC_POINT *EC_KEY_get0_public_key(EC_KEY *key); +BIGNUM *EC_KEY_get0_private_key(EC_KEY *key); +int ECParameters_print_fp(FILE *fp, EC_KEY *x); +int EC_KEY_print_fp(FILE *fp, EC_KEY *x, int off); +int RSA_print_fp(FILE *fp, RSA *x, int off); +void EC_POINT_free(EC_POINT *point); +void EC_GROUP_free(EC_GROUP *group); +size_t EC_POINT_point2buf(EC_GROUP *group, EC_POINT *point, + __u32 form, + char **pbuf, void *ctx); +int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, + const EC_POINT *p, + BIGNUM *x, + BIGNUM *y, + void *ctx); +int ECDSA_sign(int type, const unsigned char *dgst, int dgstlen, + unsigned char *sig, unsigned int *siglen, EC_KEY *eckey); +int ECDSA_verify(int type, const unsigned char *dgst, int dgstlen, + const unsigned char *sig, int siglen, EC_KEY *eckey); +int RAND_priv_bytes(unsigned char *buf, int num); +int ECDSA_sign_ex(int type, const unsigned char *dgst, int dgstlen, + unsigned char *sig, unsigned int *siglen, + const BIGNUM *kinv, const BIGNUM *rp, EC_KEY *eckey); +int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub); +int ECDSA_sign_setup(EC_KEY *eckey, void *ctx_in, BIGNUM **kinvp, + BIGNUM **rp); +int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s); +void ECDSA_SIG_free(ECDSA_SIG *sig); +ECDSA_SIG *ECDSA_SIG_new(void); +ECDSA_SIG *ECDSA_do_sign(const unsigned char *dgst, int dgst_len, + EC_KEY *eckey); +const BIGNUM *ECDSA_SIG_get0_r(const ECDSA_SIG *sig); +const BIGNUM *ECDSA_SIG_get0_s(const ECDSA_SIG *sig); +int ECDSA_do_verify(const unsigned char *dgst, int dgst_len, + const ECDSA_SIG *sig, EC_KEY *eckey); +int ECDSA_size(const EC_KEY *eckey); +const EVP_MD *EVP_sm3(void); +int EVP_MD_size(const EVP_MD *md); +int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type); +int EVP_DigestFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s); +int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *d, size_t cnt); +EVP_MD_CTX *EVP_MD_CTX_new(void); +EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx); +EC_POINT *EC_POINT_new(const EC_GROUP *group); +int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, + const BIGNUM *order, const BIGNUM *cofactor); +char *BN_bn2hex(const BIGNUM *a); +int EC_POINT_set_affine_coordinates(const EC_GROUP *group, EC_POINT *p, + const BIGNUM *x, const BIGNUM *y, + BN_CTX *ctx); +const RAND_METHOD *RAND_get_rand_method(void); +unsigned char *OPENSSL_hexstr2buf(const char *str, long *len); +char *OPENSSL_buf2hexstr(const unsigned char *buffer, long len); +void RAND_set_rand_method(const RAND_METHOD *meth); +ECDSA_SIG *sm2_do_sign(const EC_KEY *key, + const EVP_MD *digest, + const uint8_t *id, + const size_t id_len, + const uint8_t *msg, size_t msg_len); +EVP_PKEY *EVP_PKEY_new(void); +int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, struct ec_key_st *key); +int EVP_PKEY_set_alias_type(EVP_PKEY *pkey, int type); +EVP_MD_CTX *EVP_MD_CTX_new(void); +EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e); +void EVP_MD_CTX_set_pkey_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pctx); +int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype, + int cmd, int p1, void *p2); +int EVP_DigestSignInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, const EVP_MD *type, + ENGINE *e, EVP_PKEY *pkey); +int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, size_t *siglen); +int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *d, size_t cnt); +int EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx); +int EVP_PKEY_sign(EVP_PKEY_CTX *ctx, + unsigned char *sig, size_t *siglen, + const unsigned char *tbs, size_t tbslen); +int EVP_DigestSign(EVP_MD_CTX *ctx, unsigned char *sigret, + size_t *siglen, const unsigned char *tbs, + size_t tbslen); +void EVP_PKEY_free(EVP_PKEY *pkey); +void EVP_MD_CTX_free(EVP_MD_CTX *ctx); +void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx); +int BN_hex2bn(BIGNUM **a, const char *str); +EVP_PKEY_CTX *EVP_MD_CTX_pkey_ctx(const EVP_MD_CTX *ctx); +struct ec_key_st *EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey); +struct ec_key_st *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey); +void *EVP_PKEY_get0(EVP_PKEY *pkey); +EVP_PKEY *EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *ctx); +int EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret, + size_t siglen, const unsigned char *tbs, + size_t tbslen); +int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, + const EVP_MD *type, ENGINE *e, + EVP_PKEY *pkey); +int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig, + size_t siglen); +const EVP_MD *EVP_sm3(void); +const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key); +int EVP_PKEY_decrypt_init(EVP_PKEY_CTX *ctx); +int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx, + unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen); +int EVP_PKEY_encrypt_init(EVP_PKEY_CTX *ctx); +int EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx, + unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen); +int EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx); +int EVP_PKEY_verify(EVP_PKEY_CTX *ctx, + const unsigned char *sig, size_t siglen, + const unsigned char *tbs, size_t tbslen); + + +const EVP_MD *EVP_sha1(void); +const EVP_MD *EVP_sha224(void); +const EVP_MD *EVP_sha256(void); +const EVP_MD *EVP_sha384(void); +const EVP_MD *EVP_sha512(void); +const EVP_MD *EVP_sha512_224(void); +const EVP_MD *EVP_sha512_256(void); +const EVP_MD *EVP_sha3_224(void); +const EVP_MD *EVP_sha3_256(void); +const EVP_MD *EVP_sha3_384(void); +const EVP_MD *EVP_sha3_512(void); +const EVP_MD *EVP_shake128(void); +const EVP_MD *EVP_shake256(void); +const EVP_MD *EVP_md2(void); +const EVP_MD *EVP_md4(void); +const EVP_MD *EVP_md5(void); + +# define EVP_DigestSignUpdate(a,b,c) EVP_DigestUpdate(a,b,c) +# define EVP_DigestVerifyUpdate(a,b,c) EVP_DigestUpdate(a,b,c) + +#define EVP_PKEY_ALG_CTRL 0x1000 +# define EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID (EVP_PKEY_ALG_CTRL + 1) +# define EVP_PKEY_CTRL_EC_PARAM_ENC (EVP_PKEY_ALG_CTRL + 2) +# define EVP_PKEY_CTRL_EC_ECDH_COFACTOR (EVP_PKEY_ALG_CTRL + 3) +# define EVP_PKEY_CTRL_EC_KDF_TYPE (EVP_PKEY_ALG_CTRL + 4) +# define EVP_PKEY_CTRL_EC_KDF_MD (EVP_PKEY_ALG_CTRL + 5) +# define EVP_PKEY_CTRL_GET_EC_KDF_MD (EVP_PKEY_ALG_CTRL + 6) +# define EVP_PKEY_CTRL_EC_KDF_OUTLEN (EVP_PKEY_ALG_CTRL + 7) +# define EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN (EVP_PKEY_ALG_CTRL + 8) +# define EVP_PKEY_CTRL_EC_KDF_UKM (EVP_PKEY_ALG_CTRL + 9) +# define EVP_PKEY_CTRL_GET_EC_KDF_UKM (EVP_PKEY_ALG_CTRL + 10) +# define EVP_PKEY_CTRL_SET1_ID (EVP_PKEY_ALG_CTRL + 11) +# define EVP_PKEY_CTRL_GET1_ID (EVP_PKEY_ALG_CTRL + 12) +# define EVP_PKEY_CTRL_GET1_ID_LEN (EVP_PKEY_ALG_CTRL + 13) +# define EVP_PKEY_CTX_set1_id(ctx, id, id_len) \ + EVP_PKEY_CTX_ctrl(ctx, -1, -1, \ + EVP_PKEY_CTRL_SET1_ID, (int)id_len, (void*)(id)) + +static int sm2_sign_result_check(struct ecc_test_ctx *test_ctx, __u8 is_async); + +static RAND_METHOD fake_rand; +static const RAND_METHOD *saved_rand; +static uint8_t *fake_rand_bytes = NULL; +static size_t fake_rand_bytes_offset = 0; +static size_t fake_rand_size = 0; + +static int get_faked_bytes(unsigned char *buf, int num) +{ + int i; + + if (fake_rand_bytes == NULL) + return saved_rand->bytes(buf, num); + + //if (!TEST_size_t_le(fake_rand_bytes_offset + num, fake_rand_size)) + //return 0; + + for (i = 0; i != num; ++i) + buf[i] = fake_rand_bytes[fake_rand_bytes_offset + i]; + fake_rand_bytes_offset += num; + return 1; +} + +static int start_fake_rand(const char *hex_bytes) +{ + /* save old rand method */ + if (!(saved_rand = RAND_get_rand_method())) + return 0; + + fake_rand = *saved_rand; + /* use own random function */ + fake_rand.bytes = get_faked_bytes; + + fake_rand_bytes = OPENSSL_hexstr2buf(hex_bytes, NULL); + fake_rand_bytes_offset = 0; + fake_rand_size = strlen(hex_bytes) / 2; + + /* set new RAND_METHOD */ + RAND_set_rand_method(&fake_rand); + + return 1; +} + +static void print_data(void *ptr, int size, const char *name) +{ + __u32 i = 0; + __u8* p = ptr; + + printf("\n%s:start_addr=%p, size %d\n", name, ptr, size); + for (i = 1; i <= size; i++) { + printf("0x%02x ", p[i - 1]); + if (i % 16 == 0) + printf("\n"); + } + printf("\n"); +} + +static int crypto_bin_to_hpre_bin(char *dst, const char *src, + int b_size, int d_size) +{ + int i = d_size - 1; + char *buff = NULL; + char *src_tmp; + int j = 0; + + if (!dst || !src || b_size <= 0 || d_size <= 0) { + WD_ERR("crypto bin to hpre bin params err!\n"); + return -WD_EINVAL; + } + + if (b_size < d_size) { + WD_ERR("crypto bin to hpre bin param data is too long!\n"); + return -WD_EINVAL; + } + + if (b_size == d_size) + return WD_SUCCESS; + + if (dst == src) { + buff = malloc(d_size); + if (!buff) + return -WD_ENOMEM; + memcpy(buff, src, d_size); + src_tmp = buff; + } else { + src_tmp = (void *)src; + } + + for (j = b_size - 1; j >= 0; j--, i--) { + if (i >= 0) + dst[j] = src_tmp[i]; + else + dst[j] = 0; + } + + if (buff) + free(buff); + + return WD_SUCCESS; +} + +static __u32 get_ecc_min_blocksize(__u32 key_bits) +{ + __u32 size = 0; + + if (key_bits <= 256) + size = 32; + else if (key_bits <= 384) + size = 48; + else if (key_bits <= 576) + size = 72; + else + WD_ERR("get min block size key_bits %d err!\n", key_bits); + + return size; +} + +static __u32 get_hash_bytes(void) +{ + __u32 val = 0; + + switch (set_hash) { + case HASH_MD4: + case HASH_MD5: + val = BITS_TO_BYTES(128); + break; + case HASH_SHA1: + val = BITS_TO_BYTES(160); + break; + case HASH_SHA224: + val = BITS_TO_BYTES(224); + break; + case HASH_SHA256: + case HASH_SM3: + val = BITS_TO_BYTES(256); + break; + case HASH_SHA384: + val = BITS_TO_BYTES(384); + break; + case HASH_SHA512: + val = BITS_TO_BYTES(512); + break; + default: + break; + } + + return val; +} + +const EVP_MD *get_digest_handle(void) +{ + const EVP_MD *digest; + + if (set_hash == HASH_SHA1) + digest = EVP_sha1(); + else if (set_hash == HASH_SHA224) + digest = EVP_sha224(); + else if (set_hash == HASH_SHA256) + digest = EVP_sha256(); + else if (set_hash == HASH_SHA384) + digest = EVP_sha384(); + else if (set_hash == HASH_SHA512) + digest = EVP_sha512(); + else if (set_hash == HASH_MD4) + digest = EVP_md4(); + else if (set_hash == HASH_MD5) + digest = EVP_md5(); + else + digest = EVP_sm3(); + + return digest; +} + +static int hpre_compute_hash(const char *in, size_t in_len, + char *out, size_t out_len, void *usr) +{ + const EVP_MD *digest; + EVP_MD_CTX *hash = EVP_MD_CTX_new(); + int ret = 0; + + digest = get_digest_handle(); + if (EVP_DigestInit(hash, digest) == 0 + || EVP_DigestUpdate(hash, in, in_len) == 0 + || EVP_DigestFinal(hash, (void *)out, NULL) == 0) { + HPRE_TST_PRT("compute hash failed!\n"); + ret = -1; + } + + EVP_MD_CTX_free(hash); + + return ret; +} + +static __u8 is_async_test(__u32 opType) +{ + if (opType == ECDSA_SIGN || opType == ECDSA_VERF || + opType == SM2_SIGN || opType == SM2_VERF || + opType == SM2_ENC || opType == SM2_DEC || opType == SM2_KG || + opType == ECDH_GEN || opType == ECDH_COMPUTE || + opType == X25519_GEN || opType == X25519_COMPUTE || + opType == X448_GEN || opType == X448_COMPUTE) + return false; + + return true; +} + +static void evp_sign_to_hpre_bin(char *evp, size_t *evp_size, __u32 ksz) +{ + __u32 r_sz = evp[3]; + __u32 s_sz = evp[4 + r_sz + 1]; + char *r_data = evp + 4; + char *s_data = evp + 4 + r_sz + 2; + char tmp[MAX_SIGN_LENS] = {0}; + + if (r_sz >= ksz) { + memcpy(tmp, r_data + r_sz - ksz, ksz); + } else if (r_sz < ksz) { + memcpy(tmp + ksz - r_sz, r_data, r_sz); + } + + if (s_sz >= ksz) { + memcpy(tmp + ksz, s_data + s_sz - ksz, ksz); + } else if (s_sz < ksz) { + memcpy(tmp + ksz + ksz - s_sz, s_data, s_sz); + } + + memset(evp, 0, *evp_size); + memcpy(evp, tmp, 2 * ksz); + *evp_size = 2 * ksz; +} + +static int hpre_bin_sign_to_evp(char *evp, char *bin, __u32 ksz) +{ + char tmp[MAX_SIGN_LENS] = {0}; + char head[2] = {0x30, 0x44}; + char r_head[3] = {0x02, 0x20}; + char s_head[3] = {0x02, 0x20}; + __u8 head_bytes = 2; + __u8 r_head_bytes = 2; + __u8 s_head_bytes = 2; + __u32 total_len = 0x46; + __u8 r_size = ksz; + __u8 s_size = ksz; + __u8 val; + int i; + + + i = 0; + val = bin[i]; + while (!val && i++ < ksz - 1) { + val = bin[i]; + } + r_size -= i; + total_len -= i; + head[1] -= i; + r_head[1] -= i; + if (bin[i] & 0x80) { + r_head_bytes = 3; + total_len += 1; + head[1]++; + r_head[1]++; + } + + i = 0; + val = bin[ksz + i]; + while (!val && i++ < ksz - 1) { + val = bin[ksz + i]; + } + s_size -= i; + total_len -= i; + head[1] -= i; + s_head[1] -= i; + if (bin[ksz + i] & 0x80) { + s_head_bytes = 3; + total_len += 1; + head[1]++; + s_head[1]++; + } + + memcpy(tmp, head, head_bytes); + memcpy(tmp + head_bytes, r_head, r_head_bytes); + memcpy(tmp + head_bytes + r_head_bytes, bin + ksz - r_size, r_size); + memcpy(tmp + head_bytes + r_head_bytes + r_size, s_head, s_head_bytes); + memcpy(tmp + head_bytes + r_head_bytes + r_size + s_head_bytes, bin + 2 * ksz - s_size, s_size); + memcpy(evp, tmp, total_len); + + return total_len; +} + +static int sm2_enc_in_bin_to_evp(char *evp, char *bin, __u32 m_len, __u32 ksz, __u32 c3_sz) +{ + char *tmp; + char *c1 = bin; + char *c2 = bin + ksz * 2; + char *c3 = c2 + m_len; + __u32 total_len; + char head[4] = {0x30, 0x00}; + char c1x_head[3] = {0x02, 0x20}; + char c1y_head[3] = {0x02, 0x20, 0x00}; + char c3_head[3] = {0x04, 0x20}; + char c2_head[4] = {0x04, 0x00}; + __u8 head_bytes = 2; + __u8 c1x_head_bytes = 2; + __u8 c1y_head_bytes = 2; + __u8 c3_head_bytes = 2; + __u8 c2_head_bytes = 2; + __u8 c1x_size = ksz; + __u8 c1y_size = ksz; + __u8 c3_size = c3_sz; + __u8 val; + int i; + + tmp = malloc(MAX_ENC_LENS); + if (!tmp) { + HPRE_TST_PRT("%s: malloc fail\n", __func__); + return 0; + } + + if (m_len > 127) { + c2_head_bytes = 4; + c2_head[1] = 0x82; + c2_head[2] = m_len >> 8; + c2_head[3] = m_len & 0xff; + } else { + c2_head[1] = m_len; + } + + c3_head[1] = c3_sz; + total_len = 64 + c3_sz + head_bytes + c1x_head_bytes + c1y_head_bytes + + c3_head_bytes + c2_head_bytes + m_len; + + i = 0; + val = bin[i]; + while (!val && i++ < ksz - 1) { + val = bin[i]; + } + c1x_size -= i; + total_len -= i; + c1x_head[1] -= i; + if (bin[i] & 0x80) { + c1x_head_bytes = 3; + total_len += 1; + c1x_head[1]++; + } + + i = 0; + val = bin[i + ksz]; + while (!val && i++ < ksz - 1) { + val = bin[i + ksz]; + } + c1y_size -= i; + total_len -= i; + c1y_head[1] -= i; + if (bin[i + ksz] & 0x80) { + c1y_head_bytes = 3; + total_len += 1; + c1y_head[1]++; + } + + if (total_len >= 130) { + head_bytes = 4; + total_len += 2; + head[1] = 0x82; + head[2] = (total_len - 4) >> 8; + head[3] = (total_len - 4) & 0xff; + //c2_head[1] = 0x82; + //c2_head[2] = m_len >> 8; + //c2_head[3] = m_len & 0xff; + } else { + head[1] = (total_len - 2) & 0xff; + //c2_head[1] = m_len; + } + + memcpy(tmp, head, head_bytes); // head + memcpy(tmp + head_bytes, c1x_head, c1x_head_bytes); // c1 x head + memcpy(tmp + head_bytes + c1x_head_bytes, bin + ksz - c1x_size, c1x_size); // c1 x + memcpy(tmp + head_bytes + c1x_head_bytes + c1x_size, c1y_head, c1y_head_bytes); //c1 y head + memcpy(tmp + head_bytes + c1x_head_bytes + c1x_size + c1y_head_bytes, c1 + 2 * ksz - c1y_size, c1y_size); // c1 y + memcpy(tmp + head_bytes + c1x_head_bytes + c1x_size + c1y_head_bytes + c1y_size, c3_head, c3_head_bytes); //c3 head + memcpy(tmp + head_bytes + c1x_head_bytes + c1x_size + c1y_head_bytes + c1y_size + c3_head_bytes, c3, c3_size); //c3 head + memcpy(tmp + head_bytes + c1x_head_bytes + c1x_size + c1y_head_bytes + c1y_size + c3_head_bytes + c3_size, c2_head, c2_head_bytes); //c2 head + memcpy(tmp + head_bytes + c1x_head_bytes + c1x_size + c1y_head_bytes + c1y_size + c3_head_bytes + c3_size + c2_head_bytes, c2, m_len); //c2 + + memcpy(evp, tmp, total_len); + //print_data(evp, total_len, "evp"); + + free(tmp); + return total_len; +} + +__u32 get_big_endian_value(char *buf, __u32 size) +{ + __u32 ret = 0; + char tmp[4] = {0}; + + if (size == 1) { + ret = buf[0]; + } else if (size == 2) { + tmp[0] = buf[1]; + tmp[1] = buf[0]; + ret = *(unsigned short *)tmp; + } + + return ret; +} + +static int evp_to_wd_crypto(char *evp, size_t *evp_size, __u32 ksz, __u8 op_type) +{ + __u32 total_len = 0; + __u32 l_sz = 0; + __u8 *data; + __u32 d_sz = 0; + __u32 cur_len = 0; + __u32 out_len = 0; + __u32 i = 0; + char *buf; + char *buf_backup; + + buf = malloc(*evp_size + 64); /* may crypto bin len > evp_size */ + if (!buf) { + HPRE_TST_PRT("%s: malloc fail\n", __func__); + return -1; + } + memset(buf, 0, *evp_size); + buf_backup = buf; + + cur_len += 1; + if (evp[cur_len] & 0x80) { + l_sz = evp[cur_len] & 0x7f; + cur_len += 1; + } else { + l_sz = 1; + } + + if (l_sz == 1) + total_len = evp[cur_len]; + else if (l_sz == 2) + total_len = get_big_endian_value(&evp[cur_len], 2); + cur_len += l_sz; + + while (cur_len < *evp_size) { + if (evp[cur_len] == 0x2) { + cur_len += 1; + l_sz = 1; + } else if (evp[cur_len] == 0x4) { + cur_len += 1; + if (evp[cur_len] & 0x80) { + l_sz = evp[cur_len] & 0x7f; + cur_len += 1; + } else { + l_sz = 1; + } + } + + if (l_sz == 1) + d_sz = evp[cur_len]; + else if (l_sz == 2) + d_sz = get_big_endian_value(&evp[cur_len], 2); + cur_len += l_sz; + + data = (void *)&evp[cur_len]; + if (!data[0] && i < 2) { //c3 c2 no need + cur_len += 1; + d_sz -= 1; + } + + if (op_type == SM2_HW_ENC && cur_len + d_sz >= *evp_size) { + memcpy(buf, &evp[cur_len], d_sz); + buf += d_sz; + cur_len += d_sz; + out_len += d_sz; + } else if (op_type == SM2_HW_ENC && i == 2) { + memcpy(buf, &evp[cur_len], d_sz); + buf += d_sz; + cur_len += d_sz; + out_len += d_sz; + } else { + memcpy(buf + ksz - d_sz, &evp[cur_len], d_sz); + buf += ksz; + cur_len += ksz; + out_len += ksz; + } + //memcpy(buf, &evp[cur_len], d_sz); + + i++; + } + + memcpy(evp, buf_backup, out_len); + *evp_size = out_len; + free(buf_backup); + + return total_len; +} + +static int init_opdata_param(void *pool, + struct wcrypto_dh_op_data *opdata, + int key_size, enum dh_check_index step) +{ + unsigned char *ag_bin = NULL; + + memset(opdata, 0, sizeof(*opdata)); + if (step == DH_ALICE_PRIVKEY) { + ag_bin = wd_alloc_blk(pool); + if (!ag_bin) + return -ENOMEM; + memset(ag_bin, 0, 2 * key_size); + opdata->pv = ag_bin; + } + + opdata->x_p = wd_alloc_blk(pool); + if (!opdata->x_p) { + if (ag_bin) + wd_free_blk(pool, ag_bin); + return -ENOMEM; + } + memset(opdata->x_p, 0, 2 * key_size); + + opdata->pri = wd_alloc_blk(pool); + if (!opdata->pri) { + if (ag_bin) + wd_free_blk(pool, ag_bin); + wd_free_blk(pool, opdata->x_p); + return -ENOMEM; + } + memset(opdata->pri, 0, 2 * key_size); + + return 0; +} + + +void hpre_dh_del_test_ctx(struct hpre_dh_test_ctx *test_ctx) +{ + if (!test_ctx) + return; + + if (SW_GENERATE_KEY == test_ctx->op) { + DH_free(test_ctx->priv); + } else if (SW_COMPUTE_KEY == test_ctx->op) { + struct hpre_dh_sw_opdata *opdata = test_ctx->opdata; + + free(opdata->except_pub_key); + free(opdata->share_key); + free(opdata); + DH_free(test_ctx->priv); + } else if (HW_GENERATE_KEY == test_ctx->op) { + struct wcrypto_dh_op_data *opdata = test_ctx->opdata; + + wd_free_blk(test_ctx->pool, opdata->x_p); + wd_free_blk(test_ctx->pool, opdata->pri); + free(opdata); + free(test_ctx->cp_pub_key); + } else if (HW_COMPUTE_KEY == test_ctx->op) { + struct wcrypto_dh_op_data *opdata = test_ctx->opdata; + + wd_free_blk(test_ctx->pool, opdata->pv); + wd_free_blk(test_ctx->pool, opdata->x_p); + wd_free_blk(test_ctx->pool, opdata->pri); + free(opdata); + free(test_ctx->cp_share_key); + } else { + HPRE_TST_PRT("%s: no op %d\n", __func__, test_ctx->op); + } + + free(test_ctx); +} + +static struct hpre_dh_test_ctx *create_sw_gen_key_test_ctx(struct hpre_dh_test_ctx_setup setup) +{ + BIGNUM *p = NULL, *g = NULL, *x = NULL; + struct hpre_dh_test_ctx *test_ctx; + DH *dh = NULL; + + if (SW_GENERATE_KEY != setup.op_type) { + HPRE_TST_PRT("%s: err op type %d\n", __func__, setup.op_type); + return NULL; + } + + dh = DH_new(); + if (!dh) + return NULL; + + printf("dh %p\n", dh); + + test_ctx = malloc(sizeof(struct hpre_dh_test_ctx)); + if (!test_ctx) { + DH_free(dh); + return NULL; + } + + if (setup.key_from) { + p = BN_bin2bn(setup.p, setup.p_size, NULL); + g = BN_bin2bn(setup.g, setup.g_size, NULL); + x = BN_bin2bn(setup.x, setup.x_size, NULL); + DH_set0_pqg(dh, p, NULL, g); + DH_set0_key(dh, NULL, x); + } else { + if (!DH_generate_parameters_ex(dh, setup.key_bits, setup.generator, NULL)) { + HPRE_TST_PRT("DH_generate_parameters_ex fail!\n"); + DH_free(dh); + free(test_ctx); + return NULL; + } + } + + test_ctx->op = SW_GENERATE_KEY; + test_ctx->priv = dh; + test_ctx->key_size = setup.key_bits >> 3; + +//#ifdef DEBUG + DHparams_print_fp(stdout, dh); +//#endif + + return test_ctx; +} + +static struct hpre_dh_test_ctx *create_sw_compute_key_test_ctx(struct hpre_dh_test_ctx_setup setup) +{ + struct hpre_dh_sw_opdata *opdata; + struct hpre_dh_test_ctx *test_ctx; + DH *dh = NULL; + + if (!setup.except_pub_key || + !setup.except_pub_key_size || + setup.op_type !=SW_COMPUTE_KEY) { + HPRE_TST_PRT("%s: parm err!\n", __func__); + return NULL; + } + + dh = DH_new(); + if (!dh) + return NULL; + + opdata = malloc(sizeof(struct hpre_dh_sw_opdata)); + if (!opdata) { + DH_free(dh); + return NULL; + } + memset(opdata, 0, sizeof(struct hpre_dh_sw_opdata)); + + test_ctx = malloc(sizeof(struct hpre_dh_test_ctx)); + if (!test_ctx) { + DH_free(dh); + free(opdata); + return NULL; + } + memset(test_ctx, 0, sizeof(struct hpre_dh_test_ctx)); + + opdata->share_key = malloc(setup.key_bits >> 3); + if (!opdata->share_key) { + DH_free(dh); + free(opdata); + free(test_ctx); + return NULL; + } + + if (setup.key_from) { + BIGNUM *p = NULL, *g = NULL, *x = NULL; + p = BN_bin2bn(setup.p, setup.p_size, NULL); + g = BN_bin2bn(setup.g, setup.g_size, NULL); + x = BN_bin2bn(setup.x, setup.x_size, NULL); + DH_set0_pqg(dh, p, NULL, g); + DH_set0_key(dh, NULL, x); + + opdata->except_pub_key = BN_bin2bn(setup.except_pub_key, + setup.except_pub_key_size, NULL); + + } else { + opdata->except_pub_key = BN_bin2bn(setup.except_pub_key, + setup.except_pub_key_size, NULL); + + if (!DH_generate_parameters_ex(dh, setup.key_bits, setup.generator, NULL)) { + HPRE_TST_PRT("DH_generate_parameters_ex fail!\n"); + goto exit_free; + } + + if (!DH_generate_key(dh)) { + HPRE_TST_PRT("Alice DH_generate_key fail!\n"); + goto exit_free; + } + } +#ifdef DEBUG + //DHparams_print_fp(stdout, dh); +#endif + test_ctx->op = SW_COMPUTE_KEY; + test_ctx->priv = dh; + test_ctx->opdata = opdata; + test_ctx->key_size = setup.key_bits >> 3; + + return test_ctx; + +exit_free: + hpre_dh_del_test_ctx(test_ctx); + + return NULL; +} + +static struct hpre_dh_test_ctx *create_hw_gen_key_test_ctx(struct hpre_dh_test_ctx_setup setup) +{ + const BIGNUM *p = NULL, *g = NULL, *x = NULL; + const BIGNUM *pub_key = NULL; + struct wcrypto_dh_op_data *opdata; + struct hpre_dh_test_ctx *test_ctx; + struct wd_dtb ctx_g; + int ret; + u32 key_size = setup.key_bits >> 3; + DH *dh = NULL; + + if (!setup.q || !setup.pool || setup.op_type !=HW_GENERATE_KEY) { + HPRE_TST_PRT("%s: parm err!\n", __func__); + return NULL; + } + + opdata = malloc(sizeof(struct wcrypto_dh_op_data)); + if (!opdata) + return NULL; + memset(opdata, 0, sizeof(struct hpre_dh_sw_opdata)); + + dh = DH_new(); + if (!dh) { + free(opdata); + return NULL; + } + + test_ctx = malloc(sizeof(struct hpre_dh_test_ctx)); + if (!test_ctx) { + free(opdata); + DH_free(dh); + return NULL; + } + memset(test_ctx, 0, sizeof(struct hpre_dh_test_ctx)); + + ctx_g.data = malloc(key_size); + if (!ctx_g.data) { + free(test_ctx); + free(opdata); + DH_free(dh); + return NULL; + } + memset(ctx_g.data, 0, key_size); + + test_ctx->cp_pub_key = malloc(key_size); + if (!test_ctx->cp_pub_key) { + free(test_ctx); + free(opdata); + DH_free(dh); + free(ctx_g.data); + return NULL; + } + + ret = init_opdata_param(setup.pool, opdata, key_size, DH_ALICE_PUBKEY); + if (ret < 0) { + HPRE_TST_PRT("init_opdata_param failed\n"); + free(test_ctx); + free(opdata); + DH_free(dh); + free(ctx_g.data); + return NULL; + } + + if (setup.key_from) { + if (!setup.x || !setup.x_size || !setup.p || !setup.cp_pub_key || + !setup.p_size || !setup.g || !setup.g_size || !setup.cp_pub_key_size) { + HPRE_TST_PRT("%s: x/p/g parm err\n", __func__); + goto exit_free; + } + + memcpy(opdata->x_p, setup.x, setup.x_size); + memcpy(opdata->x_p + key_size, setup.p, setup.p_size); + memcpy(ctx_g.data, setup.g, setup.g_size); + memcpy(test_ctx->cp_pub_key, setup.cp_pub_key, setup.cp_pub_key_size); + opdata->pbytes = setup.p_size; + opdata->xbytes = setup.x_size; + ctx_g.dsize = setup.g_size; + ctx_g.bsize = key_size; + test_ctx->cp_pub_key_size = setup.cp_pub_key_size; + } else { + ret = DH_generate_parameters_ex(dh, setup.key_bits, setup.generator, NULL); + if (!ret) { + HPRE_TST_PRT("DH_generate_parameters_ex failed\n"); + goto exit_free; + } + + if (!DH_generate_key(dh)) { + HPRE_TST_PRT("DH_generate_key failed\n"); + goto exit_free; + } + + DH_get0_pqg(dh, &p, NULL, &g); + DH_get0_key(dh, &pub_key, &x); + + opdata->pbytes = BN_bn2bin(p, opdata->x_p + key_size); + opdata->xbytes = BN_bn2bin(x, opdata->x_p); + ctx_g.dsize = BN_bn2bin(g, (unsigned char*)ctx_g.data); + ctx_g.bsize = key_size; + test_ctx->cp_pub_key_size = BN_bn2bin(pub_key, test_ctx->cp_pub_key); + } + +#ifdef DEBUG + print_data(ctx_g.data, ctx_g.dsize, "g"); + print_data(opdata->x_p, opdata->xbytes, "x"); + print_data(opdata->x_p + key_size, opdata->pbytes, "p"); + print_data(test_ctx->cp_pub_key, test_ctx->cp_pub_key_size, "cp_pub_key"); +#endif + + opdata->op_type = WCRYPTO_DH_PHASE1; + test_ctx->opdata = opdata; + test_ctx->pool = setup.pool; + test_ctx->op = setup.op_type; + test_ctx->priv = setup.ctx; //init ctx + test_ctx->key_size = key_size; + + ret = wcrypto_set_dh_g(test_ctx->priv, &ctx_g); + if (ret) { + HPRE_TST_PRT("wcrypto_set_dh_g failed\n"); + goto exit_free; + } + + + DH_free(dh); + free(ctx_g.data); + + return test_ctx; +exit_free: + DH_free(dh); + free(ctx_g.data); + hpre_dh_del_test_ctx(test_ctx); + + return NULL; +} + +static struct hpre_dh_test_ctx *create_hw_compute_key_test_ctx(struct hpre_dh_test_ctx_setup setup) +{ + const BIGNUM *p = NULL, *g = NULL, *x = NULL; + struct wcrypto_dh_op_data *opdata; + struct hpre_dh_test_ctx *test_ctx; + int ret; + u32 key_size = setup.key_bits >> 3; + DH *dh = NULL; + DH *b = NULL; + + if (!setup.q || !setup.pool || setup.op_type !=HW_COMPUTE_KEY) { + HPRE_TST_PRT("%s: parm err!\n", __func__); + return NULL; + } + + opdata = malloc(sizeof(struct wcrypto_dh_op_data)); + if (!opdata) + return NULL; + memset(opdata, 0, sizeof(struct wcrypto_dh_op_data)); + + dh = DH_new(); + if (!dh) { + free(opdata); + return NULL; + } + + test_ctx = malloc(sizeof(struct hpre_dh_test_ctx)); + if (!test_ctx) { + free(opdata); + DH_free(dh); + return NULL; + } + memset(test_ctx, 0, sizeof(struct hpre_dh_test_ctx)); + + test_ctx->cp_share_key = malloc(key_size); + if (!test_ctx->cp_share_key) { + free(test_ctx); + free(opdata); + DH_free(dh); + return NULL; + } + + ret = init_opdata_param(setup.pool, opdata, key_size, DH_ALICE_PRIVKEY); + if (ret < 0) { + HPRE_TST_PRT("init_opdata_param failed\n"); + free(test_ctx); + free(opdata); + DH_free(dh); + return NULL; + } + + if (setup.key_from) { + memcpy(opdata->x_p, setup.x, setup.x_size); + memcpy(opdata->x_p + key_size, setup.p, setup.p_size); + memcpy(opdata->pv, setup.except_pub_key, setup.except_pub_key_size); + memcpy(test_ctx->cp_share_key, setup.cp_share_key, setup.cp_share_key_size); + opdata->pbytes = setup.p_size; + opdata->xbytes = setup.x_size; + opdata->pvbytes = setup.except_pub_key_size; + test_ctx->cp_share_key_size = setup.cp_share_key_size; + } else { + const BIGNUM *bp = NULL, *bg = NULL, + *bpub_key = NULL, *bpriv_key = NULL; + b = DH_new(); + + ret = DH_generate_parameters_ex(dh, setup.key_bits, setup.generator, NULL); + if (!ret) { + HPRE_TST_PRT("DH_generate_parameters_ex fail!\n"); + goto exit_free; + } + + if (!DH_generate_key(dh)) { + HPRE_TST_PRT("Alice DH_generate_key fail!\n"); + goto exit_free; + } + + DH_get0_pqg(dh, &p, NULL, &g); + DH_get0_key(dh, NULL, &x); + bp = BN_dup(p); + bg = BN_dup(g); + DH_set0_pqg(b, (BIGNUM *)bp, NULL, (BIGNUM *)bg); + if (!DH_generate_key(b)) { + HPRE_TST_PRT("a DH_generate_key fail!\n"); + ret = -1; + goto exit_free; + } + DH_get0_key(b, &bpub_key, &bpriv_key); + + test_ctx->cp_share_key_size = DH_compute_key(test_ctx->cp_share_key, bpub_key, dh); + if (!test_ctx->cp_share_key_size || test_ctx->cp_share_key_size == -1) { + HPRE_TST_PRT("DH_compute_key fail!\n"); + goto exit_free; + } + + opdata->pbytes = BN_bn2bin(p, opdata->x_p + key_size); + opdata->xbytes = BN_bn2bin(x, opdata->x_p); + opdata->pvbytes = setup.except_pub_key_size; + opdata->pvbytes = BN_bn2bin(bpub_key, opdata->pv); + } + + opdata->op_type = WCRYPTO_DH_PHASE2; + test_ctx->priv = setup.ctx; //init ctx + test_ctx->opdata = opdata; + test_ctx->pool = setup.pool; + test_ctx->op = setup.op_type; + test_ctx->key_size = key_size; + +#ifdef DEBUG + print_data(opdata->pv, opdata->pvbytes, "pv"); + print_data(opdata->x_p, opdata->xbytes, "x"); + print_data(opdata->x_p + key_size, opdata->pbytes, "p"); + print_data(test_ctx->cp_share_key, test_ctx->cp_share_key_size, "cp_share_key"); +#endif + + DH_free(dh); + if (b) + DH_free(b); + + return test_ctx; +exit_free: + DH_free(dh); + if (b) + DH_free(b); + hpre_dh_del_test_ctx(test_ctx); + + return NULL; +} + + +struct hpre_dh_test_ctx *hpre_dh_create_test_ctx(struct hpre_dh_test_ctx_setup setup) +{ + struct hpre_dh_test_ctx *test_ctx = NULL; + + switch (setup.op_type) { + case SW_GENERATE_KEY: + { + test_ctx = create_sw_gen_key_test_ctx(setup); + } + break; + case HW_GENERATE_KEY: + { + test_ctx = create_hw_gen_key_test_ctx(setup); + } + break; + case SW_COMPUTE_KEY: + { + test_ctx = create_sw_compute_key_test_ctx(setup); + } + break; + case HW_COMPUTE_KEY: + { + test_ctx = create_hw_compute_key_test_ctx(setup); + } + break; + default: + break; + } + + return test_ctx; +} + +int dh_generate_key(void *test_ctx, void *tag) +{ + struct hpre_dh_test_ctx *t_c = test_ctx; + int ret = 0; + + if (t_c->op == SW_GENERATE_KEY) { + DH *dh = t_c->priv; + + if (!DH_generate_key(dh)) { + HPRE_TST_PRT("DH_generate_key fail!\n"); + return -1; + } + +#ifdef DEBUG + //DHparams_print_fp(stdout, dh); +#endif + + } else { + struct wcrypto_dh_op_data *opdata = t_c->opdata; + void* ctx = t_c->priv; +try_again: + ret = wcrypto_do_dh(ctx, opdata, tag); + if (ret == -WD_EBUSY) { + usleep(100); + goto try_again; + } else if (ret) { + HPRE_TST_PRT("wcrypto_do_dh fail!\n"); + return -1; + } + } + + return 0; +} + +int dh_compute_key(void *test_ctx, void *tag) +{ + struct hpre_dh_test_ctx *t_c = test_ctx; + int ret = 0; + + if (t_c->op == SW_COMPUTE_KEY) { + struct hpre_dh_sw_opdata *opdata = t_c->opdata; + DH *dh = t_c->priv; + + ret = DH_compute_key(opdata->share_key, opdata->except_pub_key, dh); + if (ret <= 0) { + HPRE_TST_PRT("DH_compute_key fail!\n"); + return -1; + } + opdata->share_key_size = ret; + +#ifdef DEBUG + //DHparams_print_fp(stdout, dh); + //print_data(opdata->share_key, ret, "openssl share key"); + +#endif + } else { + struct wcrypto_dh_op_data *opdata = t_c->opdata; + void* ctx = t_c->priv; +try_again: + + ret = wcrypto_do_dh(ctx, opdata, tag); + if (ret == -WD_EBUSY) { + usleep(100); + goto try_again; + } else if (ret) { + HPRE_TST_PRT("wcrypto_do_dh fail!\n"); + return -1; + } +#ifdef DEBUG + //print_data(opdata->pri, opdata->pri_bytes,"hpre share key"); +#endif + } + + return 0; +} + + +static bool is_exit(struct test_hpre_pthread_dt *pdata) +{ + struct timeval cur_tval; + float time_used; + + gettimeofday(&cur_tval, NULL); + time_used = (float)((cur_tval.tv_sec -pdata->start_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - pdata->start_tval.tv_usec); + + if (t_seconds) + return time_used >= t_seconds * 1000000; + else if (t_times) + return pdata->send_task_num >= t_times; + + return false; +} + +static int dh_result_check(struct hpre_dh_test_ctx *test_ctx) +{ + struct wcrypto_dh_op_data *opdata = test_ctx->opdata; + unsigned char *cp_key; + u32 cp_size; + + if (test_ctx->op == HW_GENERATE_KEY) { + cp_key = test_ctx->cp_pub_key; + cp_size = test_ctx->cp_pub_key_size; + + } else { + cp_key = test_ctx->cp_share_key; + cp_size = test_ctx->cp_share_key_size; + } + + if (opdata->pri_bytes != cp_size || memcmp(cp_key, opdata->pri, cp_size)) { + HPRE_TST_PRT("dh op %d mismatch!\n", test_ctx->op); + +#ifdef DEBUG + print_data(opdata->pri, opdata->pri_bytes, "hpre out"); + print_data(cp_key, cp_size, "openssl out"); +#endif + + return -1; + } + + return 0; + +} + +static bool is_allow_print(int cnt, enum alg_op_type opType, int thread_num) +{ + int intval_index = 0; + unsigned int log_intval_adjust = 0; + int log_intval[LOG_INTVL_NUM] = {0x1, 0xff, 0x3ff, 0x7ff, 0xfff, 0x1fff}; + + if (!with_log) + return false; + + if (only_soft) + return true; + + switch (opType) { + case RSA_ASYNC_GEN: + case RSA_ASYNC_EN: + case RSA_ASYNC_DE: + case DH_ASYNC_COMPUTE: + case DH_ASYNC_GEN: + case RSA_KEY_GEN: + { + intval_index = 0x04; + } + break; + case ECDH_ASYNC_COMPUTE: + case ECDH_ASYNC_GEN: + case ECDSA_ASYNC_SIGN: + case ECDSA_ASYNC_VERF: + case ECDH_COMPUTE: + case ECDH_GEN: + { + intval_index = 0x01; + } + break; + case DH_COMPUTE: + case DH_GEN: + { + intval_index = 0x00; + } + break; + default: + { + intval_index = 0x01; + } + break; + } + + if (!thread_num) + return false; + log_intval_adjust = log_intval[intval_index] * ((thread_num - 1) / 16 + 1); + + if (!(cnt % log_intval_adjust)) + return true; + else + return false; +} + +static void _dh_perf_cb(const void *message, void *tag) +{ + //const struct wcrypto_dh_msg *msg = message; + struct dh_user_tag_info* pTag = (struct dh_user_tag_info*)tag; + struct test_hpre_pthread_dt *thread_data = pTag->thread_data; + + thread_data->recv_task_num++; + hpre_dh_del_test_ctx(pTag->test_ctx); + free(pTag); +} + +static void _dh_cb(const void *message, void *tag) +{ + const struct wcrypto_dh_msg *msg = message; + struct dh_user_tag_info* pSwData = (struct dh_user_tag_info*)tag; + struct timeval start_tval, end_tval; + int pid, threadId; + float time, speed; + int ret; + static int failTimes = 0; + struct hpre_dh_test_ctx *test_ctx = pSwData->test_ctx; + struct wcrypto_dh_op_data *opdata = test_ctx->opdata; + struct test_hpre_pthread_dt *thread_data = pSwData->thread_data; + + start_tval = thread_data->start_tval; + pid = pSwData->pid; + threadId = pSwData->thread_id; + + if (opdata->status != WD_SUCCESS) { + HPRE_TST_PRT("Proc-%d, %d-TD dh %dtimes fail!, status 0x%02x\n", + pid, threadId, thread_data->send_task_num, opdata->status); + goto err; + } + + if (openssl_check) { + opdata->pri_bytes = msg->out_bytes; + ret = dh_result_check(test_ctx); + if (ret) { + failTimes++; + HPRE_TST_PRT("TD-%d:dh %d result mismatching!\n", + threadId, test_ctx->op); + } + } + + gettimeofday(&end_tval, NULL); + if (is_allow_print(thread_data->send_task_num, DH_ASYNC_GEN, 1)) { + time = (end_tval.tv_sec - start_tval.tv_sec) * 1000000 + + (end_tval.tv_usec - start_tval.tv_usec); + speed = 1 / (time / thread_data->send_task_num) * 1000 * 1000; + HPRE_TST_PRT("Proc-%d, %d-TD dh %dtimes,%f us, %0.3fps, fail %dtimes(all TD)\n", + pid, threadId, thread_data->send_task_num, time, speed, failTimes); + } + +err: + if (is_allow_print(thread_data->send_task_num, DH_ASYNC_GEN, 1)) + HPRE_TST_PRT("thread %d do DH %dth time success!\n", threadId, thread_data->send_task_num); + hpre_dh_del_test_ctx(test_ctx); + if (pSwData) + free(pSwData); +} + + +int dh_init_test_ctx_setup(struct hpre_dh_test_ctx_setup *setup) +{ + if (!setup) + return -1; + + if (!strcmp(g_mode, "-g2")) + setup->generator = DH_GENERATOR_2; + else + setup->generator = DH_GENERATOR_5; + + if (performance_test) + setup->key_from = 1; //0 - Openssl 1 - Designed + else + setup->key_from = 0; //0 - Openssl 1 - Designed + + setup->key_bits = key_bits; + + if (key_bits == 768) { + setup->x = dh_xa_768; + setup->p = dh_p_768; + setup->except_pub_key = dh_except_b_pubkey_768; + setup->cp_pub_key = dh_except_a_pubkey_768; + setup->cp_share_key = dh_share_key_768; + setup->x_size = sizeof(dh_xa_768); + setup->p_size = sizeof(dh_p_768); + setup->except_pub_key_size = sizeof(dh_except_b_pubkey_768); + setup->cp_pub_key_size = sizeof(dh_except_a_pubkey_768); + setup->cp_share_key_size = sizeof(dh_share_key_768); + } else if (key_bits == 1024) { + setup->x = dh_xa_1024; + setup->p = dh_p_1024; + setup->except_pub_key = dh_except_b_pubkey_1024; + setup->cp_pub_key = dh_except_a_pubkey_1024; + setup->cp_share_key = dh_share_key_1024; + setup->x_size = sizeof(dh_xa_1024); + setup->p_size = sizeof(dh_p_1024); + setup->except_pub_key_size = sizeof(dh_except_b_pubkey_1024); + setup->cp_pub_key_size = sizeof(dh_except_a_pubkey_1024); + setup->cp_share_key_size = sizeof(dh_share_key_1024); + } else if (key_bits == 1536) { + setup->x = dh_xa_1536; + setup->p = dh_p_1536; + setup->except_pub_key = dh_except_b_pubkey_1536; + setup->cp_pub_key = dh_except_a_pubkey_1536; + setup->cp_share_key = dh_share_key_1536; + setup->x_size = sizeof(dh_xa_1536); + setup->p_size = sizeof(dh_p_1536); + setup->except_pub_key_size = sizeof(dh_except_b_pubkey_1536); + setup->cp_pub_key_size = sizeof(dh_except_a_pubkey_1536); + setup->cp_share_key_size = sizeof(dh_share_key_1536); + } else if (key_bits == 2048) { + setup->x = dh_xa_2048; + setup->p = dh_p_2048; + setup->except_pub_key = dh_except_b_pubkey_2048; + setup->cp_pub_key = dh_except_a_pubkey_2048; + setup->cp_share_key = dh_share_key_2048; + setup->x_size = sizeof(dh_xa_2048); + setup->p_size = sizeof(dh_p_2048); + setup->except_pub_key_size = sizeof(dh_except_b_pubkey_2048); + setup->cp_pub_key_size = sizeof(dh_except_a_pubkey_2048); + setup->cp_share_key_size = sizeof(dh_share_key_2048); + } else if (key_bits == 3072) { + setup->x = dh_xa_3072; + setup->p = dh_p_3072; + setup->except_pub_key = dh_except_b_pubkey_3072; + setup->cp_pub_key = dh_except_a_pubkey_3072; + setup->cp_share_key = dh_share_key_3072; + setup->x_size = sizeof(dh_xa_3072); + setup->p_size = sizeof(dh_p_3072); + setup->except_pub_key_size = sizeof(dh_except_b_pubkey_3072); + setup->cp_pub_key_size = sizeof(dh_except_a_pubkey_3072); + setup->cp_share_key_size = sizeof(dh_share_key_3072); + } else if (key_bits == 4096) { + setup->x = dh_xa_4096; + setup->p = dh_p_4096; + setup->except_pub_key = dh_except_b_pubkey_4096; + setup->cp_pub_key = dh_except_a_pubkey_4096; + setup->cp_share_key = dh_share_key_4096; + setup->x_size = sizeof(dh_xa_4096); + setup->p_size = sizeof(dh_p_4096); + setup->except_pub_key_size = sizeof(dh_except_b_pubkey_4096); + setup->cp_pub_key_size = sizeof(dh_except_a_pubkey_4096); + setup->cp_share_key_size = sizeof(dh_share_key_4096); + } else { + HPRE_TST_PRT("not find this keybits %d\n", key_bits); + return -1; + } + + if (!strcmp(g_mode, "-g2")) { + setup->g = dh_g_2; + } else { + setup->g = dh_g_5; + } + setup->g_size = 1; + + return 0; +} + +static void *_hpre_dh_sys_test_thread(void *data) +{ + struct test_hpre_pthread_dt *pdata = data; + struct dh_user_tag_info *pTag = NULL; + struct hpre_dh_test_ctx *test_ctx; + struct hpre_dh_test_ctx_setup setup; + struct timeval cur_tval; + enum alg_op_type opType; + float time_used, speed; + int thread_num; + cpu_set_t mask; + int pid = getpid(); + int thread_id = (int)syscall(__NR_gettid); + int ret, cpuid, opstr_idx = 0; + struct wd_queue *q = NULL; + void *pool = NULL; + void *ctx = NULL; + struct wcrypto_dh_ctx_setup dh_setup; + + CPU_ZERO(&mask); + cpuid = pdata->cpu_id; + q = (struct wd_queue *)pdata->q; + pool = pdata->pool; + opType = pdata->op_type; + thread_num = pdata->thread_num; + + if (performance_test && (!t_times && !t_seconds)) { + HPRE_TST_PRT("t_times or t_seconds err\n"); + return NULL; + } + + if (!q || !pool) { + HPRE_TST_PRT("q or pool null!\n"); + return NULL; + } + + CPU_SET(cpuid, &mask); + if (cpuid) { + ret = pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask); + if (ret < 0) { + HPRE_TST_PRT("Proc-%d, thrd-%d:set affinity fail!\n", + pid, thread_id); + return NULL; + } + HPRE_TST_PRT("Proc-%d, thrd-%d bind to cpu-%d!\n", + pid, thread_id, cpuid); + } + + if (!only_soft) { + memset(&dh_setup, 0, sizeof(dh_setup)); + dh_setup.key_bits = key_bits; + if (performance_test) + dh_setup.cb = _dh_perf_cb; + else + dh_setup.cb = _dh_cb; + dh_setup.br.alloc = (void *)wd_alloc_blk; + dh_setup.br.free = (void *)wd_free_blk; + dh_setup.br.iova_map = (void *)wd_blk_iova_map; + dh_setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + dh_setup.br.get_bufsize = (void *)wd_blksize; + dh_setup.br.usr = pool; + if (!strcmp(g_mode, "-g2")) + dh_setup.is_g2 = true; + else + dh_setup.is_g2 = false; + + ctx = wcrypto_create_dh_ctx(q, &dh_setup); + if (!ctx) { + HPRE_TST_PRT("wcrypto_create_dh_ctx failed\n"); + return NULL; + } + } + + if (dh_init_test_ctx_setup(&setup)) { + wcrypto_del_dh_ctx(ctx); + return NULL; + } + + setup.pool = pool; + setup.q = q; + setup.ctx = ctx; + + if (opType == DH_ASYNC_GEN || opType == DH_GEN) + setup.op_type = (only_soft) ? SW_GENERATE_KEY: HW_GENERATE_KEY; + else + setup.op_type = (only_soft) ? SW_COMPUTE_KEY: HW_COMPUTE_KEY; + +new_test_again: + test_ctx = hpre_dh_create_test_ctx(setup); + if (!test_ctx) { + HPRE_TST_PRT("hpre_dh_create_test_ctx failed\n"); + return NULL; + } + + do { + if (opType == DH_ASYNC_GEN || + opType == DH_ASYNC_COMPUTE) { + + pTag = malloc(sizeof(struct dh_user_tag_info)); + if (!pTag) { + HPRE_TST_PRT("malloc pTag fail!\n"); + goto fail_release; + } + + pTag->test_ctx = test_ctx; + pTag->thread_data = pdata; + pTag->pid = pid; + pTag->thread_id = thread_id; + } + + if (opType == DH_ASYNC_GEN || opType == DH_GEN) { + if (dh_generate_key(test_ctx, pTag)) { + goto fail_release; + } + opstr_idx = 0; + } else { + if (dh_compute_key(test_ctx, pTag)) { + goto fail_release; + } + opstr_idx = 1; + } + + pdata->send_task_num++; + if (opType == DH_GEN ||opType == DH_COMPUTE) { + if (!performance_test && !only_soft) { + if (dh_result_check(test_ctx)) + goto fail_release; + + if (is_allow_print(pdata->send_task_num, opType, thread_num)) { + HPRE_TST_PRT("Proc-%d, %d-TD dh %s succ!\n", + getpid(), (int)syscall(__NR_gettid), dh_op_str[opstr_idx]); + } + + hpre_dh_del_test_ctx(test_ctx); + goto new_test_again; + } + } else { + if (is_exit(pdata)) + break; + goto new_test_again; + } + + }while(!is_exit(pdata)); + + if (opType == DH_GEN || opType == DH_COMPUTE) + pdata->recv_task_num = pdata->send_task_num; + + if (performance_test) { + gettimeofday(&cur_tval, NULL); + time_used = (float)((cur_tval.tv_sec -pdata->start_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - pdata->start_tval.tv_usec); + + if (t_seconds){ + speed = pdata->send_task_num / time_used * 1000000; + HPRE_TST_PRT("Proc-%d, %d-TD: dh do %s send %u task, recv %u task, run %0.1f s at %0.3f ops\n", + pid, thread_id, dh_op_str[opstr_idx], + pdata->send_task_num, pdata->recv_task_num, + time_used / 1000000, speed); + } else if (t_times) { + speed = 1 / (time_used / t_times) * 1000; + HPRE_TST_PRT("\r\nPID(%d)-thread-%d:%s g2 mode %dbits kgen %s time %0.0f us, pkt len =" + " %d bytes, %0.3f Kops\n", getpid(), (int)syscall(__NR_gettid), "dh", + key_bits, dh_op_str[opstr_idx],time_used, key_bits / 8, speed); + } + } + + /* wait for recv finish */ + while (pdata->send_task_num != pdata->recv_task_num) + usleep(1000); + +fail_release: + if (opType == DH_ASYNC_GEN || + opType == DH_ASYNC_COMPUTE) { + return NULL; + } + if (test_ctx->op == HW_COMPUTE_KEY || test_ctx->op == HW_GENERATE_KEY) + wcrypto_del_dh_ctx(test_ctx->priv); + + if (opType == DH_GEN || opType == DH_COMPUTE) + hpre_dh_del_test_ctx(test_ctx); + + return NULL; +} + +static struct ecc_test_ctx *x_create_sw_gen_test_ctx(struct ecc_test_ctx_setup setup, u32 optype) +{ + struct ecc_test_ctx *test_ctx; + + test_ctx = malloc(sizeof(struct ecc_test_ctx)); + if (!test_ctx) { + printf("malloc failed.\n"); + return NULL; + } + + test_ctx->op = ECDH_SW_GENERATE; + test_ctx->key_size = setup.key_bits >> 3; + + return test_ctx; +} + +static struct ecc_test_ctx *ecc_create_sw_gen_test_ctx(struct ecc_test_ctx_setup setup, u32 optype) +{ + struct ecc_test_ctx *test_ctx; + EC_KEY *key = NULL; + EC_GROUP *group; + int ret; + + if (ECDH_SW_GENERATE != setup.op_type) { + HPRE_TST_PRT("%s: err op type %d\n", __func__, setup.op_type); + return NULL; + } + + key = EC_KEY_new(); + if (!key) { + printf("EC_KEY_new err!\n"); + return NULL; + } + + group = EC_GROUP_new_by_curve_name(setup.nid); + if(!group) { + printf("EC_GROUP_new_by_curve_name err!\n"); + goto free_ec_key; + } + + ret = EC_KEY_set_group(key, group); + if(ret != 1) { + printf("EC_KEY_set_group err.\n"); + goto free_ec_key; + } + + EC_GROUP_free(group); + + test_ctx = malloc(sizeof(struct ecc_test_ctx)); + if (!test_ctx) { + printf("malloc failed.\n"); + goto free_ec_key; + } + + if (setup.key_from) { + BIGNUM *privKey; + + privKey = BN_bin2bn(setup.d, setup.d_size, NULL); + ret = EC_KEY_set_private_key(key, privKey); + if (ret != 1) { + printf("EC_KEY_set_private_key failed\n"); + goto free_ctx; + } + } else {} + + test_ctx->op = ECDH_SW_GENERATE; + test_ctx->priv = key; + test_ctx->key_size = setup.key_bits >> 3; + +#ifdef DEBUG + ECParameters_print_fp(stdout, key); + EC_KEY_print_fp(stdout, key, 0); +#endif + + return test_ctx; + +free_ctx: + free(test_ctx); +free_ec_key: + EC_KEY_free(key); + return NULL; +} + +static struct ecc_test_ctx *x_create_sw_compute_test_ctx(struct ecc_test_ctx_setup setup, u32 optype) +{ + struct ecc_test_ctx *test_ctx; + + test_ctx = malloc(sizeof(struct ecc_test_ctx)); + if (!test_ctx) { + printf("malloc failed.\n"); + return NULL; + } + + test_ctx->op = ECDH_SW_COMPUTE; + test_ctx->key_size = setup.key_bits >> 3; + + return test_ctx; +} + +static struct ecc_test_ctx *ecc_create_sw_compute_test_ctx(struct ecc_test_ctx_setup setup, u32 optype) +{ + struct ecc_test_ctx *test_ctx; + struct ecdh_sw_opdata *opdata; + + EC_KEY *key_a = NULL; + EC_KEY *key_b = NULL; + EC_GROUP *group_a, *group_b; + BIGNUM *privKey, *pubKey; + EC_POINT *point_tmp, *ptr; + int ret; + + if (ECDH_SW_COMPUTE != setup.op_type) { + HPRE_TST_PRT("%s: err op type %d\n", __func__, setup.op_type); + return NULL; + } + + key_a = EC_KEY_new(); + if (!key_a) { + printf("EC_KEY_new err!\n"); + return NULL; + } + + group_a = EC_GROUP_new_by_curve_name(setup.nid); + if(!group_a) { + printf("EC_GROUP_new_by_curve_name err!\n"); + goto free_ec_key_a; + } + + ret = EC_KEY_set_group(key_a, group_a); + if(ret != 1) { + printf("EC_KEY_set_group err.\n"); + goto free_ec_key_a; + } + + test_ctx = malloc(sizeof(struct ecc_test_ctx)); + if (!test_ctx) { + printf("malloc failed.\n"); + goto free_ec_key_a; + } + + opdata = malloc(sizeof(struct ecdh_sw_opdata)); + if (!opdata) { + EC_KEY_free(key_a); + free(test_ctx); + goto free_ctx; + } + + memset(opdata, 0, sizeof(struct ecdh_sw_opdata)); + test_ctx->opdata = opdata; + + opdata->share_key = malloc((setup.key_bits >> 3) * 3); + if (!opdata->share_key) { + goto free_opdata; + } + opdata->share_key_size = (setup.key_bits >> 3) * 3; + + if (setup.key_from) { + point_tmp = EC_GROUP_get0_generator(group_a); + pubKey = BN_bin2bn(setup.except_pub_key, setup.except_pub_key_size, NULL); + ptr = EC_POINT_bn2point(group_a, pubKey, point_tmp, NULL); + if (!ptr) { + printf("EC_POINT_bn2point failed\n"); + BN_free(pubKey); + goto free_opdata; + } + BN_free(pubKey); + opdata->except_pub_key = point_tmp; + privKey = BN_bin2bn(setup.d, setup.d_size, NULL); + ret = EC_KEY_set_private_key(key_a, privKey); + if (ret != 1) { + printf("EC_KEY_set_private_key failed\n"); + goto free_opdata; + } + BN_free(privKey); + } else { + ret = EC_KEY_generate_key(key_a); + if(ret != 1) { + printf("EC_KEY_generate_key err.\n"); + goto free_share_key; + } + + key_b = EC_KEY_new(); + if (!key_b) { + printf("EC_KEY_new err!\n"); + goto free_share_key; + } + + group_b = EC_GROUP_new_by_curve_name(setup.nid); + if(!group_b) { + printf("EC_GROUP_new_by_curve_name err!\n"); + goto free_ec_key_b; + } + + ret = EC_KEY_set_group(key_b, group_b); + if(ret != 1) { + printf("EC_KEY_set_group err.\n"); + goto free_ec_key_b; + } + + ret = EC_KEY_generate_key(key_b); + if(ret != 1) { + printf("EC_KEY_generate_key err.\n"); + goto free_ec_key_b; + } + + opdata->except_pub_key = EC_POINT_dup(EC_KEY_get0_public_key(key_b), group_b); + if (!opdata->except_pub_key) { + printf("EC_KEY_get0_public_key err.\n"); + goto free_ec_key_b; + } + + EC_GROUP_free(group_b); +#ifdef DEBUG + printf("except_pub_key:\n"); + ECParameters_print_fp(stdout, key_b); + EC_KEY_print_fp(stdout, key_b, 0); +#endif + EC_KEY_free(key_b); + } + + EC_GROUP_free(group_a); + test_ctx->op = ECDH_SW_COMPUTE; + test_ctx->priv = key_a; + test_ctx->key_size = setup.key_bits >> 3; + +#ifdef DEBUG + ECParameters_print_fp(stdout, key_a); + EC_KEY_print_fp(stdout, key_a, 0); +#endif + return test_ctx; + +free_ec_key_b: + EC_KEY_free(key_b); +free_share_key: + free(opdata->share_key); +free_opdata: + free(test_ctx->opdata); +free_ctx: + free(test_ctx); +free_ec_key_a: + EC_KEY_free(key_a); + + return NULL; +} + +/* id = 1: x25519, 32byte, + * id = 2: x448, 56byte; */ +#define KEYLENID(id) (id == 1) ? 32 : 56 +int x_genkey_by_openssl(struct ecc_test_ctx *test_ctx, + struct wcrypto_ecc_key *ecc_key, + int key_size, int id) +{ + EVP_PKEY_METHOD *pmeth; + EVP_PKEY_CTX ctx; + struct wd_dtb d; + EVP_PKEY pkey; + int ret; + + memset(&pkey, 0, sizeof(EVP_PKEY)); + if (id == 1) { + pkey.save_type = EVP_PKEY_X25519; + pmeth = EVP_PKEY_meth_find(EVP_PKEY_X25519); + } else { //if (id == 2) + pkey.save_type = EVP_PKEY_X448; + pmeth = EVP_PKEY_meth_find(EVP_PKEY_X448); + } + ctx.pmeth = pmeth; + ret = pmeth->keygen(&ctx, &pkey); + if (ret <= 0) { + return -1; + } + + ECX_KEY *ecx = NULL; + ecx = (ECX_KEY *)(pkey.pkey.ptr); + char *data = calloc(key_size, sizeof(char)); + char data_pub[key_size]; + int i; + + memset(data_pub, 0, key_size); + for (i = 0; i < key_size; i++) { + data[i] = ecx->privkey[key_size - i -1]; + data_pub[i] = ecx->pubkey[key_size - i -1]; + } + d.data = data; + d.dsize = key_size; + d.bsize = key_size; + + ret = wcrypto_set_ecc_prikey(ecc_key, &d); + if (ret) { + HPRE_TST_PRT("%s: set prikey err\n", __func__); + return 0; + } + + memcpy(test_ctx->cp_pub_key, data_pub, key_size); + test_ctx->cp_pub_key_size = key_size; + + free(data); + return 1; +} + +static struct ecc_test_ctx *ecc_create_hw_gen_test_ctx(struct ecc_test_ctx_setup setup, u32 op_type) +{ + struct wcrypto_ecc_op_data *opdata; + struct ecc_test_ctx *test_ctx; + struct wcrypto_ecc_key *ecc_key; + struct wcrypto_ecc_out *ecc_out; + void *ctx = setup.ctx; + struct wd_dtb d; + int ret; + u32 key_size; + + if (!setup.q || !setup.pool) { + HPRE_TST_PRT("%s: parm err!\n", __func__); + return NULL; + } + + opdata = malloc(sizeof(struct wcrypto_ecc_op_data)); + if (!opdata) + return NULL; + memset(opdata, 0, sizeof(struct wcrypto_ecc_op_data)); + + test_ctx = malloc(sizeof(struct ecc_test_ctx)); + if (!test_ctx) { + HPRE_TST_PRT("%s: malloc fail!\n", __func__); + goto free_opdata; + } + memset(test_ctx, 0, sizeof(struct ecc_test_ctx)); + + key_size = (wcrypto_get_ecc_key_bits(ctx) + 7) / 8; + test_ctx->cp_pub_key = malloc(2 * key_size); + if (!test_ctx->cp_pub_key) { + HPRE_TST_PRT("%s: malloc fail!\n", __func__); + goto free_ctx; + } + + ecc_out = wcrypto_new_ecxdh_out(ctx); + if (!ecc_out) { + HPRE_TST_PRT("%s: new ecc out fail!\n", __func__); + goto free_cp_key; + } + + ecc_key = wcrypto_get_ecc_key(ctx); + + if (setup.key_from) { // performance || async ,the param is ready by curve + if (!setup.d || !setup.cp_pub_key || + !setup.cp_pub_key_size) { + HPRE_TST_PRT("%s: d parm err\n", __func__); + goto del_ecc_out; + } + + if ((!g_is_set_prikey && is_async_test(op_type)) || !is_async_test(op_type)) { + d.data = setup.d; + d.dsize = setup.d_size; + d.bsize = setup.d_size; + ret = wcrypto_set_ecc_prikey(ecc_key, &d); + if (ret) { + HPRE_TST_PRT("%s: set prikey err\n", __func__); + goto del_ecc_out; + } + g_is_set_prikey = true; + } + + if (op_type >= X25519_GEN && op_type <= X448_ASYNC_COMPUTE) { + memcpy(test_ctx->cp_pub_key, setup.cp_pub_key, key_size); + test_ctx->cp_pub_key_size = setup.cp_pub_key_size; + } else { + memcpy(test_ctx->cp_pub_key, setup.cp_pub_key + 1, key_size * 2); + test_ctx->cp_pub_key_size = setup.cp_pub_key_size - 1; + } + } else { // sync && not performance, the prikey/pubkey are from openssl + if (op_type == X25519_GEN ||op_type == X25519_COMPUTE) { // x25519 + ret = x_genkey_by_openssl(test_ctx, ecc_key, key_size, 1); + if (ret == 0) { + return NULL; + } + } else if (op_type == X448_GEN ||op_type == X448_COMPUTE) { // x448 + ret = x_genkey_by_openssl(test_ctx, ecc_key, key_size, 2); + if (ret == 0) { + return NULL; + } + } else { // ecdh + EC_KEY *key_a = NULL; + EC_GROUP *group_a; + EC_POINT *point; + BIGNUM *d; + struct wd_dtb dtb_d; + char *tmp; + size_t len; + + key_a = EC_KEY_new(); + if (!key_a) { + printf("EC_KEY_new err!\n"); + goto del_ecc_out; + } + + group_a = EC_GROUP_new_by_curve_name(setup.nid); + if(!group_a) { + printf("EC_GROUP_new_by_curve_name err!\n"); + EC_KEY_free(key_a); + goto del_ecc_out; + } + + ret = EC_KEY_set_group(key_a, group_a); + if(ret != 1) { + printf("EC_KEY_set_group err.\n"); + EC_KEY_free(key_a); + goto del_ecc_out; + } + + ret = EC_KEY_generate_key(key_a); + if(ret != 1) { + printf("EC_KEY_generate_key err.\n"); + ECParameters_print_fp(stdout, key_a); + EC_KEY_print_fp(stdout, key_a, 4); + EC_KEY_free(key_a); + goto del_ecc_out; + } + + d = EC_KEY_get0_private_key(key_a); + if (!d) { + printf("EC_KEY_get0_private_key err.\n"); + EC_KEY_free(key_a); + goto del_ecc_out; + } + + tmp = malloc(key_size); + if (!tmp) { + printf("malloc fail!\n"); + EC_KEY_free(key_a); + goto del_ecc_out; + } + + memset(tmp, 0, key_size); + dtb_d.dsize = BN_bn2bin(d, (void *)tmp); + dtb_d.bsize = key_size; + dtb_d.data = tmp; + ret = wcrypto_set_ecc_prikey(ecc_key, &dtb_d); + if (ret) { + HPRE_TST_PRT("%s: set prikey err\n", __func__); + EC_KEY_free(key_a); + free(tmp); + goto del_ecc_out; + } + free(tmp); + + point = EC_KEY_get0_public_key(key_a); + if (!point) { + printf("EC_KEY_get0_public_key err.\n"); + EC_KEY_free(key_a); + goto del_ecc_out; + } + len = EC_POINT_point2buf(group_a, point, 4, &tmp, NULL); + memcpy(test_ctx->cp_pub_key, tmp + 1, 2 * key_size); + test_ctx->cp_pub_key_size = len - 1; + + EC_GROUP_free(group_a); + OPENSSL_free(tmp); + EC_KEY_free(key_a); + } + } + +#ifdef DEBUG + //struct wd_dtb *p; + + //wcrypto_get_ecc_prikey_params(ecc_key, &p, NULL, NULL, NULL, NULL, NULL); + //print_data(p->data, ECC_PRIKEY_SZ(p->bsize), "prikey"); + //print_data(test_ctx->cp_pub_key, test_ctx->cp_pub_key_size, "cp_pub_key"); +#endif + + opdata->op_type = WCRYPTO_ECXDH_GEN_KEY; + opdata->out = ecc_out; + test_ctx->opdata = opdata; + test_ctx->pool = setup.pool; + test_ctx->op = setup.op_type; + test_ctx->priv = ctx; //init ctx + test_ctx->key_size = key_size; + + return test_ctx; + +del_ecc_out: + (void)wcrypto_del_ecc_out(ctx, ecc_out); +free_cp_key: + free(test_ctx->cp_pub_key); +free_ctx: + free(test_ctx); +free_opdata: + free(opdata); + + return NULL; +} + +/* return 1: ok; + * return 0: err; + */ +int x_compkey_by_openssl(struct ecc_test_ctx *test_ctx, void *ctx, + struct wcrypto_ecc_in **ecc_in, + struct wcrypto_ecc_key *ecc_key, + size_t key_size, int id) +{ + /* gen prikey && pubkey */ + EVP_PKEY_METHOD *pmeth; + EVP_PKEY_CTX pkey_ctx; + struct wd_dtb d; + EVP_PKEY pkey; + int ret; + + memset(&pkey_ctx, 0, sizeof(EVP_PKEY_CTX)); + memset(&pkey, 0, sizeof(EVP_PKEY)); + + if (id == 1) { + pkey.save_type = EVP_PKEY_X25519; + pmeth = EVP_PKEY_meth_find(EVP_PKEY_X25519); + } else { // if (id == 2) + pkey.save_type = EVP_PKEY_X448; + pmeth = EVP_PKEY_meth_find(EVP_PKEY_X448); + } + pkey_ctx.pmeth = pmeth; + ret = pmeth->keygen(&pkey_ctx, &pkey); + if (ret <= 0) { + return -1; + } + + ECX_KEY *ecx; + /* ecx->privkey is prikey, ecx->pubkey is pubkey */ + ecx = (ECX_KEY *)(pkey.pkey.ptr); + + int i; + + char *data = calloc(key_size, sizeof(char)); + + for (i = 0; i < key_size; i++) { + data[i] = ecx->privkey[key_size - i -1]; + } + d.data = data; + d.dsize = key_size; + d.bsize = key_size; + + /* set the prikey */ + ret = wcrypto_set_ecc_prikey(ecc_key, &d); + if (ret) { + HPRE_TST_PRT("%s: set prikey err\n", __func__); + return 0; + } + + /* set the pubkey(point_in) */ + struct wcrypto_ecc_point tmp; + + memset(data, 0, key_size); + for (i = 0; i pubkey[key_size - i -1]; + } + tmp.x.data = data; + tmp.x.dsize = key_size; + tmp.x.bsize = key_size; + tmp.y.data = tmp.x.data; // + key_size; + tmp.y.dsize = key_size; + tmp.y.bsize = key_size; + + *ecc_in = wcrypto_new_ecxdh_in(ctx, &tmp); + if (!*ecc_in) { + printf("%s, wcrypto_new_ecxdh_in err.\n", __func__); + return 0; + } + /* gen prikey && pubkey end */ + + /* compute the key start*/ + memset(&pkey_ctx, 0, sizeof(EVP_PKEY_CTX)); + pkey_ctx.pkey = &pkey; + pkey_ctx.peerkey = &pkey; + + /* out_shared_key: out shared key */ + uint8_t *out_shared_key = calloc(key_size, sizeof(char)); + + ret = pmeth->derive(&pkey_ctx, out_shared_key, &key_size); + if (ret == 0) { + HPRE_TST_PRT("%s: pmeth->derive err.\n", __func__); + return 0; + } + + char share_big[key_size]; + memset(share_big, 0, key_size); + for (i = 0; i cp_share_key, share_big, key_size); + test_ctx->cp_share_key_size = key_size; + + free(data); + return 1; +} + +static struct ecc_test_ctx *ecc_create_hw_compute_test_ctx(struct ecc_test_ctx_setup setup, u32 op_type) +{ + struct wcrypto_ecc_op_data *opdata; + struct ecc_test_ctx *test_ctx; + struct wcrypto_ecc_key *ecc_key; + struct wcrypto_ecc_in *ecc_in; + struct wcrypto_ecc_out *ecc_out; + struct wcrypto_ecc_point tmp; + void *ctx = setup.ctx; + struct wd_dtb d; + int ret; + u32 key_size; + size_t len; + + if (!setup.q || !setup.pool) { + HPRE_TST_PRT("%s: parm err!\n", __func__); + return NULL; + } + + opdata = malloc(sizeof(struct wcrypto_ecc_op_data)); + if (!opdata) + return NULL; + memset(opdata, 0, sizeof(struct wcrypto_ecc_op_data)); + + test_ctx = malloc(sizeof(struct ecc_test_ctx)); + if (!test_ctx) { + HPRE_TST_PRT("%s: malloc fail!\n", __func__); + goto free_opdata; + } + memset(test_ctx, 0, sizeof(struct ecc_test_ctx)); + + key_size = (wcrypto_get_ecc_key_bits(setup.ctx) + 7) / 8; + test_ctx->cp_share_key = malloc(key_size * 4); + if (!test_ctx->cp_share_key) { + HPRE_TST_PRT("%s: malloc fail!\n", __func__); + goto free_ctx; + } + + ecc_out = wcrypto_new_ecxdh_out(ctx); + if (!ecc_out) { + goto free_cp_key; + } + + ecc_key = wcrypto_get_ecc_key(ctx); + if (setup.key_from) { + if (op_type == X25519_GEN || op_type == X25519_COMPUTE || + op_type == X448_GEN || op_type == X448_COMPUTE || + op_type == X25519_ASYNC_GEN || op_type == X25519_ASYNC_COMPUTE || + op_type == X448_ASYNC_GEN || op_type == X448_ASYNC_COMPUTE) { + tmp.x.data = setup.except_pub_key; + } else { + tmp.x.data = setup.except_pub_key + 1; // step 0x04 + } + tmp.x.bsize = key_size; + tmp.x.dsize = key_size; + tmp.y.data = tmp.x.data + key_size; + tmp.y.bsize = key_size; + tmp.y.dsize = key_size; + ecc_in = wcrypto_new_ecxdh_in(ctx, &tmp); + if (!ecc_in) { + goto del_ecc_out; + } + + if ((!g_is_set_prikey && is_async_test(op_type)) || !is_async_test(op_type)) { + d.data = setup.d; + d.dsize = setup.d_size; + d.bsize = setup.d_size; + ret = wcrypto_set_ecc_prikey(ecc_key, &d); + if (ret) { + HPRE_TST_PRT("%s: set prikey err\n", __func__); + goto del_ecc_in; + } + g_is_set_prikey = true; + } + + memcpy(test_ctx->cp_share_key, setup.cp_share_key, setup.cp_share_key_size); + test_ctx->cp_share_key_size = setup.cp_share_key_size; + } else { + if (op_type == X25519_GEN ||op_type == X25519_COMPUTE) { // x25519 + ret = x_compkey_by_openssl(test_ctx, ctx, &ecc_in, ecc_key, key_size, 1); + if (ret == 0) { + return NULL; + } + } else if (op_type == X448_GEN ||op_type == X448_COMPUTE) { // x448 + ret = x_compkey_by_openssl(test_ctx, ctx, &ecc_in, ecc_key, key_size, 2); + if (ret == 0) { + return NULL; + } + } else { // ecdh + EC_KEY *key_a = NULL; + EC_GROUP *group_a; + EC_POINT *point; + BIGNUM *d; + struct wd_dtb dtb_d; + char *buff; + + key_a = EC_KEY_new(); + if (!key_a) { + printf("EC_KEY_new err!\n"); + goto del_ecc_out; + } + + group_a = EC_GROUP_new_by_curve_name(setup.nid); + if(!group_a) { + printf("EC_GROUP_new_by_curve_name err!\n"); + EC_KEY_free(key_a); + goto del_ecc_out; + } + + ret = EC_KEY_set_group(key_a, group_a); + if(ret != 1) { + printf("EC_KEY_set_group err.\n"); + EC_KEY_free(key_a); + goto del_ecc_out; + } + + ret = EC_KEY_generate_key(key_a); + if(ret != 1) { + printf("EC_KEY_generate_key err.\n"); + ECParameters_print_fp(stdout, key_a); + EC_KEY_print_fp(stdout, key_a, 4); + EC_KEY_free(key_a); + goto del_ecc_out; + } + + d = EC_KEY_get0_private_key(key_a); + if (!d) { + printf("EC_KEY_get0_private_key err.\n"); + EC_KEY_free(key_a); + goto del_ecc_out; + } + + buff = malloc(key_size); + if (!buff) { + printf("malloc fail!\n"); + EC_KEY_free(key_a); + goto del_ecc_out; + } + + dtb_d.dsize = BN_bn2bin(d, (void *)buff); + dtb_d.bsize = key_size; + dtb_d.data = buff; + ret = wcrypto_set_ecc_prikey(ecc_key, &dtb_d); + if (ret) { + HPRE_TST_PRT("%s: set prikey err\n", __func__); + EC_KEY_free(key_a); + free(buff); + goto del_ecc_out; + } + free(buff); + + point = EC_KEY_get0_public_key(key_a); + if (!point) { + printf("EC_KEY_get0_public_key err.\n"); + EC_KEY_free(key_a); + goto del_ecc_out; + } + + len = EC_POINT_point2buf(group_a, point, 4, &buff, NULL); + if (len != 2 * key_size + 1) { + printf("EC_POINT_point2buf err.\n"); + } + + EC_GROUP_free(group_a); + + tmp.x.data = buff + 1; + tmp.x.dsize = key_size; + tmp.x.bsize = key_size; + tmp.y.data = tmp.x.data + key_size; + tmp.y.dsize = key_size; + tmp.y.bsize = key_size; + ecc_in = wcrypto_new_ecxdh_in(ctx, &tmp); + if (!ecc_in) { + printf("wcrypto_new_ecxdh_in err.\n"); + EC_KEY_free(key_a); + free(buff); + goto del_ecc_out; + } + + #ifdef DEBUG + //print_data(buff + 1, len - 1, "except_pub_key"); + #endif + free(buff); + + ret = ECDH_compute_key(test_ctx->cp_share_key, key_size * 4, + point, key_a, NULL); + if (ret <= 0) { + printf("ECDH_compute_key err.\n"); + EC_KEY_free(key_a); + goto del_ecc_out; + } + + test_ctx->cp_share_key_size = ret; + EC_KEY_free(key_a); + } + } + +#ifdef DEBUG + //struct wd_dtb *p; + + //wcrypto_get_ecc_prikey_params(ecc_key, &p, NULL, NULL, NULL, NULL, NULL); + //print_data(p->data, ECC_PRIKEY_SZ(p->bsize), "prikey"); + //print_data(test_ctx->cp_share_key, test_ctx->cp_share_key_size, "cp_share_key"); +#endif + + opdata->op_type = WCRYPTO_ECXDH_COMPUTE_KEY; + opdata->in = ecc_in; + opdata->out = ecc_out; + test_ctx->opdata = opdata; + test_ctx->pool = setup.pool; + test_ctx->op = setup.op_type; + test_ctx->priv = setup.ctx; //init ctx + test_ctx->key_size = key_size; + + return test_ctx; + +del_ecc_in: + (void)wcrypto_del_ecc_in(ctx, ecc_in); +del_ecc_out: + (void)wcrypto_del_ecc_out(ctx, ecc_out); +free_cp_key: + free(test_ctx->cp_pub_key); +free_ctx: + free(test_ctx); +free_opdata: + free(opdata); + + return NULL; +} + +/* for x25519/x448, to be added*/ +int x_dh_init_test_ctx_setup(struct ecc_test_ctx_setup *setup, __u32 op_type) +{ + if (!setup) + return -1; + if (performance_test || is_async_test(op_type)) + setup->key_from = 1; //0 - Openssl 1 - Designed + else + setup->key_from = 0; //0 - Openssl 1 - Designed + + setup->key_bits = key_bits; + + if (!setup->key_from) + return 0; + + if (op_type == X25519_GEN || op_type == X25519_COMPUTE || + op_type == X25519_ASYNC_GEN || op_type == X25519_ASYNC_COMPUTE) { + setup->d = x25519_aprikey_big; + setup->except_pub_key = x25519_bpubkey_big; + setup->cp_pub_key = x25519_apubke_big; + setup->cp_share_key = x25519_absharekey_big; + setup->d_size = 32; + setup->except_pub_key_size = 32; + setup->cp_pub_key_size = 32; + setup->cp_share_key_size = 32; + } else if (op_type == X448_GEN || op_type == X448_COMPUTE || + op_type == X448_ASYNC_GEN || op_type == X448_ASYNC_COMPUTE) { + setup->d = x448_aprikey_big; + setup->except_pub_key = x448_bpubkey_big; + setup->cp_pub_key = x448_apubkey_big; + setup->cp_share_key = x448_absharekey_big; + setup->d_size = 56; + setup->except_pub_key_size = 56; + setup->cp_pub_key_size = 56; + setup->cp_share_key_size = 56; + } else { + HPRE_TST_PRT("init x25519/x448 test ctx setup not find this bits %d\n", key_bits); + return -1; + } + + return 0; +} + +static struct ecc_test_ctx *ecc_create_sw_sign_test_ctx(struct ecc_test_ctx_setup setup, u32 optype) +{ + struct ecc_test_ctx *test_ctx; + struct ecdh_sw_opdata *opdata; + EC_KEY *key_a = NULL; + EC_GROUP *group_a; + BIGNUM *kinv, *privKey, *rp; + int size; + int ret; + + if (ECC_SW_SIGN != setup.op_type) { + HPRE_TST_PRT("%s: err op type %d\n", __func__, setup.op_type); + return NULL; + } + + key_a = EC_KEY_new(); + if (!key_a) { + printf("EC_KEY_new err!\n"); + return NULL; + } + + group_a = EC_GROUP_new_by_curve_name(setup.nid); + if(!group_a) { + printf("EC_GROUP_new_by_curve_name err!\n"); + goto free_ec_key_a; + } + + ret = EC_KEY_set_group(key_a, group_a); + if(ret != 1) { + printf("EC_KEY_set_group err.\n"); + goto free_ec_key_a; + } + EC_GROUP_free(group_a); + + test_ctx = malloc(sizeof(struct ecc_test_ctx)); + if (!test_ctx) { + printf("malloc failed.\n"); + goto free_ec_key_a; + } + + opdata = malloc(sizeof(struct ecdh_sw_opdata)); + if (!opdata) { + EC_KEY_free(key_a); + free(test_ctx); + goto free_ctx; + } + + memset(opdata, 0, sizeof(struct ecdh_sw_opdata)); + test_ctx->opdata = opdata; + size = ECDSA_size(key_a); + opdata->sign = malloc(size); + memset(opdata->sign, 0, size); + if (!opdata->sign) { + goto free_opdata; + } + + if (setup.key_from) { + opdata->except_e = setup.digest; + opdata->except_e_size = setup.digest_size; + kinv = BN_bin2bn(setup.kinv, setup.kinv_size, NULL); // kinv invalid, actual should 1/kinv + opdata->except_kinv = kinv; + rp = BN_bin2bn(setup.rp, setup.rp_size, NULL); + opdata->except_rp = rp; + privKey = BN_bin2bn(setup.d, setup.d_size, NULL); + ret = EC_KEY_set_private_key(key_a, privKey); + if (ret != 1) { + printf("EC_KEY_set_private_key failed\n"); + goto free_sign; + } + BN_free(privKey); + } else {} + + test_ctx->op = setup.op_type; + test_ctx->priv = key_a; + test_ctx->key_size = setup.key_bits >> 3; +#ifdef DEBUG + ECParameters_print_fp(stdout, key_a); + EC_KEY_print_fp(stdout, key_a, 0); +#endif + return test_ctx; + +free_sign: + free(opdata->sign); +free_opdata: + free(test_ctx->opdata); +free_ctx: + free(test_ctx); +free_ec_key_a: + EC_KEY_free(key_a); + + return NULL; +} + +static struct ecc_test_ctx *ecc_create_sw_verf_test_ctx(struct ecc_test_ctx_setup setup, u32 optype) +{ + struct ecc_test_ctx *test_ctx; + struct ecdh_sw_opdata *opdata; + EC_KEY *key_a = NULL; + EC_GROUP *group_a; + BIGNUM *pubkey; + EC_POINT *point_tmp, *ptr; + int ret; + + if (ECC_SW_VERF != setup.op_type) { + HPRE_TST_PRT("%s: err op type %d\n", __func__, setup.op_type); + return NULL; + } + + key_a = EC_KEY_new(); + if (!key_a) { + printf("EC_KEY_new err!\n"); + return NULL; + } + + group_a = EC_GROUP_new_by_curve_name(setup.nid); + if(!group_a) { + printf("EC_GROUP_new_by_curve_name err!\n"); + goto free_ec_key_a; + } + + ret = EC_KEY_set_group(key_a, group_a); + if(ret != 1) { + printf("EC_KEY_set_group err.\n"); + goto free_ec_key_a; + } + + test_ctx = malloc(sizeof(struct ecc_test_ctx)); + if (!test_ctx) { + printf("malloc failed.\n"); + goto free_ec_key_a; + } + + opdata = malloc(sizeof(struct ecdh_sw_opdata)); + if (!opdata) { + EC_KEY_free(key_a); + free(test_ctx); + goto free_ctx; + } + + memset(opdata, 0, sizeof(struct ecdh_sw_opdata)); + test_ctx->opdata = opdata; + + if (setup.key_from) { + opdata->except_e = setup.digest; + opdata->except_e_size = setup.digest_size; + opdata->sign = setup.sign; + opdata->sign_size = setup.sign_size; + + point_tmp = EC_GROUP_get0_generator(group_a); + pubkey = BN_bin2bn(setup.cp_pub_key, setup.cp_pub_key_size, NULL); + ptr = EC_POINT_bn2point(group_a, pubkey, point_tmp, NULL); + if (!ptr) { + printf("EC_POINT_bn2point failed\n"); + BN_free(pubkey); + goto free_opdata; + } + + ret = EC_KEY_set_public_key(key_a, point_tmp); + if (ret != 1) { + printf("EC_KEY_set_public_key failed\n"); + BN_free(pubkey); + goto free_opdata; + } + BN_free(pubkey); + } else {} + + EC_GROUP_free(group_a); + test_ctx->op = setup.op_type; + test_ctx->priv = key_a; + test_ctx->key_size = setup.key_bits >> 3; +#ifdef DEBUG + ECParameters_print_fp(stdout, key_a); + EC_KEY_print_fp(stdout, key_a, 0); +#endif + return test_ctx; + +free_opdata: + free(test_ctx->opdata); +free_ctx: + free(test_ctx); +free_ec_key_a: + EC_KEY_free(key_a); + + return NULL; +} + +static struct ecc_test_ctx *ecc_create_hw_sign_test_ctx(struct ecc_test_ctx_setup setup, u32 op_type) +{ + + struct wcrypto_ecc_op_data *opdata; + struct ecc_test_ctx *test_ctx; + struct wcrypto_ecc_key *ecc_key; + struct wcrypto_ecc_out *ecc_out; + struct wcrypto_ecc_in *ecc_in = NULL; + struct wcrypto_ecc_point pub; + EC_POINT *point_tmp, *ptr; + EC_KEY *key_a = NULL; + EC_GROUP *group_a; + BIGNUM *pubKey; + void *ctx = setup.ctx; + struct wd_dtb d, e, k; + int ret; + u32 key_size; + + if (!setup.q || !setup.pool) { + HPRE_TST_PRT("%s: parm err!\n", __func__); + return NULL; + } + + opdata = malloc(sizeof(struct wcrypto_ecc_op_data)); + if (!opdata) + return NULL; + memset(opdata, 0, sizeof(struct wcrypto_ecc_op_data)); + + test_ctx = malloc(sizeof(struct ecc_test_ctx)); + if (!test_ctx) { + HPRE_TST_PRT("%s: malloc fail!\n", __func__); + goto free_opdata; + } + memset(test_ctx, 0, sizeof(struct ecc_test_ctx)); + + key_size = (wcrypto_get_ecc_key_bits(ctx) + 7) / 8; + ecc_out = wcrypto_new_ecdsa_sign_out(ctx); + if (!ecc_out) { + HPRE_TST_PRT("%s: new ecc out fail!\n", __func__); + goto free_ctx; + } + ecc_key = wcrypto_get_ecc_key(ctx); + if (!g_is_set_prikey || !is_async_test(op_type)) { + d.data = setup.d; + d.dsize = setup.d_size; + d.bsize = setup.d_size; + ret = wcrypto_set_ecc_prikey(ecc_key, &d); + if (ret) { + HPRE_TST_PRT("%s: set prikey err\n", __func__); + goto del_ecc_out; + } + g_is_set_prikey = true; + } + + if (!g_is_set_pubkey || !is_async_test(op_type)) { + pub.x.data = setup.cp_pub_key + 1; + pub.x.dsize = key_size; + pub.x.bsize = key_size; + pub.y.data = pub.x.data + key_size; + pub.y.dsize = key_size; + pub.y.bsize = key_size; + ret = wcrypto_set_ecc_pubkey(ecc_key, &pub); + if (ret) { + HPRE_TST_PRT("%s: set pubkey err\n", __func__); + goto del_ecc_out; + } + g_is_set_pubkey = true; + } + + e.data = setup.digest; + e.dsize = setup.digest_size; + e.bsize = key_size; + + if (setup.key_from) { + k.data = setup.kinv; + k.dsize = setup.kinv_size; + k.bsize = key_size; + ecc_in = wcrypto_new_ecdsa_sign_in(ctx, &e, &k); + if (!ecc_in) { + HPRE_TST_PRT("%s: new ecc in fail!\n", __func__); + goto del_ecc_out; + } + } else { + key_a = EC_KEY_new(); + if (!key_a) { + printf("EC_KEY_new err!\n"); + goto del_ecc_out; + } + + group_a = EC_GROUP_new_by_curve_name(setup.nid); + if(!group_a) { + printf("EC_GROUP_new_by_curve_name err!\n"); + EC_KEY_free(key_a); + goto del_ecc_out; + } + + ret = EC_KEY_set_group(key_a, group_a); + if(ret != 1) { + printf("EC_KEY_set_group err.\n"); + EC_KEY_free(key_a); + EC_GROUP_free(group_a); + goto del_ecc_out; + } + + /* set pubkey */ + point_tmp = EC_GROUP_get0_generator(group_a); + pubKey = BN_bin2bn(setup.cp_pub_key, setup.cp_pub_key_size, NULL); + ptr = EC_POINT_bn2point(group_a, pubKey, point_tmp, NULL); + if (!ptr) { + printf("EC_POINT_bn2point failed\n"); + BN_free(pubKey); + EC_KEY_free(key_a); + EC_GROUP_free(group_a); + goto del_ecc_out; + } + + ret = EC_KEY_set_public_key(key_a, point_tmp); + if (ret != 1) { + printf("EC_KEY_set_public_key failed\n"); + BN_free(pubKey); + EC_KEY_free(key_a); + EC_GROUP_free(group_a); + goto del_ecc_out; + } + BN_free(pubKey); + EC_GROUP_free(group_a); + + ecc_in = wcrypto_new_ecdsa_sign_in(ctx, &e, NULL); + if (!ecc_in) { + HPRE_TST_PRT("%s: new ecc in fail!\n", __func__); + goto del_ecc_out; + } + } + +#ifdef DEBUG + //struct wd_dtb *p; + + //wcrypto_get_ecc_prikey_params(ecc_key, &p, NULL, NULL, NULL, NULL, NULL); + //print_data(p->data, ECC_PRIKEY_SZ(p->bsize), "prikey"); + //print_data(test_ctx->cp_pub_key, test_ctx->cp_pub_key_size, "cp_pub_key"); +#endif + + opdata->op_type = WCRYPTO_ECDSA_SIGN; + opdata->out = ecc_out; + opdata->in = ecc_in; + test_ctx->opdata = opdata; + test_ctx->pool = setup.pool; + test_ctx->op = setup.op_type; + test_ctx->priv = ctx; //init ctx + test_ctx->key_size = key_size; + test_ctx->priv1 = key_a; + + return test_ctx; + +del_ecc_out: + (void)wcrypto_del_ecc_out(ctx, ecc_out); +free_ctx: + free(test_ctx); +free_opdata: + free(opdata); + + return NULL; +} + +static struct ecc_test_ctx *ecc_create_hw_verf_test_ctx(struct ecc_test_ctx_setup setup, u32 op_type) +{ + struct wcrypto_ecc_op_data *opdata; + struct ecc_test_ctx *test_ctx; + struct wcrypto_ecc_key *ecc_key; + struct wcrypto_ecc_in *ecc_in; + EC_KEY *key_a = NULL; + EC_GROUP *group_a; + BIGNUM *privKey; + ECDSA_SIG *sig; + BIGNUM *b_r, *b_s; + unsigned char buf1[100]; + unsigned char buf2[100]; + void *ctx = setup.ctx; + struct wd_dtb e, r, s; + struct wcrypto_ecc_point pub; + int ret; + u32 key_size; + + if (!setup.q || !setup.pool) { + HPRE_TST_PRT("%s: parm err!\n", __func__); + return NULL; + } + + opdata = malloc(sizeof(struct wcrypto_ecc_op_data)); + if (!opdata) + return NULL; + memset(opdata, 0, sizeof(struct wcrypto_ecc_op_data)); + + test_ctx = malloc(sizeof(struct ecc_test_ctx)); + if (!test_ctx) { + HPRE_TST_PRT("%s: malloc fail!\n", __func__); + goto free_opdata; + } + memset(test_ctx, 0, sizeof(struct ecc_test_ctx)); + + key_size = (wcrypto_get_ecc_key_bits(ctx) + 7) / 8; + ecc_key = wcrypto_get_ecc_key(ctx); + if (!g_is_set_pubkey || !is_async_test(op_type)) { + pub.x.data = setup.cp_pub_key + 1; + pub.x.dsize = key_size; + pub.x.bsize = key_size; + pub.y.data = pub.x.data + key_size; + pub.y.dsize = key_size; + pub.y.bsize = key_size; + ret = wcrypto_set_ecc_pubkey(ecc_key, &pub); + if (ret) { + HPRE_TST_PRT("%s: set pubkey err\n", __func__); + goto free_ctx; + } + g_is_set_pubkey = true; + } + e.data = setup.digest; + e.dsize = setup.digest_size; + e.bsize = key_size; + + if (setup.key_from) { + r.data = setup.sign + 4; + r.dsize = key_size; + r.bsize = key_size; + s.data = r.data + key_size; + s.dsize = key_size; + s.bsize = key_size; + ecc_in = wcrypto_new_ecdsa_verf_in(ctx, &e, &r, &s); + if (!ecc_in) { + HPRE_TST_PRT("%s: new ecc in fail!\n", __func__); + goto free_ctx; + } + } else { + key_a = EC_KEY_new(); + if (!key_a) { + printf("EC_KEY_new err!\n"); + goto free_ctx; + } + + group_a = EC_GROUP_new_by_curve_name(setup.nid); + if(!group_a) { + printf("EC_GROUP_new_by_curve_name err!\n"); + EC_KEY_free(key_a); + goto free_ctx; + } + + ret = EC_KEY_set_group(key_a, group_a); + if(ret != 1) { + printf("EC_KEY_set_group err.\n"); + EC_KEY_free(key_a); + EC_GROUP_free(group_a); + goto free_ctx; + } + + /* set prikey */ + privKey = BN_bin2bn(setup.d, setup.d_size, NULL); + ret = EC_KEY_set_private_key(key_a, privKey); + if (ret != 1) { + printf("EC_KEY_set_private_key failed\n"); + EC_KEY_free(key_a); + EC_GROUP_free(group_a); + goto free_ctx; + } + BN_free(privKey); + + EC_GROUP_free(group_a); + + sig = ECDSA_SIG_new(); + if (!sig) { + HPRE_TST_PRT("ECDSA_SIG_new fail!\n"); + EC_KEY_free(key_a); + goto free_ctx; + } + + /* openssl sign */ + sig = ECDSA_do_sign(setup.digest, setup.digest_size, key_a); + if (!sig) { + printf("ECDSA_do_sign failed\n"); + EC_KEY_free(key_a); + ECDSA_SIG_free(sig); + goto free_ctx; + } + + /* get r s */ + b_r = (void *)ECDSA_SIG_get0_r((const ECDSA_SIG *)sig); + ret = BN_bn2bin(b_r, buf1); + r.data = (void *)buf1; + r.dsize = ret; + r.bsize = key_size; + b_s = (void *)ECDSA_SIG_get0_s((const ECDSA_SIG *)sig); + ret = BN_bn2bin(b_s, buf2); + s.data = (void *)buf2; + s.dsize = ret; + s.bsize = key_size; + ECDSA_SIG_free(sig); + ecc_in = wcrypto_new_ecdsa_verf_in(ctx, &e, &r, &s); + if (!ecc_in) { + HPRE_TST_PRT("%s: new ecc in fail!\n", __func__); + EC_KEY_free(key_a); + goto free_ctx; + } + EC_KEY_free(key_a); + } + +#ifdef DEBUG + //struct wd_dtb *p; + + //wcrypto_get_ecc_prikey_params(ecc_key, &p, NULL, NULL, NULL, NULL, NULL); + //print_data(p->data, ECC_PRIKEY_SZ(p->bsize), "prikey"); + //print_data(test_ctx->cp_pub_key, test_ctx->cp_pub_key_size, "cp_pub_key"); +#endif + + opdata->op_type = WCRYPTO_ECDSA_VERIFY; + opdata->in = ecc_in; + test_ctx->opdata = opdata; + test_ctx->pool = setup.pool; + test_ctx->op = setup.op_type; + test_ctx->priv = ctx; //init ctx + test_ctx->key_size = key_size; + + return test_ctx; + +free_ctx: + free(test_ctx); +free_opdata: + free(opdata); + + return NULL; +} + +static int hpre_get_rand(char *out, size_t out_len, void *usr) +{ + int ret; + + if (!out) { + return -1; + } + + ret = RAND_priv_bytes((void *)out, out_len); + if (ret != 1) { + HPRE_TST_PRT("RAND_priv_bytes fail = %d\n", ret); + return -1; + } + + return 0; +} + +static struct ecc_test_ctx *sm2_create_hw_sign_test_ctx(struct ecc_test_ctx_setup setup, u32 op_type) +{ + + struct wcrypto_ecc_op_data *opdata; + struct ecc_test_ctx *test_ctx; + struct wcrypto_ecc_key *ecc_key; + struct wcrypto_ecc_out *ecc_out; + struct wcrypto_ecc_in *ecc_in = NULL; + struct wcrypto_ecc_point pub; + EC_POINT *point_tmp, *ptr; + EC_KEY *key_a = NULL; + EC_GROUP *group_a; + BIGNUM *pubKey, *priv; + void *ctx = setup.ctx; + struct wd_dtb d, e, k, id; + struct wd_dtb *kptr = NULL, *idptr = NULL; + char buff[32] = {0}; + char *hex_str; + int ret; + u32 key_size; + EVP_MD_CTX *md_ctx = NULL; + EVP_PKEY *p_key = NULL; + EVP_PKEY_CTX *pctx; + __u8 is_dgst = 0; + + if (!setup.q || !setup.pool) { + HPRE_TST_PRT("%s: parm err!\n", __func__); + return NULL; + } + + opdata = malloc(sizeof(struct wcrypto_ecc_op_data)); + if (!opdata) + return NULL; + memset(opdata, 0, sizeof(struct wcrypto_ecc_op_data)); + + test_ctx = malloc(sizeof(struct ecc_test_ctx)); + if (!test_ctx) { + HPRE_TST_PRT("%s: malloc fail!\n", __func__); + goto free_opdata; + } + memset(test_ctx, 0, sizeof(struct ecc_test_ctx)); + + key_size = (wcrypto_get_ecc_key_bits(ctx) + 7) / 8; + ecc_out = wcrypto_new_sm2_sign_out(ctx); + if (!ecc_out) { + HPRE_TST_PRT("%s: new ecc out fail!\n", __func__); + goto free_ctx; + } + ecc_key = wcrypto_get_ecc_key(ctx); + if (!g_is_set_prikey || !is_async_test(op_type)) { + d.data = setup.priv_key; + d.dsize = setup.priv_key_size; + d.bsize = key_size; + ret = wcrypto_set_ecc_prikey(ecc_key, &d); + if (ret) { + HPRE_TST_PRT("%s: set prikey err\n", __func__); + goto del_ecc_out; + } + g_is_set_prikey = true; + } + + if (!g_is_set_pubkey || !is_async_test(op_type)) { + pub.x.data = setup.pub_key + 1; + pub.x.dsize = key_size; + pub.x.bsize = key_size; + pub.y.data = pub.x.data + key_size; + pub.y.dsize = key_size; + pub.y.bsize = key_size; + ret = wcrypto_set_ecc_pubkey(ecc_key, &pub); + if (ret) { + HPRE_TST_PRT("%s: set pubkey err\n", __func__); + goto del_ecc_out; + } + g_is_set_pubkey = true; + } + + if (set_msg == MSG_DIGEST) { + e.data = setup.digest; + e.dsize = setup.digest_size; + e.bsize = key_size; + } else { + e.data = setup.plaintext; + e.dsize = setup.plaintext_size; + e.bsize = setup.plaintext_size; + } + + if (setup.key_from) { // set k, id param and support plaintext or dgst + k.data = setup.kinv; + k.dsize = setup.kinv_size; + k.bsize = key_size; + is_dgst = (set_msg != MSG_DIGEST) ? 0 : 1; + ecc_in = wcrypto_new_sm2_sign_in(ctx, &e, &k, &id, is_dgst); + if (!ecc_in) { + HPRE_TST_PRT("%s: new sm2 sign in fail!\n", __func__); + goto del_ecc_out; + } + } else { + key_a = EC_KEY_new(); + if (!key_a) { + printf("EC_KEY_new err!\n"); + goto del_ecc_out; + } + + group_a = EC_GROUP_new_by_curve_name(EVP_PKEY_SM2); + if(!group_a) { + printf("EC_GROUP_new_by_curve_name err!\n"); + goto del_ecc_out; + } + + ret = EC_KEY_set_group(key_a, group_a); + if(ret != 1) { + printf("EC_KEY_set_group err.\n"); + EC_KEY_free(key_a); + EC_GROUP_free(group_a); + goto del_ecc_out; + } + + /* set pubkey */ + point_tmp = EC_GROUP_get0_generator(group_a); + pubKey = BN_bin2bn(setup.pub_key, setup.pub_key_size, NULL); + ptr = EC_POINT_bn2point(group_a, pubKey, point_tmp, NULL); + if (!ptr) { + printf("EC_POINT_bn2point failed\n"); + BN_free(pubKey); + EC_KEY_free(key_a); + EC_GROUP_free(group_a); + goto del_ecc_out; + } + + ret = EC_KEY_set_public_key(key_a, point_tmp); + if (ret != 1) { + printf("EC_KEY_set_public_key failed\n"); + BN_free(pubKey); + EC_KEY_free(key_a); + EC_GROUP_free(group_a); + goto del_ecc_out; + } + BN_free(pubKey); + + /* set prikey */ + priv = BN_bin2bn(setup.priv_key, setup.priv_key_size, NULL); + ret = EC_KEY_set_private_key(key_a, priv); + if (ret != 1) { + printf("EC_KEY_set_private_key failed\n"); + EC_KEY_free(key_a); + EC_GROUP_free(group_a); + goto del_ecc_out; + } + BN_free(priv); + + EC_GROUP_free(group_a); + + p_key = EVP_PKEY_new(); + if (!p_key) { + printf("EVP_PKEY_new failed\n"); + goto del_ecc_out; + } + EVP_PKEY_set1_EC_KEY(p_key, key_a); + EVP_PKEY_set_alias_type(p_key, EVP_PKEY_SM2); + + md_ctx = EVP_MD_CTX_new(); + if (!md_ctx) { + printf("EVP_MD_CTX_new failed\n"); + goto free_pkey; + } + + pctx = EVP_PKEY_CTX_new(p_key, NULL); + if (!pctx) { + printf("EVP_PKEY_CTX_new failed\n"); + goto free_md_ctx; + } + EVP_MD_CTX_set_pkey_ctx(md_ctx, pctx); + + if (set_rand == RAND_PARAM) { + ret = hpre_get_rand(buff, 32, NULL); + if (ret) { + printf("hpre_get_rand failed\n"); + goto free_pkey_ctx; + } + k.data = buff; + k.dsize = 32; + kptr = &k; + + /* openssl set rand*/ + hex_str = OPENSSL_buf2hexstr((void *)buff, 32); + start_fake_rand(hex_str); + OPENSSL_free(hex_str); + } + + test_ctx->cp_sign_size = MAX_SIGN_LENS; + if (set_msg == MSG_DIGEST) { + ret = EVP_PKEY_sign_init(pctx); + if (ret != 1) { + printf("EVP_PKEY_sign_init fail, ret %d\n", ret); + goto free_pkey_ctx; + } + + ret = EVP_PKEY_sign(pctx, test_ctx->cp_sign, &test_ctx->cp_sign_size, + setup.digest, setup.digest_size); + if (ret != 1) { + printf("EVP_PKEY_sign fail, ret %d\n", ret); + goto free_pkey_ctx; + } + //print_data(test_ctx->cp_sign, test_ctx->cp_sign_size, "cp_sign"); + + } else { + id.data = setup.userid; + id.dsize = setup.userid_size; + idptr = &id; + + EVP_PKEY_CTX_set1_id(pctx, setup.userid, setup.userid_size); + EVP_DigestSignInit(md_ctx, NULL, get_digest_handle(), NULL, p_key); + EVP_DigestSignUpdate(md_ctx, setup.plaintext, setup.plaintext_size); + ret = EVP_DigestSignFinal(md_ctx, test_ctx->cp_sign, &test_ctx->cp_sign_size); + if (ret != 1) { + printf("EVP_DigestSignFinal failed ret = %d\n", ret); + goto free_pkey_ctx; + } + } + + + is_dgst = (set_msg != MSG_DIGEST) ? 0 : 1; + ecc_in = wcrypto_new_sm2_sign_in(ctx, &e, kptr, idptr, is_dgst); + if (!ecc_in) { + HPRE_TST_PRT("%s: new sm2 sign in fail!\n", __func__); + goto free_pkey_ctx; + } + } + +#ifdef DEBUG + struct wd_dtb *p; + + wcrypto_get_ecc_prikey_params(ecc_key, &p, NULL, NULL, NULL, NULL, NULL); + print_data(p->data, ECC_PRIKEY_SZ(p->bsize), "prikey"); + print_data(test_ctx->cp_sign, test_ctx->cp_sign_size, "cp_sign"); +#endif + + evp_to_wd_crypto((void *)test_ctx->cp_sign, &test_ctx->cp_sign_size, 32, setup.op_type); + + opdata->op_type = WCRYPTO_SM2_SIGN; + opdata->out = ecc_out; + opdata->in = ecc_in; + test_ctx->opdata = opdata; + test_ctx->pool = setup.pool; + test_ctx->op = setup.op_type; + test_ctx->priv = ctx; //init ctx + test_ctx->key_size = key_size; + test_ctx->priv1 = md_ctx; + + return test_ctx; + +free_pkey_ctx: + EVP_PKEY_CTX_free(pctx); +free_md_ctx: + EVP_MD_CTX_free(md_ctx); +free_pkey: + EVP_PKEY_free(p_key); +del_ecc_out: + (void)wcrypto_del_ecc_out(ctx, ecc_out); +free_ctx: + free(test_ctx); +free_opdata: + free(opdata); + + return NULL; +} + +static struct ecc_test_ctx *sm2_create_sw_sign_test_ctx(struct ecc_test_ctx_setup setup, u32 optype) +{ + + return NULL; +} + +static struct ecc_test_ctx *sm2_create_hw_verf_test_ctx(struct ecc_test_ctx_setup setup, u32 op_type) +{ + struct wcrypto_ecc_op_data *opdata; + struct ecc_test_ctx *test_ctx; + struct wcrypto_ecc_key *ecc_key; + struct wcrypto_ecc_in *ecc_in; + EC_KEY *key_a = NULL; + EC_GROUP *group_a; + BIGNUM *privKey, *pubKey; + void *ctx = setup.ctx; + struct wd_dtb e, r, s, id; + struct wcrypto_ecc_point pub; + int ret; + u32 key_size; + EVP_MD_CTX *md_ctx = NULL; + EVP_PKEY *p_key = NULL; + EVP_PKEY_CTX *pctx; + EC_POINT *point_tmp, *ptr; + + if (!setup.q || !setup.pool) { + HPRE_TST_PRT("%s: parm err!\n", __func__); + return NULL; + } + + opdata = malloc(sizeof(struct wcrypto_ecc_op_data)); + if (!opdata) + return NULL; + memset(opdata, 0, sizeof(struct wcrypto_ecc_op_data)); + + test_ctx = malloc(sizeof(struct ecc_test_ctx)); + if (!test_ctx) { + HPRE_TST_PRT("%s: malloc fail!\n", __func__); + goto free_opdata; + } + memset(test_ctx, 0, sizeof(struct ecc_test_ctx)); + + key_size = (wcrypto_get_ecc_key_bits(ctx) + 7) / 8; + ecc_key = wcrypto_get_ecc_key(ctx); + if (!g_is_set_pubkey || !is_async_test(op_type)) { + pub.x.data = setup.pub_key + 1; + pub.x.dsize = key_size; + pub.x.bsize = key_size; + pub.y.data = pub.x.data + key_size; + pub.y.dsize = key_size; + pub.y.bsize = key_size; + ret = wcrypto_set_ecc_pubkey(ecc_key, &pub); + if (ret) { + HPRE_TST_PRT("%s: set pubkey err\n", __func__); + goto free_ctx; + } + g_is_set_pubkey = true; + } + + if (setup.key_from) { + e.data = setup.digest; + e.dsize = setup.digest_size; + e.bsize = key_size; + r.data = setup.sign ; + r.dsize = key_size; + r.bsize = key_size; + s.data = r.data + key_size; + s.dsize = key_size; + s.bsize = key_size; + ecc_in = wcrypto_new_sm2_verf_in(ctx, &e, &r, &s, NULL, 1); + if (!ecc_in) { + HPRE_TST_PRT("%s: new ecc in fail!\n", __func__); + goto free_ctx; + } + } else { + key_a = EC_KEY_new(); + if (!key_a) { + printf("EC_KEY_new err!\n"); + goto free_ctx; + } + + group_a = EC_GROUP_new_by_curve_name(EVP_PKEY_SM2); + if(!group_a) { + printf("EC_GROUP_new_by_curve_name err!\n"); + EC_KEY_free(key_a); + goto free_ctx; + } + + ret = EC_KEY_set_group(key_a, group_a); + if(ret != 1) { + printf("EC_KEY_set_group err.\n"); + EC_KEY_free(key_a); + EC_GROUP_free(group_a); + goto free_ctx; + } + + /* set pubkey */ + point_tmp = EC_GROUP_get0_generator(group_a); + pubKey = BN_bin2bn(setup.pub_key, setup.pub_key_size, NULL); + ptr = EC_POINT_bn2point(group_a, pubKey, point_tmp, NULL); + if (!ptr) { + printf("EC_POINT_bn2point failed\n"); + BN_free(pubKey); + EC_KEY_free(key_a); + EC_GROUP_free(group_a); + goto free_ctx; + } + + ret = EC_KEY_set_public_key(key_a, point_tmp); + if (ret != 1) { + printf("EC_KEY_set_public_key failed\n"); + BN_free(pubKey); + EC_KEY_free(key_a); + EC_GROUP_free(group_a); + goto free_ctx; + } + BN_free(pubKey); + + /* set prikey */ + privKey = BN_bin2bn(setup.priv_key, setup.priv_key_size, NULL); + ret = EC_KEY_set_private_key(key_a, privKey); + if (ret != 1) { + printf("EC_KEY_set_private_key failed\n"); + EC_KEY_free(key_a); + EC_GROUP_free(group_a); + goto free_ctx; + } + BN_free(privKey); + EC_GROUP_free(group_a); + + /* openssl sign */ + p_key = EVP_PKEY_new(); + if (!p_key) { + printf("EVP_PKEY_new failed\n"); + EC_KEY_free(key_a); + goto free_ctx; + } + EVP_PKEY_set1_EC_KEY(p_key, key_a); + EVP_PKEY_set_alias_type(p_key, EVP_PKEY_SM2); + + md_ctx = EVP_MD_CTX_new(); + if (!md_ctx) { + printf("EVP_MD_CTX_new failed\n"); + EC_KEY_free(key_a); + goto free_pkey; + } + + pctx = EVP_PKEY_CTX_new(p_key, NULL); + if (!pctx) { + printf("EVP_PKEY_CTX_new failed\n"); + EC_KEY_free(key_a); + goto free_md_ctx; + } + + test_ctx->cp_sign_size = MAX_SIGN_LENS; + id.data = setup.userid; + id.dsize = setup.userid_size; + + EVP_MD_CTX_set_pkey_ctx(md_ctx, pctx); + EVP_PKEY_CTX_set1_id(pctx, setup.userid, setup.userid_size); + EVP_DigestSignInit(md_ctx, NULL, get_digest_handle(), NULL, p_key); + //EVP_DigestSignUpdate(md_ctx, setup.plaintext, setup.plaintext_size); + ret = EVP_DigestSign(md_ctx, test_ctx->cp_sign, &test_ctx->cp_sign_size, + setup.plaintext, setup.plaintext_size); + if (ret != 1) { + printf("EVP_DigestSign failed ret = %d\n", ret); + EC_KEY_free(key_a); + goto free_pkey_ctx; + } + + evp_sign_to_hpre_bin((void *)test_ctx->cp_sign, &test_ctx->cp_sign_size, key_size); + + e.data = setup.plaintext; + e.dsize = setup.plaintext_size; + e.bsize = setup.plaintext_size; + r.data = (void *)test_ctx->cp_sign; + r.dsize = key_size; + r.bsize = key_size; + s.data = (void *)(test_ctx->cp_sign + key_size); + s.dsize = key_size; + s.bsize = key_size; + ecc_in = wcrypto_new_sm2_verf_in(ctx, &e, &r, &s, &id, 0); + if (!ecc_in) { + HPRE_TST_PRT("%s: new sm2 verf in fail!\n", __func__); + EC_KEY_free(key_a); + goto free_pkey_ctx; + } + EC_KEY_free(key_a); + EVP_PKEY_free(p_key); + EVP_MD_CTX_free(md_ctx); + EVP_PKEY_CTX_free(pctx); + } + +#ifdef DEBUG + struct wd_dtb *p; + + wcrypto_get_ecc_pubkey_params(ecc_key, &p, NULL, NULL, NULL, NULL, NULL); + print_data(p->data, ECC_PRIKEY_SZ(p->bsize), "pubkey"); + print_data(setup.userid, setup.userid_size, "userid"); + + print_data(test_ctx->cp_sign, test_ctx->cp_sign_size, "openssl sign"); + +#endif + + opdata->op_type = WCRYPTO_SM2_VERIFY; + opdata->in = ecc_in; + test_ctx->opdata = opdata; + test_ctx->pool = setup.pool; + test_ctx->op = setup.op_type; + test_ctx->priv = ctx; //init ctx + test_ctx->key_size = key_size; + + return test_ctx; + +free_pkey_ctx: + EVP_PKEY_CTX_free(pctx); +free_md_ctx: + EVP_MD_CTX_free(md_ctx); +free_pkey: + EVP_PKEY_free(p_key); +free_ctx: + free(test_ctx); +free_opdata: + free(opdata); + + return NULL; +} + +static struct ecc_test_ctx *sm2_create_sw_verf_test_ctx(struct ecc_test_ctx_setup setup, u32 optype) +{ + + return NULL; +} + +static struct ecc_test_ctx *sm2_create_sw_enc_test_ctx(struct ecc_test_ctx_setup setup, u32 op_type) +{ + + return NULL; +} + +static struct ecc_test_ctx *sm2_create_hw_enc_test_ctx(struct ecc_test_ctx_setup setup, u32 op_type) +{ + + struct wcrypto_ecc_op_data *opdata; + struct ecc_test_ctx *test_ctx; + struct wcrypto_ecc_key *ecc_key; + struct wcrypto_ecc_out *ecc_out; + struct wcrypto_ecc_in *ecc_in = NULL; + struct wcrypto_ecc_point pub; + EC_POINT *point_tmp, *ptr; + EC_KEY *key_a = NULL; + EC_GROUP *group_a; + BIGNUM *pubKey, *priv; + void *ctx = setup.ctx; + struct wd_dtb d, e, k; + struct wd_dtb *kptr = NULL; + char buff[32] = {0}; + char *hex_str; + int ret; + u32 key_size; + EVP_PKEY *p_key = NULL; + EVP_PKEY_CTX *pctx = NULL; + + if (!setup.q || !setup.pool) { + HPRE_TST_PRT("%s: parm err!\n", __func__); + return NULL; + } + + opdata = malloc(sizeof(struct wcrypto_ecc_op_data)); + if (!opdata) + return NULL; + memset(opdata, 0, sizeof(struct wcrypto_ecc_op_data)); + + test_ctx = malloc(sizeof(struct ecc_test_ctx)); + if (!test_ctx) { + HPRE_TST_PRT("%s: malloc fail!\n", __func__); + goto free_opdata; + } + memset(test_ctx, 0, sizeof(struct ecc_test_ctx)); + + key_size = (wcrypto_get_ecc_key_bits(ctx) + 7) / 8; + ecc_out = wcrypto_new_sm2_enc_out(ctx, setup.plaintext_size); + if (!ecc_out) { + HPRE_TST_PRT("%s: new ecc out fail!\n", __func__); + goto free_ctx; + } + ecc_key = wcrypto_get_ecc_key(ctx); + if (!g_is_set_prikey || !is_async_test(op_type)) { + d.data = setup.priv_key; + d.dsize = setup.priv_key_size; + d.bsize = key_size; + ret = wcrypto_set_ecc_prikey(ecc_key, &d); + if (ret) { + HPRE_TST_PRT("%s: set prikey err\n", __func__); + goto del_ecc_out; + } + g_is_set_prikey = true; + } + + if (!g_is_set_pubkey || !is_async_test(op_type)) { + pub.x.data = setup.pub_key + 1; + pub.x.dsize = key_size; + pub.x.bsize = key_size; + pub.y.data = pub.x.data + key_size; + pub.y.dsize = key_size; + pub.y.bsize = key_size; + ret = wcrypto_set_ecc_pubkey(ecc_key, &pub); + if (ret) { + HPRE_TST_PRT("%s: set pubkey err\n", __func__); + goto del_ecc_out; + } + g_is_set_pubkey = true; + } + + e.data = setup.plaintext; + e.dsize = setup.plaintext_size; + e.bsize = setup.plaintext_size; + if (setup.key_from) { // set k, id param and support plaintext or dgst + k.data = setup.kinv; + k.dsize = setup.kinv_size; + k.bsize = key_size; + ecc_in = wcrypto_new_sm2_enc_in(ctx, &k, &e); + if (!ecc_in) { + HPRE_TST_PRT("%s: new sm2 sign in fail!\n", __func__); + goto del_ecc_out; + } + } else { + key_a = EC_KEY_new(); + if (!key_a) { + printf("EC_KEY_new err!\n"); + goto del_ecc_out; + } + + group_a = EC_GROUP_new_by_curve_name(EVP_PKEY_SM2); + if(!group_a) { + printf("EC_GROUP_new_by_curve_name err!\n"); + goto del_ecc_out; + } + + ret = EC_KEY_set_group(key_a, group_a); + if(ret != 1) { + printf("EC_KEY_set_group err.\n"); + EC_KEY_free(key_a); + EC_GROUP_free(group_a); + goto del_ecc_out; + } + + /* set pubkey */ + point_tmp = EC_GROUP_get0_generator(group_a); + pubKey = BN_bin2bn(setup.pub_key, setup.pub_key_size, NULL); + ptr = EC_POINT_bn2point(group_a, pubKey, point_tmp, NULL); + if (!ptr) { + printf("EC_POINT_bn2point failed\n"); + BN_free(pubKey); + EC_KEY_free(key_a); + EC_GROUP_free(group_a); + goto del_ecc_out; + } + + ret = EC_KEY_set_public_key(key_a, point_tmp); + if (ret != 1) { + printf("EC_KEY_set_public_key failed\n"); + BN_free(pubKey); + EC_KEY_free(key_a); + EC_GROUP_free(group_a); + goto del_ecc_out; + } + BN_free(pubKey); + + /* set prikey */ + priv = BN_bin2bn(setup.priv_key, setup.priv_key_size, NULL); + ret = EC_KEY_set_private_key(key_a, priv); + if (ret != 1) { + printf("EC_KEY_set_private_key failed\n"); + EC_KEY_free(key_a); + EC_GROUP_free(group_a); + goto del_ecc_out; + } + BN_free(priv); + + EC_GROUP_free(group_a); + + p_key = EVP_PKEY_new(); + if (!p_key) { + printf("EVP_PKEY_new failed\n"); + goto del_ecc_out; + } + EVP_PKEY_set1_EC_KEY(p_key, key_a); + EVP_PKEY_set_alias_type(p_key, EVP_PKEY_SM2); + + pctx = EVP_PKEY_CTX_new(p_key, NULL); + if (!pctx) { + printf("EVP_PKEY_CTX_new failed\n"); + goto free_pkey; + } + +#ifdef DEBUG + ECParameters_print_fp(stdout, key_a); + EC_KEY_print_fp(stdout, key_a, 0); +#endif + + if (set_rand == RAND_PARAM) { + ret = hpre_get_rand(buff, 32, NULL); + if (ret) { + printf("hpre_get_rand failed\n"); + goto free_pkey_ctx; + } + k.data = buff; + k.dsize = BITS_TO_BYTES(set_randparam_len); + kptr = &k; + + /* openssl set rand*/ + hex_str = OPENSSL_buf2hexstr((void *)buff, k.dsize); + start_fake_rand(hex_str); + OPENSSL_free(hex_str); + + EVP_PKEY_encrypt_init(pctx); + EVP_PKEY_CTX_ctrl(pctx, -1, -1, EVP_PKEY_CTRL_MD, -1, (void *)get_digest_handle()); + test_ctx->cp_enc_size = MAX_ENC_LENS; + ret = EVP_PKEY_encrypt(pctx, test_ctx->cp_enc, &test_ctx->cp_enc_size, + setup.plaintext, setup.plaintext_size); + if (ret != 1) { + printf("EVP_PKEY_encrypt failed ret = %d\n", ret); + goto free_pkey_ctx; + } + + #ifdef DEBUG + struct wd_dtb *p; + + wcrypto_get_ecc_pubkey_params(ecc_key, &p, NULL, NULL, NULL, NULL, NULL); + print_data(p->data, ECC_PRIKEY_SZ(p->bsize), "pubkey"); + print_data(test_ctx->cp_enc, test_ctx->cp_enc_size, "cp_enc"); + #endif + evp_to_wd_crypto((void *)test_ctx->cp_enc, &test_ctx->cp_enc_size, 32, setup.op_type); + //print_data(test_ctx->cp_enc, test_ctx->cp_enc_size, "cp_enc"); + + } else { + EVP_PKEY_decrypt_init(pctx); + EVP_PKEY_CTX_ctrl(pctx, -1, -1, EVP_PKEY_CTRL_MD, -1, (void *)get_digest_handle()); + } + + ecc_in = wcrypto_new_sm2_enc_in(ctx, kptr, &e); + if (!ecc_in) { + HPRE_TST_PRT("%s: new ecc in fail!\n", __func__); + goto free_pkey_ctx; + } + } + + opdata->op_type = WCRYPTO_SM2_ENCRYPT; + opdata->out = ecc_out; + opdata->in = ecc_in; + test_ctx->opdata = opdata; + test_ctx->pool = setup.pool; + test_ctx->op = setup.op_type; + test_ctx->priv = ctx; //init ctx + test_ctx->key_size = key_size; + test_ctx->priv1 = pctx; + + return test_ctx; + +free_pkey_ctx: + EVP_PKEY_CTX_free(pctx); +free_pkey: + EVP_PKEY_free(p_key); +del_ecc_out: + (void)wcrypto_del_ecc_out(ctx, ecc_out); +free_ctx: + free(test_ctx); +free_opdata: + free(opdata); + + return NULL; +} + +static struct ecc_test_ctx *sm2_create_hw_dec_test_ctx(struct ecc_test_ctx_setup setup, u32 op_type) +{ + + struct wcrypto_ecc_op_data *opdata; + struct ecc_test_ctx *test_ctx; + struct wcrypto_ecc_key *ecc_key; + struct wcrypto_ecc_out *ecc_out; + struct wcrypto_ecc_in *ecc_in = NULL; + EC_POINT *point_tmp, *ptr; + EC_KEY *key_a = NULL; + EC_GROUP *group_a; + BIGNUM *pubKey; + void *ctx = setup.ctx; + struct wcrypto_ecc_point c1; + struct wd_dtb d, c2, c3; + int ret; + u32 key_size; + EVP_PKEY *p_key = NULL; + EVP_PKEY_CTX *pctx = NULL; + + if (!setup.q || !setup.pool) { + HPRE_TST_PRT("%s: parm err!\n", __func__); + return NULL; + } + + opdata = malloc(sizeof(struct wcrypto_ecc_op_data)); + if (!opdata) + return NULL; + memset(opdata, 0, sizeof(struct wcrypto_ecc_op_data)); + + test_ctx = malloc(sizeof(struct ecc_test_ctx)); + if (!test_ctx) { + HPRE_TST_PRT("%s: malloc fail!\n", __func__); + goto free_opdata; + } + memset(test_ctx, 0, sizeof(struct ecc_test_ctx)); + + key_size = (wcrypto_get_ecc_key_bits(ctx) + 7) / 8; + ecc_out = wcrypto_new_sm2_dec_out(ctx, setup.plaintext_size); + if (!ecc_out) { + HPRE_TST_PRT("%s: new ecc out fail!\n", __func__); + goto free_ctx; + } + ecc_key = wcrypto_get_ecc_key(ctx); + if (!g_is_set_prikey || !is_async_test(op_type)) { + d.data = setup.priv_key; + d.dsize = setup.priv_key_size; + d.bsize = key_size; + ret = wcrypto_set_ecc_prikey(ecc_key, &d); + if (ret) { + HPRE_TST_PRT("%s: set prikey err\n", __func__); + goto del_ecc_out; + } + g_is_set_prikey = true; + } + + if (setup.key_from) { // set k, id param and support plaintext or dgst + c1.x.data = test_ctx->setup.cp_c; + c1.x.dsize = 32; + c1.y.data = c1.x.data + 32; + c1.y.dsize = 32; + c3.data = c1.y.data + 32; + c3.dsize = 32; + c2.data = c3.data + 32; + c2.dsize = test_ctx->setup.cp_c_size - 32 * 3; + ecc_in = wcrypto_new_sm2_dec_in(ctx, &c1, &c2, &c3); + if (!ecc_in) { + HPRE_TST_PRT("%s: new sm2 sign in fail!\n", __func__); + goto del_ecc_out; + } + } else { + key_a = EC_KEY_new(); + if (!key_a) { + printf("EC_KEY_new err!\n"); + goto del_ecc_out; + } + + group_a = EC_GROUP_new_by_curve_name(EVP_PKEY_SM2); + if(!group_a) { + printf("EC_GROUP_new_by_curve_name err!\n"); + goto del_ecc_out; + } + + ret = EC_KEY_set_group(key_a, group_a); + if(ret != 1) { + printf("EC_KEY_set_group err.\n"); + EC_KEY_free(key_a); + EC_GROUP_free(group_a); + goto del_ecc_out; + } + + /* set pubkey */ + point_tmp = EC_GROUP_get0_generator(group_a); + pubKey = BN_bin2bn(setup.pub_key, setup.pub_key_size, NULL); + ptr = EC_POINT_bn2point(group_a, pubKey, point_tmp, NULL); + if (!ptr) { + printf("EC_POINT_bn2point failed\n"); + BN_free(pubKey); + EC_KEY_free(key_a); + EC_GROUP_free(group_a); + goto del_ecc_out; + } + + ret = EC_KEY_set_public_key(key_a, point_tmp); + if (ret != 1) { + printf("EC_KEY_set_public_key failed\n"); + BN_free(pubKey); + EC_KEY_free(key_a); + EC_GROUP_free(group_a); + goto del_ecc_out; + } + BN_free(pubKey); + + EC_GROUP_free(group_a); + + p_key = EVP_PKEY_new(); + if (!p_key) { + printf("EVP_PKEY_new failed\n"); + goto del_ecc_out; + } + EVP_PKEY_set1_EC_KEY(p_key, key_a); + EVP_PKEY_set_alias_type(p_key, EVP_PKEY_SM2); + + pctx = EVP_PKEY_CTX_new(p_key, NULL); + if (!pctx) { + printf("EVP_PKEY_CTX_new failed\n"); + goto free_pkey; + } + + EVP_PKEY_encrypt_init(pctx); + EVP_PKEY_CTX_ctrl(pctx, -1, -1, EVP_PKEY_CTRL_MD, -1, (void *)get_digest_handle()); + test_ctx->cp_enc_size = MAX_ENC_LENS; + ret = EVP_PKEY_encrypt(pctx, (void *)test_ctx->cp_enc, &test_ctx->cp_enc_size, + setup.plaintext, setup.plaintext_size); + if (ret != 1) { + printf("EVP_PKEY_encrypt failed ret = %d\n", ret); + goto free_pkey_ctx; + } + + //print_data(test_ctx->cp_enc, test_ctx->cp_enc_size, "cp_enc"); + + evp_to_wd_crypto((void *)test_ctx->cp_enc, &test_ctx->cp_enc_size, 32, SM2_HW_ENC); + + c1.x.data = (void *)test_ctx->cp_enc; + c1.x.dsize = 32; + c1.y.data = c1.x.data + 32; + c1.y.dsize = 32; + c3.data = c1.y.data + 32; + c3.dsize = get_hash_bytes(); + c2.data = c3.data + c3.dsize; + c2.dsize = setup.plaintext_size; + ecc_in = wcrypto_new_sm2_dec_in(ctx, &c1, &c2, &c3); + if (!ecc_in) { + HPRE_TST_PRT("%s: new ecc in fail!\n", __func__); + goto del_ecc_out; + } + } + +#ifdef DEBUG + struct wd_dtb *p; + + wcrypto_get_ecc_prikey_params(ecc_key, &p, NULL, NULL, NULL, NULL, NULL); + print_data(p->data, ECC_PRIKEY_SZ(p->bsize), "prikey"); + print_data(test_ctx->cp_enc, test_ctx->cp_enc_size, "cp_enc"); +#endif + + opdata->op_type = WCRYPTO_SM2_DECRYPT; + opdata->out = ecc_out; + opdata->in = ecc_in; + test_ctx->opdata = opdata; + test_ctx->pool = setup.pool; + test_ctx->op = setup.op_type; + test_ctx->priv = ctx; //init ctx + test_ctx->key_size = key_size; + + EC_KEY_free(key_a); + EVP_PKEY_free(p_key); + EVP_PKEY_CTX_free(pctx); + + return test_ctx; + +free_pkey: + EVP_PKEY_free(p_key); +free_pkey_ctx: + EVP_PKEY_CTX_free(pctx); +del_ecc_out: + (void)wcrypto_del_ecc_out(ctx, ecc_out); +free_ctx: + free(test_ctx); +free_opdata: + free(opdata); + + return NULL; +} + +static struct ecc_test_ctx *sm2_create_sw_dec_test_ctx(struct ecc_test_ctx_setup setup, u32 optype) +{ + + return NULL; +} + +static struct ecc_test_ctx *sm2_create_hw_kg_test_ctx(struct ecc_test_ctx_setup setup, u32 optype) +{ + + struct wcrypto_ecc_op_data *opdata; + struct ecc_test_ctx *test_ctx; + struct wcrypto_ecc_out *ecc_out; + void *ctx = setup.ctx; + u32 key_size; + + if (!setup.q || !setup.pool) { + HPRE_TST_PRT("%s: parm err!\n", __func__); + return NULL; + } + + opdata = malloc(sizeof(struct wcrypto_ecc_op_data)); + if (!opdata) + return NULL; + memset(opdata, 0, sizeof(struct wcrypto_ecc_op_data)); + + test_ctx = malloc(sizeof(struct ecc_test_ctx)); + if (!test_ctx) { + HPRE_TST_PRT("%s: malloc fail!\n", __func__); + goto free_opdata; + } + memset(test_ctx, 0, sizeof(struct ecc_test_ctx)); + + key_size = (wcrypto_get_ecc_key_bits(ctx) + 7) / 8; + ecc_out = wcrypto_new_sm2_kg_out(ctx); + if (!ecc_out) { + HPRE_TST_PRT("%s: new sm2 kg out fail!\n", __func__); + goto free_ctx; + } + + if (setup.key_from) { // set k, id param and support plaintext or dgst + } else {} + +#ifdef DEBUG + //struct wd_dtb *p; + + //wcrypto_get_ecc_pubkey_params(ecc_key, &p, NULL, NULL, NULL, NULL, NULL); + //print_data(p->data, ECC_PRIKEY_SZ(p->bsize), "pubkey"); + //print_data(test_ctx->cp_enc, test_ctx->cp_enc_size, "cp_enc"); +#endif + + opdata->op_type = WCRYPTO_SM2_KG; + opdata->out = ecc_out; + test_ctx->opdata = opdata; + test_ctx->pool = setup.pool; + test_ctx->op = setup.op_type; + test_ctx->priv = ctx; //init ctx + test_ctx->key_size = key_size; + + return test_ctx; + + (void)wcrypto_del_ecc_out(ctx, ecc_out); +free_ctx: + free(test_ctx); +free_opdata: + free(opdata); + + return NULL; +} + +static struct ecc_test_ctx *sm2_create_sw_kg_test_ctx(struct ecc_test_ctx_setup setup, u32 optype) +{ + + return NULL; +} + +int ecc_init_test_ctx_setup(struct ecc_test_ctx_setup *setup, __u32 op_type) +{ + int key_size = (key_bits + 7) / 8; + + if (!setup) + return -1; + + if (performance_test || op_type == ECDH_ASYNC_GEN || op_type == ECDH_ASYNC_COMPUTE) + setup->key_from = 1; //0 - Openssl 1 - Designed + else + setup->key_from = 0; //0 - Openssl 1 - Designed + + setup->key_bits = key_bits; + + if (setup->nid == 714 || key_bits == 256) { //NID_secp256k1 + /* sm2 */ + if (op_type == SM2_SIGN || op_type == SM2_VERF || + op_type == SM2_ENC || op_type == SM2_DEC || op_type == SM2_KG || + op_type == SM2_ASYNC_SIGN || op_type == SM2_ASYNC_VERF || + op_type == SM2_ASYNC_ENC || op_type == SM2_ASYNC_DEC || op_type == SM2_ASYNC_KG) { + + setup->priv_key = sm2_priv; + setup->priv_key_size = sizeof(sm2_priv); + setup->pub_key = sm2_pubkey; + setup->pub_key_size = sizeof(sm2_pubkey); + + if (set_msg == MSG_SHORT_PTEXT) { + setup->plaintext = sm2_plaintext; + setup->plaintext_size = sizeof(sm2_plaintext); + } else if (set_msg == MSG_DIGEST){ + setup->digest = sm2_digest; + setup->digest_size = sizeof(sm2_digest); + } else if (set_msg == MSG_LONG_PTEXT) { + setup->plaintext = malloc(BITS_TO_BYTES(set_plaintext_len)); + if (!setup->plaintext) { + HPRE_TST_PRT("malloc plaintext fail\n"); + return -1; + } + setup->plaintext_size = BITS_TO_BYTES(set_plaintext_len); + memset(setup->plaintext, 0x55, setup->plaintext_size); + } + + setup->kinv = sm2_k; + setup->kinv_size = BITS_TO_BYTES(set_randparam_len); + setup->cp_sign = sm2_cp_sign; + setup->cp_sign_size = sizeof(sm2_cp_sign); + setup->sign = sm2_cp_sign; + setup->sign_size = sizeof(sm2_cp_sign); + setup->userid = sm2_id; + setup->userid_size = sizeof(sm2_id); + setup->cp_c = sm2_cp_c; + setup->cp_c_size = sizeof(sm2_cp_c); + } else { + setup->d = ecdh_da_secp256k1; + setup->except_pub_key = ecdh_except_b_pubkey_secp256k1; + setup->cp_pub_key = ecdh_cp_pubkey_secp256k1; + setup->cp_share_key = ecdh_cp_sharekey_secp256k1; + setup->d_size = sizeof(ecdh_da_secp256k1); + setup->except_pub_key_size = sizeof(ecdh_except_b_pubkey_secp256k1); + setup->cp_pub_key_size = sizeof(ecdh_cp_pubkey_secp256k1); + setup->cp_share_key_size = sizeof(ecdh_cp_sharekey_secp256k1); + + /* ecc sign */ + setup->digest = ecc_except_e_secp256k1; + setup->digest_size = sizeof(ecc_except_e_secp256k1); + setup->kinv = ecc_except_kinv_secp256k1; + setup->kinv_size = sizeof(ecc_except_kinv_secp256k1); + setup->rp = ecdh_cp_pubkey_secp256k1 + 1; + setup->rp_size = key_size; + setup->cp_sign = ecdh_cp_pubkey_secp256k1 + 1; //todo + setup->cp_sign_size = 32; //todo + + /* ecc verf */ + setup->sign = ecc_cp_sign_secp256k1; + setup->sign_size = sizeof(ecc_cp_sign_secp256k1); + } + } else if (setup->nid == 706 || key_bits == 128) { + setup->d = ecdh_da_secp128k1; + setup->except_pub_key = ecdh_except_b_pubkey_secp128k1; + setup->cp_pub_key = ecdh_cp_pubkey_secp128k1; + setup->cp_share_key = ecdh_cp_sharekey_secp128k1; + setup->d_size = sizeof(ecdh_da_secp128k1); + setup->except_pub_key_size = sizeof(ecdh_except_b_pubkey_secp128k1); + setup->cp_pub_key_size = sizeof(ecdh_cp_pubkey_secp128k1); + setup->cp_share_key_size = sizeof(ecdh_cp_sharekey_secp128k1); + + /* ecc sign */ + setup->digest = ecc_except_e_secp128k1; + setup->digest_size = sizeof(ecc_except_e_secp128k1); + setup->kinv = ecc_except_kinv_secp128k1; + setup->kinv_size = sizeof(ecc_except_kinv_secp128k1); + setup->rp = ecdh_cp_pubkey_secp128k1 + 1; + setup->rp_size = key_size; + + /* ecc verf */ + setup->sign = ecc_cp_sign_secp256k1; + setup->sign_size = sizeof(ecc_cp_sign_secp256k1); + + } else if (setup->nid == 711 || key_bits == 192) { + setup->d = ecdh_da_secp192k1; + setup->except_pub_key = ecdh_except_b_pubkey_secp192k1; + setup->cp_pub_key = ecdh_cp_pubkey_secp192k1; + setup->cp_share_key = ecdh_cp_sharekey_secp192k1; + setup->d_size = sizeof(ecdh_da_secp192k1); + setup->except_pub_key_size = sizeof(ecdh_except_b_pubkey_secp192k1); + setup->cp_pub_key_size = sizeof(ecdh_cp_pubkey_secp192k1); + setup->cp_share_key_size = sizeof(ecdh_cp_sharekey_secp192k1); + + /* ecc sign */ + setup->digest = ecc_except_e_secp192k1; + setup->digest_size = sizeof(ecc_except_e_secp192k1); + setup->kinv = ecc_except_kinv_secp192k1; + setup->kinv_size = sizeof(ecc_except_kinv_secp192k1); + setup->rp = ecdh_cp_pubkey_secp192k1 + 1; + setup->rp_size = key_size; + + /* ecc verf */ + setup->sign = ecc_cp_sign_secp256k1; + setup->sign_size = sizeof(ecc_cp_sign_secp256k1); + } else if (setup->nid == 929 || key_bits == 320) { + setup->d = ecdh_da_secp320k1; + setup->except_pub_key = ecdh_except_b_pubkey_secp320k1; + setup->cp_pub_key = ecdh_cp_pubkey_secp320k1; + setup->cp_share_key = ecdh_cp_sharekey_secp320k1; + setup->d_size = sizeof(ecdh_da_secp320k1); + setup->except_pub_key_size = sizeof(ecdh_except_b_pubkey_secp320k1); + setup->cp_pub_key_size = sizeof(ecdh_cp_pubkey_secp320k1); + setup->cp_share_key_size = sizeof(ecdh_cp_sharekey_secp320k1); + + /* ecc sign */ + setup->digest = ecc_except_e_secp320k1; + setup->digest_size = sizeof(ecc_except_e_secp320k1); + setup->kinv = ecc_except_kinv_secp320k1; + setup->kinv_size = sizeof(ecc_except_kinv_secp320k1); + setup->rp = ecdh_cp_pubkey_secp192k1 + 1; + setup->rp_size = key_size; + + /* ecc verf */ + setup->sign = ecc_cp_sign_secp256k1; + setup->sign_size = sizeof(ecc_cp_sign_secp256k1); + + } else if (setup->nid == 931 || key_bits == 384) { + setup->d = ecdh_da_secp384k1; + setup->except_pub_key = ecdh_except_b_pubkey_secp384k1; + setup->cp_pub_key = ecdh_cp_pubkey_secp384k1; + setup->cp_share_key = ecdh_cp_sharekey_secp384k1; + setup->d_size = sizeof(ecdh_da_secp384k1); + setup->except_pub_key_size = sizeof(ecdh_except_b_pubkey_secp384k1); + setup->cp_pub_key_size = sizeof(ecdh_cp_pubkey_secp384k1); + setup->cp_share_key_size = sizeof(ecdh_cp_sharekey_secp384k1); + + /* ecc sign */ + setup->digest = ecc_except_e_secp384k1; + setup->digest_size = sizeof(ecc_except_e_secp384k1); + setup->kinv = ecc_except_kinv_secp384k1; + setup->kinv_size = sizeof(ecc_except_kinv_secp384k1); + setup->rp = ecdh_cp_pubkey_secp384k1 + 1; + setup->rp_size = key_size; + + /* ecc verf */ + setup->sign = ecc_cp_sign_secp256k1; + setup->sign_size = sizeof(ecc_cp_sign_secp256k1); + + } else if (setup->nid == 716 || key_bits == 521) { + setup->d = ecdh_da_secp521k1; + setup->except_pub_key = ecdh_except_b_pubkey_secp521k1; + setup->cp_pub_key = ecdh_cp_pubkey_secp521k1; + setup->cp_share_key = ecdh_cp_sharekey_secp521k1; + setup->d_size = sizeof(ecdh_da_secp521k1); + setup->except_pub_key_size = sizeof(ecdh_except_b_pubkey_secp521k1); + setup->cp_pub_key_size = sizeof(ecdh_cp_pubkey_secp521k1); + setup->cp_share_key_size = sizeof(ecdh_cp_sharekey_secp521k1); + + /* ecc sign */ + setup->digest = ecc_except_e_secp521k1; + setup->digest_size = sizeof(ecc_except_e_secp521k1); + setup->kinv = ecc_except_kinv_secp521k1; + setup->kinv_size = sizeof(ecc_except_kinv_secp521k1); + setup->rp = ecdh_cp_pubkey_secp521k1 + 1; + setup->rp_size = key_size; + + /* ecc verf */ + setup->sign = ecc_cp_sign_secp256k1; + setup->sign_size = sizeof(ecc_cp_sign_secp256k1); + + } else { + HPRE_TST_PRT("init test ctx setup not find this bits %d or nid %d\n", + key_bits, setup->nid); + return -1; + } + + return 0; +} + +static int get_ecc_nid(const char *name, __u32 *nid, __u32 *curve_id) +{ + int i; + + for (i = 0; i < sizeof(ecc_curve_tbls) / sizeof(ecc_curve_tbls[0]); i++) { + + if (!strcmp(name, ecc_curve_tbls[i].name)) { + *nid = ecc_curve_tbls[i].nid; + *curve_id = ecc_curve_tbls[i].curve_id; + return 0; + } + } + + return -1; +} + +struct ecc_test_ctx *ecc_create_test_ctx(struct ecc_test_ctx_setup setup, u32 optype) +{ + struct ecc_test_ctx *test_ctx = NULL; + + switch (setup.op_type) { + case ECDH_SW_GENERATE: + { + if (optype == ECDH_GEN || optype == ECDH_ASYNC_GEN) { + test_ctx = ecc_create_sw_gen_test_ctx(setup, optype); + } else if (optype == X25519_GEN || optype == X25519_ASYNC_GEN || + optype == X448_GEN || optype == X448_ASYNC_GEN) { + test_ctx = x_create_sw_gen_test_ctx(setup, optype); + } + } + break; + case ECDH_HW_GENERATE: + { + test_ctx = ecc_create_hw_gen_test_ctx(setup, optype); + } + break; + case ECDH_SW_COMPUTE: + { + if (optype == ECDH_COMPUTE || optype == ECDH_ASYNC_COMPUTE) { + test_ctx = ecc_create_sw_compute_test_ctx(setup, optype); + } else if (optype == X25519_COMPUTE || optype == X25519_ASYNC_COMPUTE || + optype == X448_COMPUTE || optype == X448_ASYNC_COMPUTE) { + test_ctx = x_create_sw_compute_test_ctx(setup, optype); + } + } + break; + case ECDH_HW_COMPUTE: + { + test_ctx = ecc_create_hw_compute_test_ctx(setup, optype); + } + break; + case ECC_HW_SIGN: + { + test_ctx = ecc_create_hw_sign_test_ctx(setup, optype); + } + break; + case ECC_HW_VERF: + { + test_ctx = ecc_create_hw_verf_test_ctx(setup, optype); + } + break; + case ECC_SW_SIGN: + { + test_ctx = ecc_create_sw_sign_test_ctx(setup, optype); + } + break; + case ECC_SW_VERF: + { + test_ctx = ecc_create_sw_verf_test_ctx(setup, optype); + } + break; + case SM2_HW_SIGN: + { + test_ctx = sm2_create_hw_sign_test_ctx(setup, optype); + } + break; + case SM2_HW_VERF: + { + test_ctx = sm2_create_hw_verf_test_ctx(setup, optype); + } + break; + case SM2_SW_SIGN: + { + test_ctx = sm2_create_sw_sign_test_ctx(setup, optype); + } + break; + case SM2_SW_VERF: + { + test_ctx = sm2_create_sw_verf_test_ctx(setup, optype); + } + break; + case SM2_HW_ENC: + { + test_ctx = sm2_create_hw_enc_test_ctx(setup, optype); + } + break; + case SM2_HW_DEC: + { + test_ctx = sm2_create_hw_dec_test_ctx(setup, optype); + } + break; + case SM2_SW_ENC: + { + test_ctx = sm2_create_sw_enc_test_ctx(setup, optype); + } + break; + case SM2_SW_DEC: + { + test_ctx = sm2_create_sw_dec_test_ctx(setup, optype); + } + break; + case SM2_HW_KG: + { + test_ctx = sm2_create_hw_kg_test_ctx(setup, optype); + } + break; + case SM2_SW_KG: + { + test_ctx = sm2_create_sw_kg_test_ctx(setup, optype); + } + break; + default: + printf("optype = %d error\n", optype); + break; + } + + if (test_ctx) + test_ctx->setup = setup; + + return test_ctx; +} + +int ecdh_generate_key(void *test_ctx, void *tag) +{ + struct ecc_test_ctx *t_c = test_ctx; + int ret = 0; + + if (t_c->op == ECDH_SW_GENERATE) { + if (t_c->is_x25519_x448){ + EVP_PKEY_METHOD *pmeth; + EVP_PKEY_CTX pkey_ctx; + size_t key_sz; + EVP_PKEY pkey; + ECX_KEY ecx; + + memset(&pkey_ctx, 0, sizeof(EVP_PKEY_CTX)); + memset(&pkey, 0, sizeof(EVP_PKEY)); + memset(&ecx, 0, sizeof(ECX_KEY)); + + if (t_c->key_size == 32) { // x25519 + pmeth = EVP_PKEY_meth_find(EVP_PKEY_X25519); + ecx.privkey = x25519_aprikey; + memcpy(ecx.pubkey, x25519_x_param, 32); + } else { // if (t_c->key_size == 56) { // x448 + pmeth = EVP_PKEY_meth_find(EVP_PKEY_X448); + ecx.privkey = x448_aprikey; + memcpy(ecx.pubkey, x448_x_param, 56); + } + pkey.pkey.ecx = &ecx; + pkey_ctx.pkey = &pkey; + pkey_ctx.peerkey = &pkey; + + uint8_t *out_pub_key = calloc(t_c->key_size, sizeof(char)); + + ret = pmeth->derive(&pkey_ctx, out_pub_key, &key_sz); + if (ret == 0) { + HPRE_TST_PRT("%s: pmeth->derive err.\n", __func__); + return -1; + } + #if 0 + int i; + for (i = 0; i < t_c->key_size; i++) { + if (i % 12 == 0) + printf("\n"); + printf("0x%x, ", out_pub_key[i]); + }printf("\n"); + #endif + free(out_pub_key); + } else { + + EC_KEY *ec_key = t_c->priv; + + if (!EC_KEY_generate_key(ec_key)) { + HPRE_TST_PRT("EC_KEY_generate_key fail!\n"); + return -1; + } + //#ifdef DEBUG + ECParameters_print_fp(stdout, ec_key); + EC_KEY_print_fp(stdout, ec_key, 0); + //#endif + } + } else { + struct wcrypto_ecc_op_data *opdata = t_c->opdata; + void* ctx = t_c->priv; +try_again: + ret = wcrypto_do_ecxdh(ctx, opdata, tag); + if (ret == -WD_EBUSY) { + usleep(100); + goto try_again; + } else if (ret) { + HPRE_TST_PRT("wcrypto_do_ecxdh fail!\n"); + return -1; + } + } + + return 0; +} + +int ecdh_compute_key(void *test_ctx, void *tag) +{ + struct ecc_test_ctx *t_c = test_ctx; + int ret = 0; + + if (t_c->op == ECDH_SW_COMPUTE) { + if (t_c->is_x25519_x448){ + EVP_PKEY_METHOD *pmeth; + EVP_PKEY_CTX pkey_ctx; + EVP_PKEY pkey; + ECX_KEY ecx; + size_t key_sz; + int ret; + + memset(&pkey_ctx, 0, sizeof(EVP_PKEY_CTX)); + memset(&pkey, 0, sizeof(EVP_PKEY)); + memset(&ecx, 0, sizeof(ECX_KEY)); + + if (t_c->key_size == 32) { // x25519 + pmeth = EVP_PKEY_meth_find(EVP_PKEY_X25519); + ecx.privkey = x25519_aprikey; + memcpy(ecx.pubkey, x25519_bpubkey, 32); + } else { // if (t_c->key_size == 56) { // x448 + pmeth = EVP_PKEY_meth_find(EVP_PKEY_X448); + ecx.privkey = x448_aprikey; + memcpy(ecx.pubkey, x448_bpubkey, 56); + } + pkey.pkey.ecx = &ecx; + pkey_ctx.pkey = &pkey; + pkey_ctx.peerkey = &pkey; + + uint8_t *out_shared_key = calloc(t_c->key_size, sizeof(char)); + + ret = pmeth->derive(&pkey_ctx, out_shared_key, &key_sz); + if (ret <= 0) { + HPRE_TST_PRT("%s: pmeth->derive err.\n", __func__); + return -1; + } + #if 0 + int i; + for (i = 0; i < t_c->key_size; i++) { + if (i % 12 == 0) + printf("\n"); + printf("0x%x, ", out_shared_key[i]); + }printf("\n"); + #endif + free(out_shared_key); + } else { + struct ecdh_sw_opdata *opdata = t_c->opdata; + EC_KEY *ec_key = t_c->priv; + ret = ECDH_compute_key(opdata->share_key, opdata->share_key_size, + opdata->except_pub_key, ec_key, NULL); + if (ret <= 0) { + HPRE_TST_PRT("ECDH_compute_key fail!\n"); + return -1; + } + opdata->share_key_size = ret; + } +#ifdef DEBUG + //ECParameters_print_fp(stdout, ec_key); + //print_data(opdata->share_key, ret, "openssl share key"); + +#endif + } else { + struct wcrypto_ecc_op_data *opdata = t_c->opdata; + void* ctx = t_c->priv; +try_again: + + ret = wcrypto_do_ecxdh(ctx, opdata, tag); + if (ret == -WD_EBUSY) { + usleep(100); + goto try_again; + } else if (ret) { + HPRE_TST_PRT("wcrypto_do_dh fail!\n"); + return -1; + } +#ifdef DEBUG + //print_data(opdata->pri, opdata->pri_bytes,"hpre share key"); +#endif + } + + return 0; +} + +int ecdsa_sign(void *test_ctx, void *tag) +{ + struct ecc_test_ctx *t_c = test_ctx; + int ret = 0; + + if (t_c->op == ECC_SW_SIGN) { + EC_KEY *ec_key = t_c->priv; + struct ecdh_sw_opdata *opdata = t_c->opdata; + + if (!ECDSA_sign_ex(0, opdata->except_e, opdata->except_e_size, + opdata->sign, &opdata->sign_size, opdata->except_kinv, + opdata->except_rp, ec_key)) { + HPRE_TST_PRT("ECDSA_sign_ex fail!\n"); + return -1; + } + +#ifdef DEBUG + print_data(opdata->sign, opdata->sign_size, "openssl sign"); + ECParameters_print_fp(stdout, ec_key); + EC_KEY_print_fp(stdout, ec_key, 0); +#endif + + } else { + struct wcrypto_ecc_op_data *opdata = t_c->opdata; + void* ctx = t_c->priv; +try_again: + ret = wcrypto_do_ecdsa(ctx, opdata, tag); + if (ret == -WD_EBUSY) { + usleep(100); + goto try_again; + } else if (ret) { + HPRE_TST_PRT("wcrypto_do_ecdsa fail!\n"); + return -1; + } + + if (tag) + return 0; +#ifdef DEBUG + struct wd_dtb *r, *s; + wcrypto_get_ecdsa_sign_out_params(opdata->out, &r, &s); + print_data(r->data, r->dsize, "hpre r"); + print_data(s->data, s->dsize, "hpre s"); +#endif + } + + return 0; +} + +int sm2_sign(void *test_ctx, void *tag) +{ + struct ecc_test_ctx *t_c = test_ctx; + int ret = 0; + + if (t_c->op == SM2_SW_SIGN) { + } else { + struct wcrypto_ecc_op_data *opdata = t_c->opdata; + void* ctx = t_c->priv; +try_again: + ret = wcrypto_do_sm2(ctx, opdata, tag); + if (ret == -WD_EBUSY) { + usleep(100); + goto try_again; + } else if (ret) { + HPRE_TST_PRT("wcrypto_do_sm2 fail!\n"); + return -1; + } + + if (tag) + return 0; +#ifdef DEBUG + //struct wd_dtb *r, *s; + //wcrypto_get_sm2_sign_out_params(opdata->out, &r, &s); + //print_data(r->data, r->dsize, "hpre r"); + //print_data(s->data, s->dsize, "hpre s"); +#endif + } + + return 0; +} + +int ecdsa_verf(void *test_ctx, void *tag) +{ + struct ecc_test_ctx *t_c = test_ctx; + int ret = 0; + + if (t_c->op == ECC_SW_VERF) { + EC_KEY *ec_key = t_c->priv; + struct ecdh_sw_opdata *opdata = t_c->opdata; + + ret = ECDSA_verify(0, opdata->except_e, opdata->except_e_size, + opdata->sign, opdata->sign_size, ec_key); + if (ret != 1) { + HPRE_TST_PRT("ECDSA_verify fail = %d!\n", ret); + return -1; + } + +#ifdef DEBUG + ECParameters_print_fp(stdout, ec_key); + EC_KEY_print_fp(stdout, ec_key, 0); +#endif + + } else { + struct wcrypto_ecc_op_data *opdata = t_c->opdata; + void* ctx = t_c->priv; +try_again: + ret = wcrypto_do_ecdsa(ctx, opdata, tag); + if (ret == -WD_EBUSY) { + usleep(100); + goto try_again; + } else if (ret) { + HPRE_TST_PRT("wcrypto_do_ecdsa fail!\n"); + return -1; + } + + if (tag) + return 0; +#ifdef DEBUG + printf("hpre verf = %d\n", opdata->status); +#endif + } + + return 0; +} + +int sm2_verf(void *test_ctx, void *tag) +{ + struct ecc_test_ctx *t_c = test_ctx; + int ret = 0; + + if (t_c->op == SM2_SW_VERF) { + } else { + struct wcrypto_ecc_op_data *opdata = t_c->opdata; + void* ctx = t_c->priv; +try_again: + ret = wcrypto_do_sm2(ctx, opdata, tag); + if (ret == -WD_EBUSY) { + usleep(100); + goto try_again; + } else if (ret) { + HPRE_TST_PRT("wcrypto_do_sm2 fail!\n"); + return -1; + } + + if (tag) + return 0; +#ifdef DEBUG + printf("hpre verf = %d\n", opdata->status); +#endif + } + + return 0; +} + +int sm2_enc(void *test_ctx, void *tag) +{ + struct ecc_test_ctx *t_c = test_ctx; + int ret = 0; + + if (t_c->op == SM2_SW_ENC) { + } else { + struct wcrypto_ecc_op_data *opdata = t_c->opdata; + void* ctx = t_c->priv; +try_again: + ret = wcrypto_do_sm2(ctx, opdata, tag); + if (ret == -WD_EBUSY) { + usleep(100); + goto try_again; + } else if (ret) { + HPRE_TST_PRT("wcrypto_do_sm2 fail!\n"); + return -1; + } + + if (tag) + return 0; +#ifdef DEBUG + printf("hpre enc = %d\n", opdata->status); +#endif + } + + return 0; +} + +int sm2_dec(void *test_ctx, void *tag) +{ + struct ecc_test_ctx *t_c = test_ctx; + int ret = 0; + + if (t_c->op == SM2_SW_DEC) { + } else { + struct wcrypto_ecc_op_data *opdata = t_c->opdata; + void* ctx = t_c->priv; +try_again: + ret = wcrypto_do_sm2(ctx, opdata, tag); + if (ret == -WD_EBUSY) { + usleep(100); + goto try_again; + } else if (ret) { + HPRE_TST_PRT("wcrypto_do_sm2 fail!\n"); + return -1; + } + + if (tag) + return 0; +#ifdef DEBUG + printf("hpre dec = %d\n", opdata->status); +#endif + } + + return 0; +} + +int sm2_kg(void *test_ctx, void *tag) +{ + struct ecc_test_ctx *t_c = test_ctx; + int ret = 0; + + if (t_c->op == SM2_SW_KG) { + } else { + struct wcrypto_ecc_op_data *opdata = t_c->opdata; + void* ctx = t_c->priv; +try_again: + ret = wcrypto_do_sm2(ctx, opdata, tag); + if (ret == -WD_EBUSY) { + usleep(100); + goto try_again; + } else if (ret) { + HPRE_TST_PRT("wcrypto_do_sm2 fail!\n"); + return -1; + } + + if (tag) + return 0; +#ifdef DEBUG + printf("hpre kg = %d\n", opdata->status); +#endif + } + + return 0; +} + +static int qm_crypto_bin_to_hpre_bin(char *dst, const char *src, + int b_size, int d_size) +{ + int i = d_size - 1; + char *buff = NULL; + char *src_tmp; + int j = 0; + + if (!dst || !src || b_size <= 0 || d_size <= 0) { + WD_ERR("crypto bin to hpre bin params err!\n"); + return -WD_EINVAL; + } + + if (b_size < d_size) { + WD_ERR("crypto bin to hpre bin param data is too long!\n"); + return -WD_EINVAL; + } + + if (b_size == d_size) + return WD_SUCCESS; + + if (dst == src) { + buff = malloc(d_size); + if (!buff) + return -WD_ENOMEM; + memcpy(buff, src, d_size); + src_tmp = buff; + } else { + src_tmp = (void *)src; + } + + for (j = b_size - 1; j >= 0; j--, i--) { + if (i >= 0) + dst[j] = src_tmp[i]; + else + dst[j] = 0; + } + + if (buff) + free(buff); + + return WD_SUCCESS; +} + +int ecc_point1buf(struct wcrypto_ecc_point *in, int ksz, void *buf, int bsz) +{ + struct wd_dtb *x; + int ret = 0; + + if (!buf || !in) + return -1; + + x = &in->x; + + ret = x->dsize; + if (ret > bsz) + return -1; + + memcpy(buf, x->data, x->dsize); + + return ret; +} + +int ecc_point2buf(struct wcrypto_ecc_point *in, int ksz, void *buf, int bsz) +{ + struct wd_dtb *x, *y; + int ret = 0; + + if (!buf || !in) + return -1; + + x = &in->x; + y = &in->y; + + ret = x->dsize + y->dsize; + if (ret > bsz) + return -1; +#ifdef DEBUG + //print_data(x->data, x->dsize, "x"); + //print_data(y->data, y->dsize, "y"); +#endif + memcpy(buf, x->data, x->dsize); + memcpy(buf + x->dsize, y->data, y->dsize); + + return ret; +} + +static int ecc_sign_result_check(struct ecc_test_ctx *test_ctx, __u8 is_async) +{ + struct wcrypto_ecc_op_data *opdata = test_ctx->opdata; + struct wcrypto_ecc_in *ecc_in; + void *ctx = test_ctx->priv; + EC_KEY *ec_key = test_ctx->priv1; + ECDSA_SIG *sig; + struct wd_dtb *r, *s, e; + BIGNUM *b_r, *b_s; + int ret; + + /* openssl verf check*/ + sig = ECDSA_SIG_new(); + if (!sig) { + HPRE_TST_PRT("ECDSA_SIG_new fail!\n"); + return -1; + } + + wcrypto_get_ecdsa_sign_out_params(opdata->out, &r, &s); + b_r = BN_bin2bn((void *)r->data, r->dsize, NULL); + b_s = BN_bin2bn((void *)s->data, s->dsize, NULL); + (void)ECDSA_SIG_set0(sig, b_r, b_s); + ret = ECDSA_do_verify((void*)test_ctx->setup.digest, + test_ctx->setup.digest_size, sig, ec_key); + if (ret != 1) { + HPRE_TST_PRT("openssl verf fail = %d!\n", ret); + print_data(r->data, r->dsize, "r"); + print_data(s->data, s->dsize, "s"); + ECParameters_print_fp(stdout, ec_key); + EC_KEY_print_fp(stdout, ec_key, 0); + ECDSA_SIG_free(sig); + return -1; + } + + ECDSA_SIG_free(sig); + + if (is_async) + return 0; + + /* hpre verf check*/ + e.data = test_ctx->setup.digest; + e.dsize = test_ctx->setup.digest_size; + + ecc_in = wcrypto_new_ecdsa_verf_in(ctx, &e, r, s); + if (!ecc_in) { + HPRE_TST_PRT("%s: new ecc in fail!\n", __func__); + return -1; + } + (void)wcrypto_del_ecc_in(ctx, opdata->in); + + opdata->in = ecc_in; + opdata->op_type = WCRYPTO_ECDSA_VERIFY; +try_again: + ret = wcrypto_do_ecdsa(ctx, opdata, NULL); + if (ret == -WD_EBUSY) { + usleep(100); + goto try_again; + } else if (ret) { + HPRE_TST_PRT("wcrypto_do_ecdsa fail!\n"); + return -1; + } + + return 0; +} + +static int sm2_sign_result_check(struct ecc_test_ctx *test_ctx, __u8 is_async) +{ + struct wcrypto_ecc_op_data *opdata = test_ctx->opdata; + struct wcrypto_ecc_in *ecc_in; + void *ctx = test_ctx->priv; + EVP_MD_CTX *md_ctx = test_ctx->priv1; + EVP_PKEY_CTX *pctx = EVP_MD_CTX_pkey_ctx(md_ctx); + EVP_PKEY *p_key = EVP_PKEY_CTX_get0_pkey(pctx); + EC_KEY *ec_key = EVP_PKEY_get0(p_key); + struct wd_dtb *r, *s, e, id; + char buff[MAX_SIGN_LENS] = {0}; + __u8 is_dgst = 0; + size_t len; + int ret; + + wcrypto_get_sm2_sign_out_params(opdata->out, &r, &s); + memcpy(buff, r->data, r->dsize); + qm_crypto_bin_to_hpre_bin(buff, r->data, r->bsize, r->dsize); + memcpy(buff + 32, s->data, s->dsize); + qm_crypto_bin_to_hpre_bin(buff + 32, s->data, s->bsize, s->dsize); + + if (set_rand != RAND_PARAM) { + /* openssl and hpre rand inconsistent, verify step: + * 1. hpre do verify using hpre sign output + * 2. openssl do verify using hpre sign output + */ + + /* hpre verf check*/ + if (set_msg == MSG_DIGEST) { + e.data = test_ctx->setup.digest; + e.dsize = test_ctx->setup.digest_size; + } else { + e.data = test_ctx->setup.plaintext; + e.dsize = test_ctx->setup.plaintext_size; + id.data = test_ctx->setup.userid; + id.dsize = test_ctx->setup.userid_size; + } + + is_dgst = (set_msg != MSG_DIGEST) ? 0 : 1; + ecc_in = wcrypto_new_sm2_verf_in(ctx, &e, r, s, &id, is_dgst); + if (!ecc_in) { + HPRE_TST_PRT("%s: new ecc in fail!\n", __func__); + return -1; + } + (void)wcrypto_del_ecc_in(ctx, opdata->in); + + opdata->in = ecc_in; + opdata->op_type = WCRYPTO_SM2_VERIFY; + try_again: + ret = wcrypto_do_sm2(ctx, opdata, NULL); + if (ret == -WD_EBUSY) { + usleep(100); + goto try_again; + } else if (ret) { + HPRE_TST_PRT("wcrypto_do_ecdsa fail!\n"); + return -1; + } + + /* openssl verf check*/ + len = hpre_bin_sign_to_evp(buff, buff, 32); + if (set_msg == MSG_DIGEST) { /* msg digest format */ + ret = EVP_PKEY_verify_init(pctx); + if (ret != 1) { + HPRE_TST_PRT("EVP_PKEY_verify_init fail = %d!\n", ret); + return -1; + } + + ret = EVP_PKEY_verify(pctx, (void *)buff, len, test_ctx->setup.digest, + test_ctx->setup.digest_size); + } else { /* msg plaintext format */ + EVP_PKEY_CTX_set1_id(pctx, test_ctx->setup.userid, + test_ctx->setup.userid_size); + EVP_DigestVerifyInit(md_ctx, NULL, get_digest_handle(), NULL, p_key); + EVP_DigestVerifyUpdate(md_ctx, test_ctx->setup.plaintext, + test_ctx->setup.plaintext_size); + ret = EVP_DigestVerifyFinal(md_ctx, (void *)buff, len); + } + if (ret != 1) { + HPRE_TST_PRT("openssl verf fail = %d!\n", ret); + print_data(buff, len, "sign"); + if (set_msg == MSG_DIGEST) + print_data(test_ctx->setup.digest, + test_ctx->setup.digest_size,"digest"); + else + print_data(test_ctx->setup.plaintext, + test_ctx->setup.plaintext_size,"plaintext"); + ECParameters_print_fp(stdout, ec_key); + EC_KEY_print_fp(stdout, ec_key, 0); + return -1; + } + +#ifdef DEBUG + HPRE_TST_PRT("openssl verf pass!\n"); +#endif + if (is_async) + return 0; + + } else { + if (memcmp(test_ctx->cp_sign, buff, test_ctx->cp_sign_size)) { + HPRE_TST_PRT("sm2 op %d mismatch!\n", test_ctx->op); + print_data(buff, 64, "hpre out"); + print_data(test_ctx->cp_sign, test_ctx->cp_sign_size, "openssl out"); + return -1; + } + } + + return 0; +} + +static int sm2_enc_result_check(struct ecc_test_ctx *test_ctx, __u8 is_async) +{ + struct wcrypto_ecc_op_data *opdata = test_ctx->opdata; + struct wcrypto_ecc_in *ecc_in; + struct wcrypto_ecc_out *ecc_out; + void *ctx = test_ctx->priv; + EVP_PKEY_CTX *pctx = test_ctx->priv1; + EVP_PKEY *p_key = EVP_PKEY_CTX_get0_pkey(pctx); + EC_KEY *ec_key = EVP_PKEY_get0(p_key); + struct wcrypto_ecc_point *c1 = NULL; + struct wd_dtb *c2 = NULL, *c3 = NULL, *m = NULL; + char *buf, *ptext; + size_t lens = 0; + __u32 evp_len; + __u32 c3_len; + int ret; + + buf = malloc(MAX_ENC_LENS); + if (!buf) { + HPRE_TST_PRT("malloc out buff fail!\n"); + return -1; + } + + ptext = malloc(MAX_ENC_LENS); + if (!ptext) { + HPRE_TST_PRT("malloc ptext fail!\n"); + return -1; + } + + memset(buf, 0, MAX_ENC_LENS); + memset(ptext, 0, MAX_ENC_LENS); + lens = MAX_ENC_LENS; + wcrypto_get_sm2_enc_out_params(opdata->out, &c1, &c2, &c3); + c3_len = c3->dsize; + if (set_rand != RAND_PARAM) { + /* openssl and hpre rand inconsistent, verify step: + * 1. openssl do verify using hpre sign output + * 2. hpre do verify using hpre sign output + */ + + /* openssl dec check*/ + qm_crypto_bin_to_hpre_bin(c1->x.data, c1->x.data, c1->x.bsize, c1->x.dsize); + qm_crypto_bin_to_hpre_bin(c1->y.data, c1->y.data, c1->y.bsize, c1->y.dsize); + //qm_crypto_bin_to_hpre_bin(c3->data, c3->data, c3->bsize, c3->dsize); + evp_len = sm2_enc_in_bin_to_evp(buf, c1->x.data, c2->dsize, 32, c3->dsize); + ret = EVP_PKEY_decrypt(pctx, (void *)ptext, &lens, (void *)buf, evp_len); + if (ret != 1) { + HPRE_TST_PRT("openssl dec fail = %d!\n", ret); + print_data(buf, evp_len, "dec"); + ECParameters_print_fp(stdout, ec_key); + EC_KEY_print_fp(stdout, ec_key, 0); + return -1; + } + + if (lens != test_ctx->setup.plaintext_size || + memcmp(test_ctx->setup.plaintext, ptext, lens)) { + HPRE_TST_PRT("openssl decrypt mismatch!\n"); + print_data(buf, lens, "openssl dec out"); + return -1; + } + + if (is_async) + return 0; + + /* hpre dec check*/ + c1->x.dsize = 32; + c1->y.dsize = 32; + c3->dsize = c3_len; + ecc_in = wcrypto_new_sm2_dec_in(ctx, c1, c2, c3); + if (!ecc_in) { + HPRE_TST_PRT("%s: new ecc in fail!\n", __func__); + return -1; + } + + ecc_out = wcrypto_new_sm2_dec_out(ctx, c2->dsize); + if (!ecc_out) { + HPRE_TST_PRT("%s: new ecc in fail!\n", __func__); + return -1; + } + + (void)wcrypto_del_ecc_in(ctx, opdata->in); + (void)wcrypto_del_ecc_out(ctx, opdata->out); + opdata->in = ecc_in; + opdata->out = ecc_out; + opdata->op_type = WCRYPTO_SM2_DECRYPT; + + try_again: + ret = wcrypto_do_sm2(ctx, opdata, NULL); + if (ret == -WD_EBUSY) { + usleep(100); + goto try_again; + } else if (ret) { + HPRE_TST_PRT("wcrypto_do_ecdsa fail!\n"); + return -1; + } + + wcrypto_get_sm2_dec_out_params(opdata->out, &m); + if (m->dsize != test_ctx->setup.plaintext_size || memcmp(m->data, test_ctx->setup.plaintext, m->dsize)) { + HPRE_TST_PRT("hpre decrypt mismatch!\n"); + print_data(m->data, m->dsize, "hpre dec out"); + return -1; + } + } else { + memcpy(buf, c1->x.data, c1->x.dsize); + qm_crypto_bin_to_hpre_bin(buf, c1->x.data, c1->x.bsize, c1->x.dsize); + memcpy(buf + 32, c1->y.data, c1->y.dsize); + qm_crypto_bin_to_hpre_bin(buf + 32, c1->y.data, c1->y.bsize, c1->y.dsize); + memcpy(buf + 32 * 2, c3->data, c3->dsize); + //qm_crypto_bin_to_hpre_bin(buf + 32 * 2, c3->data, c3->bsize, c3->dsize); + memcpy(buf + 32 * 2 + c3->dsize, c2->data, c2->dsize); + lens = 32 * 2 + c2->dsize + c3->dsize; + if (lens != test_ctx->cp_enc_size || + memcmp(test_ctx->cp_enc, buf, test_ctx->cp_enc_size)) { + HPRE_TST_PRT("sm2 op %d mismatch!\n", test_ctx->op); + print_data(c1->x.data, c1->x.dsize, "c1 x"); + print_data(c1->y.data, c1->y.dsize, "c1 y"); + print_data(c3->data, c3->dsize, "c3"); + print_data(c2->data, c2->dsize, "c2"); + print_data(buf, lens, "hpre out"); + print_data(test_ctx->cp_enc, test_ctx->cp_enc_size, "openssl out"); + return -1; + } + } + + free(buf); + free(ptext); + return 0; +} + +static int sm2_dec_result_check(struct ecc_test_ctx *test_ctx, __u8 is_async) +{ + struct wcrypto_ecc_op_data *opdata = test_ctx->opdata; + struct wd_dtb *m = NULL; + + wcrypto_get_sm2_dec_out_params(opdata->out, &m); + + if (m->dsize != test_ctx->setup.plaintext_size || + memcmp(test_ctx->setup.plaintext, m->data, m->dsize)) { + HPRE_TST_PRT("sm2 op %d mismatch!\n", test_ctx->op); + print_data(m->data, m->dsize, "hpre out"); + print_data(test_ctx->setup.plaintext, + test_ctx->setup.plaintext_size,"openssl out"); + return -1; + } + + return 0; +} + +static int sm2_kg_result_check(struct ecc_test_ctx *test_ctx, __u8 is_async) +{ + struct ecc_test_ctx_setup *setup = &test_ctx->setup; + struct wcrypto_ecc_op_data *opdata = test_ctx->opdata; + struct wd_dtb *privkey = NULL; + struct wcrypto_ecc_point *pubkey = NULL; + EC_POINT *point_tmp, *ptr; + EVP_PKEY_CTX *pctx; + EVP_PKEY *p_key; + EC_KEY *key_a = NULL; + EC_GROUP *group_a; + BIGNUM *pub, *priv; + char buff[100] = {0x4}; + size_t sig_len = 100; + int ret = -1; + + wcrypto_get_sm2_kg_out_params(opdata->out, &privkey, &pubkey); + + key_a = EC_KEY_new(); + if (!key_a) { + printf("EC_KEY_new err!\n"); + return -1; + } + + group_a = EC_GROUP_new_by_curve_name(EVP_PKEY_SM2); + if(!group_a) { + printf("EC_GROUP_new_by_curve_name err!\n"); + goto free_key; + } + + ret = EC_KEY_set_group(key_a, group_a); + if(ret != 1) { + printf("EC_KEY_set_group err.\n"); + goto free_froup; + } + + /* set prikey */ + priv = BN_bin2bn((void *)privkey->data, privkey->dsize, NULL); + ret = EC_KEY_set_private_key(key_a, priv); + if (ret != 1) { + printf("EC_KEY_set_private_key failed\n"); + goto free_froup; + } + BN_free(priv); + + /* set pub */ + qm_crypto_bin_to_hpre_bin(pubkey->x.data, pubkey->x.data, pubkey->x.bsize, pubkey->x.dsize); + qm_crypto_bin_to_hpre_bin(pubkey->y.data, pubkey->y.data, pubkey->y.bsize, pubkey->y.dsize); + memcpy(&buff[1], pubkey->x.data, 64); + + point_tmp = EC_GROUP_get0_generator(group_a); + + pub = BN_bin2bn((void *)buff, 65, NULL); + ptr = EC_POINT_bn2point(group_a, pub, point_tmp, NULL); + if (!ptr) { + printf("EC_POINT_bn2point failed\n"); + print_data(buff, 65, "hpre key"); + goto free_froup; + } + + ret = EC_KEY_set_public_key(key_a, point_tmp); + if (ret != 1) { + printf("EC_KEY_set_public_key failed\n"); + goto free_froup; + + } + BN_free(pub); + EC_GROUP_free(group_a); + + + p_key = EVP_PKEY_new(); + if (!p_key) { + printf("EVP_PKEY_new failed\n"); + goto free_froup; + } + EVP_PKEY_set1_EC_KEY(p_key, key_a); + EVP_PKEY_set_alias_type(p_key, EVP_PKEY_SM2); + + pctx = EVP_PKEY_CTX_new(p_key, NULL); + if (!pctx) { + printf("EVP_PKEY_CTX_new failed\n"); + goto free_pkey; + } + + ret = EVP_PKEY_sign_init(pctx); + if (ret != 1) { + printf("EVP_PKEY_sign_init fail, ret %d\n", ret); + goto free_pkey_ctx; + } + + ret = EVP_PKEY_sign(pctx, (void *)buff, (void *)&sig_len, setup->digest, + (size_t)setup->digest_size); + if (ret != 1) { + printf("EVP_PKEY_sign fail, ret %d\n", ret); + goto free_pkey_ctx; + } + + ret = EVP_PKEY_verify_init(pctx); + if (ret != 1) { + HPRE_TST_PRT("EVP_PKEY_verify_init fail = %d!\n", ret); + goto free_pkey_ctx; + } + + ret = EVP_PKEY_verify(pctx, (void *)buff, sig_len, setup->digest, setup->digest_size); + if (ret != 1) { + HPRE_TST_PRT("EVP_PKEY_verify fail = %d!\n", ret); + ECParameters_print_fp(stdout, key_a); + EC_KEY_print_fp(stdout, key_a, 0); + goto free_pkey_ctx; + } + + EVP_PKEY_CTX_free(pctx); + EVP_PKEY_free(p_key); + EC_KEY_free(key_a); + + return 0; + +free_pkey_ctx: + EVP_PKEY_CTX_free(pctx); +free_pkey: + EVP_PKEY_free(p_key); +free_froup: + EC_GROUP_free(group_a); +free_key: + EC_KEY_free(key_a); + + return -1; +} + +int ecc_result_check(struct ecc_test_ctx *test_ctx, __u8 is_async) +{ + struct wcrypto_ecc_op_data *opdata = test_ctx->opdata; + void *ctx = test_ctx->priv; + unsigned char *cp_key; + u32 cp_size; + u32 key_size = (wcrypto_get_ecc_key_bits(ctx) + 7) / 8; + void *o_buf; + int ret; + + if (!openssl_check) + return 0; + + if (test_ctx->op == ECDH_HW_GENERATE || + test_ctx->op == ECDH_HW_COMPUTE) { + struct wcrypto_ecc_point *key = NULL; + BIGNUM *tmp; + __u32 out_sz; + + if (test_ctx->op == ECDH_HW_GENERATE) { + cp_key = test_ctx->cp_pub_key; + cp_size = test_ctx->cp_pub_key_size; + } else { + cp_key = test_ctx->cp_share_key; + cp_size = test_ctx->cp_share_key_size; + } + + wcrypto_get_ecxdh_out_params(opdata->out, &key); + if (test_ctx->is_x25519_x448) + o_buf = malloc(key_size); + else + o_buf = malloc(key_size * 2); + + if (!o_buf) { + HPRE_TST_PRT("malloc fail!\n"); + return -1; + } + + if (test_ctx->op == ECDH_HW_GENERATE) { + if (test_ctx->is_x25519_x448) { + ret = ecc_point1buf(key, key_size, o_buf, key_size); + if (ret < 0) { + HPRE_TST_PRT("ecc_point1buf fail!\n"); + free(o_buf); + return -1; + } + } else { + ret = ecc_point2buf(key, key_size, o_buf, key_size * 2); + if (ret < 0) { + HPRE_TST_PRT("ecc_point2buf fail!\n"); + free(o_buf); + return -1; + } + } + out_sz = ret; + tmp = BN_bin2bn(cp_key, key_size, NULL); + ret = BN_bn2bin(tmp, cp_key); + cp_size = ret; + BN_free(tmp); + if (!test_ctx->is_x25519_x448) { + tmp = BN_bin2bn(cp_key + key_size, key_size, NULL); + ret = BN_bn2bin(tmp, cp_key + ret); + cp_size += ret; + BN_free(tmp); + } + + } else { + ret = key->x.dsize; + out_sz = ret; + memcpy(o_buf, key->x.data, ret); + tmp = BN_bin2bn(cp_key, key_size, NULL); + ret = BN_bn2bin(tmp, cp_key); + cp_size = ret; + BN_free(tmp); + } + + if (out_sz != cp_size || memcmp(cp_key, o_buf, cp_size)) { + HPRE_TST_PRT("ecdh op %d mismatch!\n", test_ctx->op); + +//#ifdef DEBUG + struct wcrypto_ecc_key *ecc_key; + struct wd_dtb *p = NULL; + + ecc_key = wcrypto_get_ecc_key(test_ctx->priv); + wcrypto_get_ecc_prikey_params(ecc_key, &p, NULL, NULL, NULL, NULL, NULL); + + print_data(p->data, ECC_PRIKEY_SZ(p->bsize), "prikey"); + if (test_ctx->op == ECDH_HW_GENERATE) + print_data(test_ctx->cp_pub_key, test_ctx->cp_pub_key_size, "cp_pub_key"); + else + print_data(test_ctx->cp_share_key, test_ctx->cp_share_key_size, "cp_share_key"); + print_data(o_buf, out_sz, "hpre out"); + print_data(cp_key, cp_size, "openssl out"); +//#endif + free(o_buf); + return -1; + } + free(o_buf); + } else if (test_ctx->op == ECC_HW_SIGN) { + ret = ecc_sign_result_check(test_ctx, is_async); + if (ret) + return ret; + } else if (test_ctx->op == ECC_HW_VERF || test_ctx->op == SM2_HW_VERF) { + if (opdata->status != 0) { + HPRE_TST_PRT("hpre verf faild = %d!\n", opdata->status); + return -1; + } + } else if (test_ctx->op == SM2_HW_SIGN) { + ret = sm2_sign_result_check(test_ctx, is_async); + if (ret) + return ret; + } else if (test_ctx->op == SM2_HW_ENC) { + ret = sm2_enc_result_check(test_ctx, is_async); + if (ret) + return ret; + } else if (test_ctx->op == SM2_HW_DEC) { + ret = sm2_dec_result_check(test_ctx, is_async); + if (ret) + return ret; + } else if (test_ctx->op == SM2_HW_KG) { + ret = sm2_kg_result_check(test_ctx, is_async); + if (ret) + return ret; + } else {} + + return 0; +} + +void ecc_del_test_ctx(struct ecc_test_ctx *test_ctx) +{ + if (!test_ctx) + return; + + if (ECDH_SW_GENERATE == test_ctx->op) { + if (test_ctx->is_x25519_x448 == 1) { + + } else { + EC_KEY_free(test_ctx->priv); + } + } else if (ECDH_SW_COMPUTE == test_ctx->op) { + struct ecdh_sw_opdata *opdata = test_ctx->opdata; + + if (test_ctx->is_x25519_x448 == 1) { + + } else { + free(opdata->share_key); + free(opdata); + EC_KEY_free(test_ctx->priv); + } + } else if (ECDH_HW_GENERATE == test_ctx->op) { + struct wcrypto_ecc_op_data *opdata = test_ctx->opdata; + + wcrypto_del_ecc_out(test_ctx->priv, opdata->out); + free(opdata); + free(test_ctx->cp_pub_key); + } else if (ECDH_HW_COMPUTE == test_ctx->op) { + struct wcrypto_ecc_op_data *opdata = test_ctx->opdata; + + wcrypto_del_ecc_out(test_ctx->priv, opdata->out); + wcrypto_del_ecc_in(test_ctx->priv, opdata->in); + free(opdata); + free(test_ctx->cp_share_key); + } else if (ECC_SW_SIGN == test_ctx->op) { + struct ecdh_sw_opdata *opdata = test_ctx->opdata; + + free(opdata->sign); + BN_free(opdata->except_kinv); + free(opdata); + EC_KEY_free(test_ctx->priv); + } else if (ECC_HW_SIGN == test_ctx->op) { + struct wcrypto_ecc_op_data *opdata = test_ctx->opdata; + + if (test_ctx->priv1) + EC_KEY_free(test_ctx->priv1); + + wcrypto_del_ecc_out(test_ctx->priv, opdata->out); + wcrypto_del_ecc_in(test_ctx->priv, opdata->in); + free(opdata); + } else if (ECC_SW_VERF == test_ctx->op) { + struct ecdh_sw_opdata *opdata = test_ctx->opdata; + + free(opdata); + EC_KEY_free(test_ctx->priv); + } else if (ECC_HW_VERF == test_ctx->op || SM2_HW_VERF == test_ctx->op) { + struct wcrypto_ecc_op_data *opdata = test_ctx->opdata; + + wcrypto_del_ecc_in(test_ctx->priv, opdata->in); + free(opdata); + } else if (SM2_HW_SIGN == test_ctx->op) { + struct wcrypto_ecc_op_data *opdata = test_ctx->opdata; + + if (test_ctx->priv1) { + EVP_MD_CTX *md_ctx = test_ctx->priv1; + EVP_PKEY_CTX *pctx = EVP_MD_CTX_pkey_ctx(md_ctx); + EVP_PKEY *p_key = EVP_PKEY_CTX_get0_pkey(pctx); + EC_KEY *ec_key = EVP_PKEY_get0(p_key); + + EC_KEY_free(ec_key); + EVP_PKEY_free(p_key); + EVP_PKEY_CTX_free(pctx); + EVP_MD_CTX_free(md_ctx); + } + + wcrypto_del_ecc_out(test_ctx->priv, opdata->out); + wcrypto_del_ecc_in(test_ctx->priv, opdata->in); + free(opdata); + } else if (SM2_SW_SIGN == test_ctx->op) { + } else if (SM2_HW_ENC == test_ctx->op) { + struct wcrypto_ecc_op_data *opdata = test_ctx->opdata; + + if (test_ctx->priv1) { + EVP_PKEY_CTX *pctx = test_ctx->priv1; + EVP_PKEY *p_key = EVP_PKEY_CTX_get0_pkey(pctx); + EC_KEY *ec_key = EVP_PKEY_get0(p_key); + + EC_KEY_free(ec_key); + EVP_PKEY_free(p_key); + EVP_PKEY_CTX_free(pctx); + } + + wcrypto_del_ecc_out(test_ctx->priv, opdata->out); + wcrypto_del_ecc_in(test_ctx->priv, opdata->in); + free(opdata); + } else if (SM2_HW_DEC == test_ctx->op) { + struct wcrypto_ecc_op_data *opdata = test_ctx->opdata; + + wcrypto_del_ecc_out(test_ctx->priv, opdata->out); + wcrypto_del_ecc_in(test_ctx->priv, opdata->in); + free(opdata); + } else if (SM2_HW_KG == test_ctx->op) { + struct wcrypto_ecc_op_data *opdata = test_ctx->opdata; + + if (test_ctx->priv1) { + EVP_PKEY_CTX *pctx = test_ctx->priv1; + EVP_PKEY *p_key = EVP_PKEY_CTX_get0_pkey(pctx); + EC_KEY *ec_key = EVP_PKEY_get0(p_key); + + EC_KEY_free(ec_key); + EVP_PKEY_free(p_key); + EVP_PKEY_CTX_free(pctx); + } + + wcrypto_del_ecc_out(test_ctx->priv, opdata->out); + free(opdata); + } else { + HPRE_TST_PRT("%s: no op %d\n", __func__, test_ctx->op); + } + + free(test_ctx); +} + +static void _ecc_perf_cb(const void *message, void *tag) +{ + struct dh_user_tag_info* pSwData = (struct dh_user_tag_info*)tag; + struct test_hpre_pthread_dt *thread_data = pSwData->thread_data; + struct ecc_test_ctx *test_ctx = pSwData->test_ctx; + //int pid, threadId; + //int ret; + + //pid = pSwData->pid; + //threadId = pSwData->thread_id; + //ret = ecc_result_check(test_ctx); + //if (ret) { + //HPRE_TST_PRT("Proc-%d, %d-TD:%s result mismatching!\n", + //pid, threadId, ecc_op_str[test_ctx->op]); + //} + + thread_data->recv_task_num++; + ecc_del_test_ctx(test_ctx); + free(pSwData); +} + +static void _ecc_cb(const void *message, void *tag) +{ + struct dh_user_tag_info* pSwData = (struct dh_user_tag_info*)tag; + struct timeval start_tval, end_tval; + struct wcrypto_ecc_msg *resp = (void *)message; + int pid, threadId; + float time, speed; + int ret; + static int failTimes = 0; + struct ecc_test_ctx *test_ctx = pSwData->test_ctx; + struct test_hpre_pthread_dt *thread_data = pSwData->thread_data; + + start_tval = thread_data->start_tval; + pid = pSwData->pid; + threadId = pSwData->thread_id; + + thread_data->recv_task_num++; + + if (resp->result != WD_SUCCESS) { + HPRE_TST_PRT("Proc-%d, %d-TD %s %dtimes fail!, status 0x%02x\n", + pid, threadId, ecc_op_str[test_ctx->op], thread_data->send_task_num, resp->result); + goto err; + } + + if (openssl_check) { + ret = ecc_result_check(test_ctx, 1); + if (ret) { + failTimes++; + HPRE_TST_PRT("TD-%d:%s result mismatching!\n", + threadId, ecc_op_str[test_ctx->op]); + } + } + + gettimeofday(&end_tval, NULL); + if (is_allow_print(thread_data->send_task_num, DH_ASYNC_GEN, 1)) { + time = (end_tval.tv_sec - start_tval.tv_sec) * 1000000 + + (end_tval.tv_usec - start_tval.tv_usec); + speed = 1 / (time / thread_data->send_task_num) * 1000 * 1000; + HPRE_TST_PRT("Proc-%d, %d-TD %s %dtimes,%f us, %0.3fps, fail %dtimes(all TD)\n", + pid, threadId, ecc_op_str[test_ctx->op], + thread_data->send_task_num, time, speed, failTimes); + } + +err: + ecc_del_test_ctx(test_ctx); + if (pSwData) + free(pSwData); +} + +void fill_ecdh_param_of_curve(struct wcrypto_ecc_curve *param) +{ + __u32 key_size = (key_bits + 7) / 8; + + if (key_bits == 128) { + param->a.data = ecdh_a_secp128k1; + param->b.data = ecdh_b_secp128k1; + param->p.data = ecdh_p_secp128k1; + param->n.data = ecdh_n_secp128k1; + param->g.x.data = ecdh_g_secp128k1; + param->g.y.data = ecdh_g_secp128k1 + key_size; + } else if (key_bits == 192) { + param->a.data = ecdh_a_secp192k1; + param->b.data = ecdh_b_secp192k1; + param->p.data = ecdh_p_secp192k1; + param->n.data = ecdh_n_secp192k1; + param->g.x.data = ecdh_g_secp192k1; + param->g.y.data = ecdh_g_secp192k1 + key_size; + } else if (key_bits == 256) { + param->a.data = ecdh_a_secp256k1; + param->b.data = ecdh_b_secp256k1; + param->p.data = ecdh_p_secp256k1; + param->n.data = ecdh_n_secp256k1; + param->g.x.data = ecdh_g_secp256k1; + param->g.y.data = ecdh_g_secp256k1 + key_size; + } else if (key_bits == 320) { + param->a.data = ecdh_a_secp320k1; + param->b.data = ecdh_b_secp320k1; + param->p.data = ecdh_p_secp320k1; + param->n.data = ecdh_n_secp320k1; + param->g.x.data = ecdh_g_secp320k1; + param->g.y.data = ecdh_g_secp320k1 + key_size; + } else if (key_bits == 384) { + param->a.data = ecdh_a_secp384k1; + param->b.data = ecdh_b_secp384k1; + param->p.data = ecdh_p_secp384k1; + param->n.data = ecdh_n_secp384k1; + param->g.x.data = ecdh_g_secp384k1; + param->g.y.data = ecdh_g_secp384k1 + key_size; + } else if (key_bits == 521) { + param->a.data = ecdh_a_secp521k1; + param->b.data = ecdh_b_secp521k1; + param->p.data = ecdh_p_secp521k1; + param->n.data = ecdh_n_secp521k1; + param->g.x.data = ecdh_g_secp521k1; + param->g.y.data = ecdh_g_secp521k1 + key_size; + } else { + HPRE_TST_PRT("key_bits %d not find\n", key_bits); + return; + } + + param->a.bsize = key_size; + param->a.dsize = key_size; + param->b.bsize = key_size; + param->b.dsize = key_size; + param->p.bsize = key_size; + param->p.dsize = key_size; + param->n.bsize = key_size; + param->n.dsize = key_size; + param->g.x.bsize = key_size; + param->g.x.dsize = key_size; + param->g.y.bsize = key_size; + param->g.y.dsize = key_size; +} + +static void *_ecc_sys_test_thread(void *data) +{ + struct test_hpre_pthread_dt *pdata = data; + struct dh_user_tag_info *pTag = NULL; + struct ecc_test_ctx *test_ctx; + struct ecc_test_ctx_setup setup = {0}; + struct timeval cur_tval; + enum alg_op_type opType; + float time_used, speed = 0.0; + int thread_num; + cpu_set_t mask; + int pid = getpid(); + int thread_id = (int)syscall(__NR_gettid); + int ret, cpuid; + struct wd_queue *q = NULL; + void *pool = NULL; + void *ctx = NULL; + struct wcrypto_ecc_ctx_setup ctx_setup; + struct wcrypto_ecc_curve param; + __u32 opstr_idx; + __u32 free_num; + + CPU_ZERO(&mask); + cpuid = pdata->cpu_id; + q = (struct wd_queue *)pdata->q; + pool = pdata->pool; + opType = pdata->op_type; + thread_num = pdata->thread_num; + + HPRE_TST_PRT("ecc sys test start!\n"); + + if (performance_test && (!t_times && !t_seconds)) { + HPRE_TST_PRT("t_times or t_seconds err\n"); + return NULL; + } + + if (!q || !pool) { + HPRE_TST_PRT("q or pool null!\n"); + return NULL; + } + + CPU_SET(cpuid, &mask); + if (cpuid) { + ret = pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask); + if (ret < 0) { + HPRE_TST_PRT("Proc-%d, thrd-%d:set affinity fail!\n", + pid, thread_id); + return NULL; + } + HPRE_TST_PRT("Proc-%d, thrd-%d bind to cpu-%d!\n", + pid, thread_id, cpuid); + } + + if (!(!strncmp(q->capa.alg, "x448", 4) || !strncmp(q->capa.alg, "x25519", 5) || + !strncmp(q->capa.alg, "sm2", 3))) { + ret = get_ecc_nid(ecc_curve_name, &setup.nid, &setup.curve_id); + if (ret < 0) { + HPRE_TST_PRT("ecc sys test not find curve!\n"); + return NULL; + } + } + + if (!only_soft) { + memset(&ctx_setup, 0, sizeof(ctx_setup)); + if (performance_test) + ctx_setup.cb = _ecc_perf_cb; + else + ctx_setup.cb = _ecc_cb; + ctx_setup.br.alloc = (void *)wd_alloc_blk; + ctx_setup.br.free = (void *)wd_free_blk; + ctx_setup.br.iova_map = (void *)wd_blk_iova_map; + ctx_setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + ctx_setup.br.get_bufsize = (void *)wd_blksize; + ctx_setup.br.usr = pool; + + if (!(!strncmp(q->capa.alg, "x448", 4) || + !strncmp(q->capa.alg, "x25519", 5) || + !strncmp(q->capa.alg, "sm2", 3))) { + if (!setup.curve_id) { + ctx_setup.cv.type = WCRYPTO_CV_CFG_PARAM; + fill_ecdh_param_of_curve(¶m); + ctx_setup.cv.cfg.pparam = ¶m; + } else { + ctx_setup.cv.type = WCRYPTO_CV_CFG_ID; + ctx_setup.cv.cfg.id = setup.curve_id; + } + } + + ctx_setup.key_bits = key_bits; + + if (set_rand == RAND_CB) { + ctx_setup.rand.cb = hpre_get_rand; + } + + if (set_hash != HASH_NON) { + ctx_setup.hash.cb = hpre_compute_hash; + if (set_hash == HASH_SHA1) { + ctx_setup.hash.type = WCRYPTO_HASH_SHA1; + } else if (set_hash == HASH_SHA224) { + ctx_setup.hash.type = WCRYPTO_HASH_SHA224; + } else if (set_hash == HASH_SHA256) { + ctx_setup.hash.type = WCRYPTO_HASH_SHA256; + } else if (set_hash == HASH_SHA384) { + ctx_setup.hash.type = WCRYPTO_HASH_SHA384; + } else if (set_hash == HASH_SHA512) { + ctx_setup.hash.type = WCRYPTO_HASH_SHA512; + } else if (set_hash == HASH_MD4) { + ctx_setup.hash.type = WCRYPTO_HASH_MD4; + } else if (set_hash == HASH_MD5) { + ctx_setup.hash.type = WCRYPTO_HASH_MD5; + } else { + ctx_setup.hash.type = WCRYPTO_HASH_SM3; + } + } + } + + if ((!strncmp(q->capa.alg, "x25519", 6)) || (!strncmp(q->capa.alg, "x448", 4))) { + if (x_dh_init_test_ctx_setup(&setup, opType)) { // todo + wcrypto_del_ecc_ctx(ctx); + return NULL; + } + } else if (ecc_init_test_ctx_setup(&setup, opType)) { + wcrypto_del_ecc_ctx(ctx); + return NULL; + } + + if (opType == ECDSA_SIGN || opType == ECDSA_ASYNC_SIGN) + setup.op_type = (only_soft) ? ECC_SW_SIGN: ECC_HW_SIGN; + else if (opType == ECDSA_VERF || opType == ECDSA_ASYNC_VERF) + setup.op_type = (only_soft) ? ECC_SW_VERF: ECC_HW_VERF; + else if (opType == SM2_SIGN || opType == SM2_ASYNC_SIGN) + setup.op_type = (only_soft) ? SM2_SW_SIGN: SM2_HW_SIGN; + else if (opType == SM2_VERF || opType == SM2_ASYNC_VERF) + setup.op_type = (only_soft) ? SM2_SW_VERF: SM2_HW_VERF; + else if (opType == SM2_ENC || opType == SM2_ASYNC_ENC) + setup.op_type = (only_soft) ? SM2_SW_ENC: SM2_HW_ENC; + else if (opType == SM2_DEC || opType == SM2_ASYNC_DEC) + setup.op_type = (only_soft) ? SM2_SW_DEC: SM2_HW_DEC; + else if (opType == SM2_KG || opType == SM2_ASYNC_KG) + setup.op_type = (only_soft) ? SM2_SW_KG: SM2_HW_KG; + else if (opType == ECDH_ASYNC_GEN || opType == ECDH_GEN || + opType == X25519_ASYNC_GEN || opType == X25519_GEN || + opType == X448_ASYNC_GEN || opType == X448_GEN) + setup.op_type = (only_soft) ? ECDH_SW_GENERATE: ECDH_HW_GENERATE; + else if (opType == ECDH_ASYNC_COMPUTE || opType == ECDH_COMPUTE || + opType == X25519_ASYNC_COMPUTE || opType == X25519_COMPUTE || + opType == X448_ASYNC_COMPUTE || opType == X448_COMPUTE) + setup.op_type = (only_soft) ? ECDH_SW_COMPUTE: ECDH_HW_COMPUTE; + +new_test_again: + + if (!only_soft) { + ctx = wcrypto_create_ecc_ctx(q, &ctx_setup); + if (!ctx) { + HPRE_TST_PRT("wcrypto_create_ecc_ctx failed\n"); + return NULL; + } + + setup.pool = pool; + setup.q = q; + setup.ctx = ctx; + } + +new_test_with_no_req_ctx: // async test + + test_ctx = ecc_create_test_ctx(setup, opType); + if (!test_ctx) { + HPRE_TST_PRT("ecc_create_test_ctx failed\n"); + return NULL; + } + if (opType >= X25519_GEN && opType <= X448_ASYNC_COMPUTE) + test_ctx->is_x25519_x448 = 1; + + opstr_idx = test_ctx->op; + + do { + if (is_async_test(opType)) { + pTag = malloc(sizeof(struct dh_user_tag_info)); + if (!pTag) { + HPRE_TST_PRT("malloc pTag fail!\n"); + ret = -1; + goto fail_release; + } + + pTag->test_ctx = test_ctx; + pTag->thread_data = pdata; + pTag->pid = pid; + pTag->thread_id = thread_id; + } + + if (opType == ECDSA_ASYNC_SIGN || opType == ECDSA_SIGN) { + if (ecdsa_sign(test_ctx, pTag)) { // todo + ret = -1; + goto fail_release; + } + } else if (opType == SM2_SIGN || opType == SM2_ASYNC_SIGN) { + if (sm2_sign(test_ctx, pTag)) { // todo + ret = -1; + goto fail_release; + } + } else if (opType == ECDSA_VERF || opType == ECDSA_ASYNC_VERF) { + if (ecdsa_verf(test_ctx, pTag)) { // todo + ret = -1; + goto fail_release; + } + } else if (opType == SM2_VERF || opType == SM2_ASYNC_VERF) { + if (sm2_verf(test_ctx, pTag)) { // todo + ret = -1; + goto fail_release; + } + } else if (opType == SM2_ENC || opType == SM2_ASYNC_ENC) { + if (sm2_enc(test_ctx, pTag)) { // todo + ret = -1; + goto fail_release; + } + } else if (opType == SM2_DEC || opType == SM2_ASYNC_DEC) { + if (sm2_dec(test_ctx, pTag)) { // todo + ret = -1; + goto fail_release; + } + } else if (opType == SM2_KG || opType == SM2_ASYNC_KG) { + if (sm2_kg(test_ctx, pTag)) { // todo + ret = -1; + goto fail_release; + } + } else if (opType == ECDH_ASYNC_GEN || opType == ECDH_GEN || + opType == X25519_ASYNC_GEN || opType == X25519_GEN || + opType == X448_ASYNC_GEN || opType == X448_GEN) { + if (ecdh_generate_key(test_ctx, pTag)) { + ret = -1; + goto fail_release; + } + } else if (opType == ECDH_ASYNC_COMPUTE || opType == ECDH_COMPUTE || + opType == X25519_ASYNC_COMPUTE || opType == X25519_COMPUTE || + opType == X448_ASYNC_COMPUTE || opType == X448_COMPUTE) { + if (ecdh_compute_key(test_ctx, pTag)) { + ret = -1; + goto fail_release; + } + } + + pdata->send_task_num++; + if (!is_async_test(opType)) { + + if (only_soft && !performance_test) { + ecc_del_test_ctx(test_ctx); + goto new_test_with_no_req_ctx; + } else if (!performance_test) { + if (ecc_result_check(test_ctx, 0)) { + ret = -1; + goto fail_release; + } + + wd_get_free_blk_num(pool, &free_num); + if (is_allow_print(pdata->send_task_num, opType, thread_num)) { + HPRE_TST_PRT("Proc-%d, %d-TD: %s %uth succ!, free_num = %d.\n", + getpid(), (int)syscall(__NR_gettid), + ecc_op_str[test_ctx->op], pdata->send_task_num, free_num); + } + + ecc_del_test_ctx(test_ctx); + wcrypto_del_ecc_ctx(ctx); + ctx = NULL; + test_ctx = NULL; + + if (is_exit(pdata)) + goto func_test_exit; + + goto new_test_again; + //goto new_test_with_no_req_ctx; + } + } else { + if (is_exit(pdata)) + break; + + goto new_test_with_no_req_ctx; + } + } while(!is_exit(pdata)); + + if (!is_async_test(opType)) + pdata->recv_task_num = pdata->send_task_num; + + if (performance_test) { + gettimeofday(&cur_tval, NULL); + time_used = (float)((cur_tval.tv_sec -pdata->start_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - pdata->start_tval.tv_usec); + + if (t_seconds){ + speed = pdata->send_task_num / time_used * 1000000; + } else if (t_times) { + speed = 1 / (time_used / t_times) * 1000; + } + + HPRE_TST_PRT("Proc-%d, %d-TD: ecc %s send %u task, recv %u task, run %0.1f s at %0.3f ops\n", + pid, thread_id, ecc_op_str[test_ctx->op], + pdata->send_task_num, pdata->recv_task_num, + time_used / 1000000, speed); + } + + /* wait for recv finish */ + while (pdata->send_task_num != pdata->recv_task_num) + usleep(1000); + + ret = 0; + +fail_release: + + if (!only_soft && !is_async_test(opType)) + wcrypto_del_ecc_ctx(test_ctx->priv); + + if (!is_async_test(opType)) + ecc_del_test_ctx(test_ctx); + + if (ret) + HPRE_TST_PRT("%s test fail!\n", ecc_op_str[opstr_idx]); + else + HPRE_TST_PRT("%s test succ!\n", ecc_op_str[opstr_idx]); + + HPRE_TST_PRT("ecc sys test end!\n"); + + return NULL; + +func_test_exit: + + HPRE_TST_PRT("%s test succ!\n", ecc_op_str[opstr_idx]); + + HPRE_TST_PRT("ecc sys test end!\n"); + + return NULL; +} + +static inline int _get_cpu_id(int thr, __u64 core_mask) +{ + __u64 i; + int cnt = 0; + + + for (i = 1; i < 64; i++) { + if (core_mask & (0x1ull << i)) { + if (thr == cnt) + return i; + cnt++; + } + } + + return 0; +} + +static inline int _get_one_bits(__u64 val) +{ + int count = 0; + + while (val) { + if (val % 2 == 1) + count++; + val = val / 2; + } + + return count; +} + +int hpre_test_get_file_size(char *in_file) +{ + int fd = -1, ret; + struct stat file_info; + + if (!in_file) { + HPRE_TST_PRT("para err while try to %s!\n", __func__); + return -EINVAL; + } + fd = open(in_file, O_RDONLY, S_IRUSR) ; + if (fd < 0) { + HPRE_TST_PRT("Get %s file fail!\n", in_file); + return fd; + } + ret = fstat(fd, &file_info); + if (ret < 0) { + close(fd); + HPRE_TST_PRT("fstat file %s fail!\n", in_file); + return -ret; + } + close(fd); + return (int)file_info.st_size; +} + +int hpre_test_read_from_file(__u8 *out, char *in_file, int size) +{ + int fd = -1, bytes_rd; + + if (!out || !size || !in_file) { + HPRE_TST_PRT("para err while try to write file!\n"); + return -EINVAL; + } + + fd = open(in_file, O_RDONLY, S_IRUSR) ; + if (fd < 0) { + HPRE_TST_PRT("Get %s file fail!\n", in_file); + return fd; + } + + bytes_rd = read(fd, out, size); + if (bytes_rd < 0) { + close(fd); + HPRE_TST_PRT("write data to %s file fail!\n", in_file); + return -ENOMEM; + } + close(fd); + + /* to be fixed */ + return bytes_rd; +} + +int hpre_test_write_to_file(__u8 *out, int size, char *out_file, + int handle, int try_close) +{ + int fd = -1, bytes_write; + + if (!out || !size || !out_file) { + HPRE_TST_PRT("para err while try to write file!\n"); + return -EINVAL; + } + + if (handle < 0) { + fd = open(out_file, O_WRONLY | O_CREAT, + S_IRUSR | S_IWUSR); + if (fd < 0) { + HPRE_TST_PRT("create %s file fail!\n", out_file); + return fd; + } + } else + fd = handle; + + bytes_write = write(fd, out, size); + if (bytes_write < 0 || bytes_write < size) { + if (try_close) + close(fd); + HPRE_TST_PRT("write data to %s file fail!\n", out_file); + return -ENOMEM; + } + if (try_close) + close(fd); + + /* to be fixed */ + return fd; +} + +static int test_rsa_key_gen(void *ctx, char *pubkey_file, + char *privkey_file, + char *crt_privkey_file, int is_file) +{ + int ret, bits; + RSA *test_rsa; + BIGNUM *p, *q, *e_value, *n, *e, *d, *dmp1, *dmq1, *iqmp; + //struct wd_dtb *wd_e, *wd_d, *wd_n, *wd_dq, *wd_dp, *wd_qinv, *wd_q, *wd_p; + struct wd_dtb wd_e, wd_d, wd_n, wd_dq, wd_dp, wd_qinv, wd_q, wd_p; + //struct wcrypto_rsa_pubkey *pubkey; + //struct wcrypto_rsa_prikey *prikey; + u32 key_size = key_bits >> 3; + char *tmp; + + memset(&wd_e, 0, sizeof(wd_e)); + memset(&wd_d, 0, sizeof(wd_d)); + memset(&wd_n, 0, sizeof(wd_n)); + memset(&wd_dq, 0, sizeof(wd_dq)); + memset(&wd_dp, 0, sizeof(wd_dp)); + memset(&wd_qinv, 0, sizeof(wd_qinv)); + memset(&wd_q, 0, sizeof(wd_q)); + memset(&wd_p, 0, sizeof(wd_p)); + + bits = wcrypto_rsa_key_bits(ctx); + test_rsa = RSA_new(); + if (!test_rsa || !bits) { + HPRE_TST_PRT("RSA new fail!\n"); + return -ENOMEM; + } + e_value = BN_new(); + if (!e_value) { + RSA_free(test_rsa); + HPRE_TST_PRT("BN new e fail!\n"); + ret = -ENOMEM; + return ret; + } + ret = BN_set_word(e_value, 65537); + if (ret != 1) { + HPRE_TST_PRT("BN_set_word fail!\n"); + ret = -1; + goto gen_fail; + } + + ret = RSA_generate_key_ex(test_rsa, key_bits, e_value, NULL); + if (ret != 1) { + HPRE_TST_PRT("RSA_generate_key_ex fail!\n"); + ret = -1; + goto gen_fail; + } + RSA_get0_key((const RSA *)test_rsa, (const BIGNUM **)&n, + (const BIGNUM **)&e, (const BIGNUM **)&d); + RSA_get0_factors((const RSA *)test_rsa, (const BIGNUM **)&p, + (const BIGNUM **)&q); + RSA_get0_crt_params((const RSA *)test_rsa, (const BIGNUM **)&dmp1, + (const BIGNUM **)&dmq1, (const BIGNUM **)&iqmp); + + //wcrypto_get_rsa_pubkey(ctx, &pubkey); + //wcrypto_get_rsa_pubkey_params(pubkey, &wd_e, &wd_n); + wd_e.bsize = key_size; + wd_e.data = malloc(GEN_PARAMS_SZ(key_size)); + wd_n.bsize = wd_e.bsize; + wd_n.data = wd_e.data + wd_e.bsize; + + wd_e.dsize = BN_bn2bin(e, (unsigned char *)wd_e.data); + if (wd_e.dsize > wd_e.bsize) { + HPRE_TST_PRT("e bn to bin overflow!\n"); + goto gen_fail; + } + wd_n.dsize = BN_bn2bin(n, (unsigned char *)wd_n.data); + if (wd_n.dsize > wd_n.bsize) { + HPRE_TST_PRT("n bn to bin overflow!\n"); + goto gen_fail; + } + + if (wcrypto_set_rsa_pubkey_params(ctx, &wd_e, &wd_n)) + { + HPRE_TST_PRT("set rsa pubkey failed %d!\n", ret); + goto gen_fail; + } + + tmp = malloc(key_size); + if (!tmp) { + HPRE_TST_PRT("failed to malloc!\n"); + goto gen_fail; + } + + memcpy(tmp, wd_e.data, wd_e.dsize); + crypto_bin_to_hpre_bin(wd_e.data, tmp, wd_e.bsize, wd_e.dsize); + memcpy(tmp, wd_n.data, wd_n.dsize); + crypto_bin_to_hpre_bin(wd_n.data, tmp, wd_n.bsize, wd_n.dsize); + wd_e.dsize = key_size; + wd_n.dsize = key_size; + + + if (pubkey_file && is_file) { + ret = hpre_test_write_to_file((unsigned char *)wd_e.data, key_bits >> 2, + pubkey_file, -1, 1); + if (ret < 0) + goto gen_fail; + HPRE_TST_PRT("RSA public key was written to %s!\n", + privkey_file); + } + + if (rsa_key_in) { + memset(rsa_key_in->e, 0, key_size); + memset(rsa_key_in->p, 0, key_size >> 1); + memset(rsa_key_in->q, 0, key_size >> 1); + rsa_key_in->e_size = BN_bn2bin(e, (unsigned char *)rsa_key_in->e); + rsa_key_in->p_size = BN_bn2bin(p, (unsigned char *)rsa_key_in->p); + rsa_key_in->q_size = BN_bn2bin(q, (unsigned char *)rsa_key_in->q); + } + + //wcrypto_get_rsa_prikey(ctx, &prikey); + if (wcrypto_rsa_is_crt(ctx)) { + //wcrypto_get_rsa_crt_prikey_params(prikey, &wd_dq, &wd_dp, &wd_qinv, &wd_q, &wd_p); + wd_dq.bsize = CRT_PARAM_SZ(key_size); + wd_dq.data = malloc(CRT_PARAMS_SZ(key_size)); + wd_dp.bsize = CRT_PARAM_SZ(key_size); + wd_dp.data = wd_dq.data + wd_dq.bsize; + wd_q.bsize = CRT_PARAM_SZ(key_size); + wd_q.data = wd_dp.data + wd_dp.bsize; + wd_p.bsize = CRT_PARAM_SZ(key_size); + wd_p.data = wd_q.data + wd_q.bsize; + wd_qinv.bsize = CRT_PARAM_SZ(key_size); + wd_qinv.data = wd_p.data + wd_p.bsize; + + /* CRT mode private key */ + wd_dq.dsize = BN_bn2bin(dmq1, (unsigned char *)wd_dq.data); + if (wd_dq.dsize > wd_dq.bsize) { + HPRE_TST_PRT("dq bn to bin overflow!\n"); + goto gen_fail; + } + + wd_dp.dsize = BN_bn2bin(dmp1, (unsigned char *)wd_dp.data); + if (wd_dp.dsize > wd_dp.bsize) { + HPRE_TST_PRT("dp bn to bin overflow!\n"); + goto gen_fail; + } + + wd_q.dsize = BN_bn2bin(q, (unsigned char *)wd_q.data); + if (wd_q.dsize > wd_q.bsize) { + HPRE_TST_PRT("q bn to bin overflow!\n"); + goto gen_fail; + } + + wd_p.dsize = BN_bn2bin(p, (unsigned char *)wd_p.data); + if (wd_p.dsize > wd_p.bsize) { + HPRE_TST_PRT("p bn to bin overflow!\n"); + goto gen_fail; + } + + wd_qinv.dsize = BN_bn2bin(iqmp, (unsigned char *)wd_qinv.data); + if (wd_qinv.dsize > wd_qinv.bsize) { + HPRE_TST_PRT("qinv bn to bin overflow!\n"); + goto gen_fail; + } + + if (wcrypto_set_rsa_crt_prikey_params(ctx, &wd_dq, + &wd_dp, &wd_qinv, + &wd_q, &wd_p)) + { + HPRE_TST_PRT("set rsa crt prikey failed %d!\n", ret); + goto gen_fail; + } + + memcpy(tmp, wd_dq.data, wd_dq.dsize); + crypto_bin_to_hpre_bin(wd_dq.data, tmp, wd_dq.bsize, wd_dq.dsize); + memcpy(tmp, wd_dp.data, wd_dp.dsize); + crypto_bin_to_hpre_bin(wd_dp.data, tmp, wd_dp.bsize, wd_dp.dsize); + memcpy(tmp, wd_q.data, wd_q.dsize); + crypto_bin_to_hpre_bin(wd_q.data, tmp, wd_q.bsize, wd_q.dsize); + memcpy(tmp, wd_p.data, wd_p.dsize); + crypto_bin_to_hpre_bin(wd_p.data, tmp, wd_p.bsize, wd_p.dsize); + memcpy(tmp, wd_qinv.data, wd_qinv.dsize); + crypto_bin_to_hpre_bin(wd_qinv.data, tmp, wd_qinv.bsize, wd_qinv.dsize); + wd_dq.dsize = key_size / 2; + wd_dp.dsize = key_size / 2; + wd_q.dsize = key_size / 2; + wd_p.dsize = key_size / 2; + wd_qinv.dsize = key_size / 2; + + if (crt_privkey_file && is_file) { + ret = hpre_test_write_to_file((unsigned char *)wd_dq.data, + (key_bits >> 4) * 5, crt_privkey_file, -1, 0); + if (ret < 0) + goto gen_fail; + ret = hpre_test_write_to_file((unsigned char *)wd_e.data, + (key_bits >> 2), crt_privkey_file, ret, 1); + if (ret < 0) + goto gen_fail; + HPRE_TST_PRT("RSA CRT private key was written to %s!\n", + crt_privkey_file); + } else if (crt_privkey_file && !is_file) { + memcpy(crt_privkey_file, wd_dq.data, (key_bits >> 4) * 5); + memcpy(crt_privkey_file + (key_bits >> 4) * 5, + wd_e.data, (key_bits >> 2)); + } + + } else { + //wcrypto_get_rsa_prikey_params(prikey, &wd_d, &wd_n); + wd_d.bsize = key_size; + wd_d.data = malloc(GEN_PARAMS_SZ(key_size)); + wd_n.bsize =key_size; + wd_n.data = wd_d.data + wd_d.bsize; + + /* common mode private key */ + wd_d.dsize = BN_bn2bin(d, (unsigned char *)wd_d.data); + wd_n.dsize = BN_bn2bin(n, (unsigned char *)wd_n.data); + + if (wcrypto_set_rsa_prikey_params(ctx, &wd_d, &wd_n)) + { + HPRE_TST_PRT("set rsa prikey failed %d!\n", ret); + goto gen_fail; + } + + memcpy(tmp, wd_d.data, wd_d.dsize); + crypto_bin_to_hpre_bin(wd_d.data, tmp, wd_d.bsize, wd_d.dsize); + memcpy(tmp, wd_n.data, wd_n.dsize); + crypto_bin_to_hpre_bin(wd_n.data, tmp, wd_n.bsize, wd_n.dsize); + wd_d.dsize = key_size; + wd_n.dsize = key_size; + + if (privkey_file && is_file) { + ret = hpre_test_write_to_file((unsigned char *)wd_d.data, + (key_size), + privkey_file, -1, 0); + if (ret < 0) + goto gen_fail; + ret = hpre_test_write_to_file((unsigned char *)wd_n.data, + (key_size), + privkey_file, ret, 1); + if (ret < 0) + goto gen_fail; + + ret = hpre_test_write_to_file((unsigned char *)wd_e.data, + (key_size), privkey_file, ret, 1); + if (ret < 0) + goto gen_fail; + HPRE_TST_PRT("RSA common private key was written to %s!\n", + privkey_file); + } else if (privkey_file && !is_file) { + memcpy(privkey_file, wd_d.data, key_size); + memcpy(privkey_file + key_size, wd_n.data, key_size); + memcpy(privkey_file + 2 * key_size, wd_e.data, key_size); + memcpy(privkey_file + 3 * key_size, wd_n.data, key_size); + } + } + + RSA_free(test_rsa); + BN_free(e_value); + + if (wd_e.data) + free(wd_e.data); + + if (wcrypto_rsa_is_crt(ctx)) { + if (wd_dq.data) + free(wd_dq.data); + } else { + if (wd_d.data) + free(wd_d.data); + } + + free(tmp); + + return 0; +gen_fail: + RSA_free(test_rsa); + BN_free(e_value); + + if (wd_e.data) + free(wd_e.data); + + if (wcrypto_rsa_is_crt(ctx)) { + if (wd_dq.data) + free(wd_dq.data); + } else { + if (wd_d.data) + free(wd_d.data); + } + + return ret; +} + +int hpre_test_fill_keygen_opdata(void *ctx, struct wcrypto_rsa_op_data *opdata) +{ + struct wd_dtb *e, *p, *q; + struct wcrypto_rsa_pubkey *pubkey; + struct wcrypto_rsa_prikey *prikey; + struct wd_dtb t_e, t_p, t_q; + + wcrypto_get_rsa_pubkey(ctx, &pubkey); + wcrypto_get_rsa_pubkey_params(pubkey, &e, NULL); + wcrypto_get_rsa_prikey(ctx, &prikey); + + if (wcrypto_rsa_is_crt(ctx)) { + wcrypto_get_rsa_crt_prikey_params(prikey, NULL , NULL, NULL, &q, &p); + } else { + e = &t_e; + p = &t_p; + q = &t_q; + e->data = rsa_key_in->e; + e->dsize = rsa_key_in->e_size; + p->data = rsa_key_in->p; + p->dsize = rsa_key_in->p_size; + q->data = rsa_key_in->q; + q->dsize = rsa_key_in->q_size; + } + + opdata->in = wcrypto_new_kg_in(ctx, e, p, q); + if (!opdata->in) { + HPRE_TST_PRT("create rsa kgen in fail!\n"); + return -ENOMEM; + } + opdata->out = wcrypto_new_kg_out(ctx); + if (!opdata->out) { + HPRE_TST_PRT("create rsa kgen out fail!\n"); + return -ENOMEM; + } + return 0; +} + +static BIGNUM *hpre_bin_to_bn(void *bin, int raw_size) +{ + if (!bin || !raw_size) + return NULL; + + return BN_bin2bn((const unsigned char *)bin, raw_size, NULL); +} + +int hpre_test_result_check(void *ctx, struct wcrypto_rsa_op_data *opdata, void *key) +{ + struct wcrypto_rsa_kg_out *out = (void *)opdata->out; + struct wcrypto_rsa_prikey *prikey; + int ret, keybits, key_size; + void *ssl_out; + BIGNUM *nn; + BIGNUM *e; + RSA *rsa; + + + rsa = RSA_new(); + if (!rsa) { + HPRE_TST_PRT("%s:RSA new fail!\n", __func__); + return -ENOMEM; + } + + wcrypto_get_rsa_prikey(ctx, &prikey); + keybits = wcrypto_rsa_key_bits(ctx); + key_size = keybits >> 3; + if (opdata->op_type == WCRYPTO_RSA_GENKEY) { + if (wcrypto_rsa_is_crt(ctx)) { + struct wd_dtb qinv, dq, dp; + struct wd_dtb *s_qinv, *s_dq, *s_dp; + + wcrypto_get_rsa_crt_prikey_params(prikey, &s_dq, &s_dp, + &s_qinv, NULL, NULL); + wcrypto_get_rsa_kg_out_crt_params(out, &qinv, &dq, &dp); + + if (memcmp(s_qinv->data, qinv.data, s_qinv->dsize)) { + HPRE_TST_PRT("keygen qinv mismatch!\n"); + return -EINVAL; + } + if (memcmp(s_dq->data, dq.data, s_dq->dsize)) { + HPRE_TST_PRT("keygen dq mismatch!\n"); + return -EINVAL; + } + if (memcmp(s_dp->data, dp.data, s_dp->dsize)) { + HPRE_TST_PRT("keygen dp mismatch!\n"); + return -EINVAL; + } + } else { + struct wd_dtb d, n; + struct wd_dtb *s_d, *s_n; + + wcrypto_get_rsa_kg_out_params(out, &d, &n); + + wcrypto_get_rsa_prikey_params(prikey, &s_d, &s_n); + + /* check D */ + if (memcmp(s_n->data, n.data, s_n->dsize)) { + HPRE_TST_PRT("key generate N result mismatching!\n"); + return -EINVAL; + } + if (memcmp(s_d->data, d.data, s_d->dsize)) { + HPRE_TST_PRT("key generate D result mismatching!\n"); + return -EINVAL; + } + } + } else if (opdata->op_type == WCRYPTO_RSA_VERIFY) { + ssl_out = malloc(key_size); + if (!ssl_out) { + HPRE_TST_PRT("malloc ssl out fail!\n"); + return -ENOMEM; + } + if (key) { + nn = hpre_bin_to_bn(key + key_size, + key_size); + if (!nn) { + HPRE_TST_PRT("n bin2bn err!\n"); + return -EINVAL; + } + e = hpre_bin_to_bn(key, key_size); + if (!e) { + HPRE_TST_PRT("e bin2bn err!\n"); + return -EINVAL; + } + ret = RSA_set0_key(rsa, nn, e, NULL); + if (ret <= 0) { + HPRE_TST_PRT("e set0_key err!\n"); + return -EINVAL; + } + } + ret = RSA_public_encrypt(opdata->in_bytes, opdata->in, ssl_out, + rsa, RSA_NO_PADDING); + if (ret != (int)opdata->in_bytes) { + HPRE_TST_PRT("openssl pub encrypto fail!ret=%d\n", ret); + return -ENOMEM; + } + if (!only_soft && memcmp(ssl_out, opdata->out, key_size)) { + HPRE_TST_PRT("pub encrypto result mismatch!\n"); + print_data(ssl_out, opdata->in_bytes, "openssl out"); + print_data(opdata->out, opdata->out_bytes, "hpre out"); + RSA_print_fp(stdout, rsa, 4); + return -EINVAL; + } + free(ssl_out); + } else { + + ssl_out = malloc(key_size); + if (!ssl_out) { + HPRE_TST_PRT("malloc ssl out fail!\n"); + return -ENOMEM; + } + + if (key && wcrypto_rsa_is_crt(ctx)) { + BIGNUM *dp, *dq, *iqmp, *p, *q; + int size = key_size / 2; + + dq = hpre_bin_to_bn(key, size); + if (!dq) { + HPRE_TST_PRT("dq bin2bn err!\n"); + return -EINVAL; + } + dp = hpre_bin_to_bn(key + size, size); + if (!dp) { + HPRE_TST_PRT("dp bin2bn err!\n"); + return -EINVAL; + } + q = hpre_bin_to_bn(key + 2 * size, size); + if (!q) { + HPRE_TST_PRT("q bin2bn err!\n"); + return -EINVAL; + } + p = hpre_bin_to_bn(key + 3 * size, size); + if (!p) { + HPRE_TST_PRT("p bin2bn err!\n"); + return -EINVAL; + } + iqmp = hpre_bin_to_bn(key + 4 * size, size); + if (!iqmp) { + HPRE_TST_PRT("iqmp bin2bn err!\n"); + return -EINVAL; + } + ret = RSA_set0_crt_params(rsa, dp, dq, iqmp); + if (ret <= 0) { + HPRE_TST_PRT("set0_crt_params err!\n"); + return -EINVAL; + } + ret = RSA_set0_factors(rsa, p, q); + if (ret <= 0) { + HPRE_TST_PRT("set0_factors err!\n"); + return -EINVAL; + } + nn = hpre_bin_to_bn(key + 7 * size, key_size); + if (!nn) { + HPRE_TST_PRT("n bin2bn err!\n"); + return -EINVAL; + } + e = hpre_bin_to_bn(key + 5 * size, key_size); + if (!e) { + HPRE_TST_PRT("e bin2bn err!\n"); + return -EINVAL; + } + ret = RSA_set0_key(rsa, nn, e, NULL); + if (ret <= 0) { + HPRE_TST_PRT("rsa set0_key crt err!\n"); + return -EINVAL; + } + + } else if (key && !wcrypto_rsa_is_crt(ctx)) { + BIGNUM *d; + + nn = hpre_bin_to_bn(key + key_size, key_size); + if (!nn) { + HPRE_TST_PRT("n bin2bn err!\n"); + return -EINVAL; + } + d = hpre_bin_to_bn(key, key_size); + if (!d) { + HPRE_TST_PRT("d bin2bn err!\n"); + return -EINVAL; + } + e = hpre_bin_to_bn(key + 2 * key_size, key_size); + if (!e) { + HPRE_TST_PRT("e bin2bn err!\n"); + return -EINVAL; + } + ret = RSA_set0_key(rsa, nn, e, d); + if (ret <= 0) { + HPRE_TST_PRT("d set0_key err!\n"); + return -EINVAL; + } + } + + ret = RSA_private_decrypt(opdata->in_bytes, opdata->in, ssl_out, + rsa, RSA_NO_PADDING); + if (ret != (int)opdata->in_bytes) { + HPRE_TST_PRT("openssl priv decrypto fail!ret=%d\n", ret); + print_data(ssl_out, opdata->in_bytes, "openssl out"); + print_data(opdata->out, opdata->out_bytes, "hpre out"); + RSA_print_fp(stdout, rsa, 4); + return -ENOMEM; + } +#ifdef DEBUG + print_data(opdata->out, 16, "out"); + print_data(opdata->in, 16, "in"); + print_data(ssl_out, 16, "ssl_out"); +#endif + + if (!only_soft && memcmp(ssl_out, opdata->out, ret)) { + HPRE_TST_PRT("prv decrypto result mismatch!\n"); + print_data(ssl_out, opdata->in_bytes, "openssl out"); + print_data(opdata->out, opdata->out_bytes, "hpre out"); + RSA_print_fp(stdout, rsa, 4); + return -EINVAL; + } + free(ssl_out); + + } + + return 0; +} + +int hpre_dh_test(void *c, struct hpre_queue_mempool *pool) +{ + DH *a = NULL, *b = NULL; + int ret, generator = DH_GENERATOR_5; + struct wcrypto_dh_op_data opdata_a; + struct wcrypto_dh_op_data opdata_b; + const BIGNUM *ap = NULL, *ag = NULL, + *apub_key = NULL, *apriv_key = NULL; + const BIGNUM *bp = NULL, *bg = NULL, + *bpub_key = NULL, *bpriv_key = NULL; + unsigned char *ap_bin = NULL, *ag_bin = NULL, + *apub_key_bin = NULL, *apriv_key_bin = NULL; + unsigned char *bp_bin = NULL, *bg_bin = NULL, + *bpub_key_bin = NULL, *bpriv_key_bin = NULL; + unsigned char *abuf = NULL; + struct wd_dtb g; + + __u32 gbytes; + void *tag = NULL; + int key_size, key_bits, bin_size = 0; + + if (!pool) { + HPRE_TST_PRT("pool null!\n"); + return -1; + } + + a = DH_new(); + b = DH_new(); + if (!a || !b) { + HPRE_TST_PRT("New DH fail!\n"); + return -1; + } + + if (wcrypto_dh_is_g2(c)) + generator = DH_GENERATOR_2; + + key_bits = wcrypto_dh_key_bits(c); + key_size = key_bits >> 3; + + /* Alice generates DH parameters */ + ret = DH_generate_parameters_ex(a, key_bits, generator, NULL); + if (!ret) { + HPRE_TST_PRT("DH_generate_parameters_ex fail!\n"); + goto dh_err; + } + + DH_get0_pqg(a, &ap, NULL, &ag); + bp = BN_dup(ap); + bg = BN_dup(ag); + if (!bp || !bg) { + HPRE_TST_PRT("bn dump fail!\n"); + ret = -1; + goto dh_err; + } + + /* Set the same parameters on Bob as Alice :) */ + DH_set0_pqg(b, (BIGNUM *)bp, NULL, (BIGNUM *)bg); + if (!DH_generate_key(a)) { + HPRE_TST_PRT("a DH_generate_key fail!\n"); + ret = -1; + goto dh_err; + } + + DH_get0_key(a, &apub_key, &apriv_key); + ag_bin = wd_alloc_blk(pool); + if (!ag_bin) { + HPRE_TST_PRT("pool alloc ag_bin fail!\n"); + goto dh_err; + } + memset(ag_bin, 0, key_size * 2); + apriv_key_bin = wd_alloc_blk(pool); + if (!apriv_key_bin) { + HPRE_TST_PRT("pool alloc apriv_key_bin fail!\n"); + goto dh_err; + } + memset(apriv_key_bin, 0, key_size * 2); + + /* The hpre_UM tells us key_addr contains xa and p, + * their addr should be together + */ + ap_bin= apriv_key_bin + key_size; + + gbytes = BN_bn2bin(ag, ag_bin); + g.data = (char*)ag_bin; + g.bsize = key_size; + g.dsize = gbytes; + opdata_a.pbytes = BN_bn2bin(ap, ap_bin); + opdata_a.xbytes = BN_bn2bin(apriv_key, apriv_key_bin); + ret = wcrypto_set_dh_g(c, &g); + if (ret) { + HPRE_TST_PRT("Alice wcrypto_set_dh_g fail!\n"); + goto dh_err; + } + opdata_a.x_p = apriv_key_bin; + opdata_a.pri = wd_alloc_blk(pool); + if (!opdata_a.pri) { + HPRE_TST_PRT("pool alloc opdata_a.pri fail!\n"); + goto dh_err; + } + memset(opdata_a.pri, 0, key_size * 2); + + opdata_a.op_type = WCRYPTO_DH_PHASE1; + + /* Alice computes public key */ + ret = wcrypto_do_dh(c, &opdata_a, tag); + if (ret) { + HPRE_TST_PRT("a wcrypto_do_dh fail!\n"); + goto dh_err; + } + + if (openssl_check) { + apub_key_bin = malloc(key_size); + if (!apub_key_bin) { + HPRE_TST_PRT("malloc apub_key_bin fail!\n"); + ret = -ENOMEM; + goto dh_err; + } + ret = BN_bn2bin(apub_key, apub_key_bin); + if (!ret) { + HPRE_TST_PRT("apub_key bn 2 bin fail!\n"); + ret = -1; + goto dh_err; + } + bin_size = ret; + + if (memcmp(apub_key_bin, opdata_a.pri, bin_size)) { + HPRE_TST_PRT("Alice HPRE DH key gen pub mismatch, dsize %d!\n", bin_size); + ret = -EINVAL; +#ifdef DEBUG + print_data(apub_key_bin, key_size, "SOFT"); + print_data(opdata_a.pri, key_size, "HARDWATE"); +#endif + goto dh_err; + } + } + if (!DH_generate_key(b)) { + HPRE_TST_PRT("b DH_generate_key fail!\n"); + ret = -1; + goto dh_err; + } + DH_get0_key(b, &bpub_key, &bpriv_key); + bg_bin = wd_alloc_blk(pool); + if (!bg_bin) { + HPRE_TST_PRT("pool alloc bg_bin fail!\n"); + ret = -1; + goto dh_err; + } + memset(bg_bin, 0, key_size * 2); + + bpriv_key_bin= wd_alloc_blk(pool); + if (!bpriv_key_bin) { + HPRE_TST_PRT("pool alloc bpriv_key_bin fail!\n"); + ret = -1; + goto dh_err; + } + memset(bpriv_key_bin, 0, key_size * 2); + bp_bin = bpriv_key_bin + key_size; + gbytes = BN_bn2bin(bg, bg_bin); + g.data = (char*)bg_bin; + g.bsize = gbytes; + g.dsize = key_size; + ret = wcrypto_set_dh_g(c, &g); + if (ret) { + HPRE_TST_PRT("bob wcrypto_set_dh_g fail!\n"); + goto dh_err; + } + opdata_b.pbytes = BN_bn2bin(bp, bp_bin); + opdata_b.xbytes = BN_bn2bin(bpriv_key, bpriv_key_bin); + opdata_b.x_p = bpriv_key_bin; + opdata_b.pri = wd_alloc_blk(pool); + if (!opdata_b.pri) { + HPRE_TST_PRT("pool alloc opdata_b.pri fail!\n"); + ret = -1; + goto dh_err; + } + memset(opdata_b.pri, 0, key_size * 2); + opdata_b.op_type = WCRYPTO_DH_PHASE1; + + /* Bob computes public key */ + ret = wcrypto_do_dh(c, &opdata_b, tag); + if (ret) { + HPRE_TST_PRT("b wcrypto_do_dh fail!\n"); + goto dh_err; + } + if (openssl_check) { + bpub_key_bin = malloc(key_size); + if (!bpub_key_bin) { + HPRE_TST_PRT("malloc bpub_key_bin fail!\n"); + ret = -1; + goto dh_err; + } + ret = BN_bn2bin(bpub_key, bpub_key_bin); + if (!ret) { + HPRE_TST_PRT("bpub_key bn 2 bin fail!\n"); + goto dh_err; + } + bin_size = ret; + + if (memcmp(bpub_key_bin, opdata_b.pri, bin_size)) { + HPRE_TST_PRT("Bob HPRE DH key gen pub mismatch, dsize %d!\n", bin_size); + ret = -EINVAL; +#ifdef DEBUG + print_data(bpub_key_bin, key_size, "SOFT"); + print_data(opdata_b.pri, key_size, "HARDWATE"); +#endif + goto dh_err; + } + } + /* Alice computes private key with OpenSSL */ + abuf = malloc(key_size); + if (!abuf) { + HPRE_TST_PRT("malloc abuf fail!\n"); + ret = -ENOMEM; + goto dh_err; + } + + memset(abuf, 0, key_size); + if (openssl_check) { + ret = DH_compute_key(abuf, bpub_key, a); + if (!ret) { + HPRE_TST_PRT("DH_compute_key fail!\n"); + ret = -1; + goto dh_err; + } + bin_size = ret; + } + + /* Alice computes private key with HW accelerator */ + memset(ag_bin, 0, key_size * 2); + memset(apriv_key_bin, 0, key_size * 2); + ap_bin = apriv_key_bin + key_size; + memset(opdata_a.pri, 0, key_size * 2); + + opdata_a.pvbytes = BN_bn2bin(bpub_key, ag_bin); + opdata_a.pv = ag_bin;/* bob's public key here */ + opdata_a.pbytes = BN_bn2bin(ap, ap_bin); + opdata_a.xbytes = BN_bn2bin(apriv_key, apriv_key_bin); + opdata_a.x_p = apriv_key_bin; + opdata_a.pri = wd_alloc_blk(pool); + if (!opdata_a.pri) { + HPRE_TST_PRT("pool alloc opdata_a.pri fail!\n"); + ret = -1; + goto dh_err; + } + memset(opdata_a.pri, 0, key_size * 2); + opdata_a.op_type = WCRYPTO_DH_PHASE2; + + /* Alice computes private key with HPRE */ + ret = wcrypto_do_dh(c, &opdata_a, tag); + if (ret) { + HPRE_TST_PRT("a wcrypto_do_dh fail!\n"); + goto dh_err; + } + if (openssl_check) { + if (memcmp(abuf, opdata_a.pri, bin_size)) { + HPRE_TST_PRT("Alice HPRE DH gen privkey mismatch!\n"); + ret = -EINVAL; +#ifdef DEBUG + print_data(abuf, key_size, "SOFT"); + print_data(opdata_a.pri, key_size, "HARDWATE"); +#endif + goto dh_err; + } + } + + ret = 0; + HPRE_TST_PRT("HPRE DH generate key sucessfully!\n"); + dh_err: + DH_free(a); + DH_free(b); + if (ag_bin) + wd_free_blk(pool, ag_bin); + if (apriv_key_bin) + wd_free_blk(pool, apriv_key_bin); + if (opdata_a.pri) + wd_free_blk(pool, opdata_a.pri); + + if (bg_bin) + wd_free_blk(pool, bg_bin); + if (bpriv_key_bin) + wd_free_blk(pool, bpriv_key_bin); + if (opdata_b.pri) + wd_free_blk(pool, opdata_b.pri); + + if (apub_key_bin) + free(apub_key_bin); + if (bpub_key_bin) + free(bpub_key_bin); + if (abuf) + free(abuf); + return ret; +} + +#ifdef RSA_OP_DEBUG +int hpre_test_rsa_op(enum alg_op_type op_type, void *c, __u8 *in, + int in_size, __u8 *out, __u8 *key) +{ + struct wcrypto_rsa_op_data opdata; + int ret, move; + void *tag; + int key_bits, key_size; + + key_bits = wcrypto_dh_key_bits(c); + key_size = key_bits >> 3; + if (op_type == RSA_KEY_GEN) { + /* use openSSL generate key and store them to files at first */ + ret = test_rsa_key_gen(c, (char *)in, + (char *)out, (char *)key, 1); + if (ret < 0) + return ret; + } else { + struct wcrypto_rsa_pubkey pubkey; + struct wcrypto_rsa_prikey prvkey; + + if (!key) + goto try_format_input; + memset(&pubkey, 0, sizeof(pubkey)); + memset(&prvkey, 0, sizeof(prvkey)); + if (op_type == RSA_PUB_EN) { + pubkey.e = key; + pubkey.n = key + (key_bits >> 3); + ret = wd_set_rsa_pubkey(c, &pubkey); + if (ret) { + HPRE_TST_PRT("wd_set_rsa_pubkey fail!\n"); + return ret; + } + } + if (op_type == RSA_PRV_DE && wcrypto_rsa_is_crt(c)) { + prvkey.pkey2.dq = key; + prvkey.pkey2.dp = key + (key_bits >> 4); + prvkey.pkey2.q = key + (key_bits >> 3); + prvkey.pkey2.p = key + (key_bits >> 4) * 3; + prvkey.pkey2.qinv = key + (key_bits >> 2); + ret = wd_set_rsa_prikey(c, &prvkey); + if (ret) { + HPRE_TST_PRT("wd_set_rsa_prikey crt fail!\n"); + return ret; + } + } else if (op_type == RSA_PRV_DE && !wcrypto_rsa_is_crt(c)) { + prvkey.pkey1.d = key; + prvkey.pkey1.n = key + (key_bits >> 3); + ret = wd_set_rsa_prikey(c, &prvkey); + if (ret) { + HPRE_TST_PRT("wd_set_rsa_prikey fail!\n"); + return ret; + } + } +try_format_input: + /* Padding zero in this sample */ + if (in_size < key_size && op_type == RSA_PUB_EN) { + move = key_size - in_size; + memmove(in + move, in, in_size); + memset(in, 0, move); + } + } + + /* always key size bytes input */ + opdata.in_bytes = key_size; + if (op_type == RSA_PRV_DE) { + opdata.op_type = WCRYPTO_RSA_SIGN; + } else if (op_type == RSA_PUB_EN) { + opdata.op_type = WCRYPTO_RSA_VERIFY; + } else if (op_type == RSA_KEY_GEN) { + opdata.op_type = WCRYPTO_RSA_GENKEY; + } else { + ret = -EINVAL; + goto type_err; + } + if (op_type == RSA_KEY_GEN) { + ret = hpre_test_fill_keygen_opdata(c, &opdata); + if (ret) + goto type_err; + } else { + opdata.in = in; + opdata.out = out; + opdata.out_bytes = key_size; + } + tag = NULL; + ret = wcrypto_do_rsa(c, &opdata, tag); + if (ret) + goto type_err; + if (openssl_check) { + ret = hpre_test_result_check(c, &opdata, key); + if (ret) + goto type_err; + else if (opdata->op_type == WCRYPTO_RSA_GENKEY) + HPRE_TST_PRT("HPRE hardware key generate successfully!\n"); + } else if (!openssl_check && op_type == RSA_KEY_GEN) { + HPRE_TST_PRT("HPRE hardware key generate finished!\n"); + } + if (op_type == RSA_PRV_DE) { + __u8 *tmp = opdata.out; + + move = 0; + while (!tmp[move]) + move++; + opdata.out_bytes -= move; + memmove(out, out + move, opdata.out_bytes); + } + return (int)opdata.out_bytes; +type_err: + return ret; +} +#endif + +int hpre_sys_qmng_test(int thread_num) +{ + int pid = getpid(), i = 0, ret; + int thread_id = (int)syscall(__NR_gettid); + struct wd_queue q; + + memset((void *)&q, 0, sizeof(q)); + q.capa.alg = "rsa"; + + while (1) { + ret = wd_request_queue(&q); + if (ret) { + HPRE_TST_PRT("Proc-%d, thrd-%d:request queue t-%d fail!\n", + pid, thread_id, i); + return ret; + } + i++; + if (is_allow_print(i, HPRE_ALG_INVLD_TYPE, thread_num)) + HPRE_TST_PRT("Proc-%d, %d-TD request %dQs at %dnode\n", + pid, thread_id, i, wd_get_node_id(&q)); + usleep(1); + wd_release_queue(&q); + } + return 0; +} + +int hpre_sys_func_test(struct test_hpre_pthread_dt * pdata) +{ + int pid = getpid(), ret = 0, i = 0; + int thread_id = (int)syscall(__NR_gettid); + struct wcrypto_rsa_ctx_setup setup; + struct wcrypto_rsa_op_data opdata; + void *ctx = NULL; + void *tag = NULL; + struct wd_queue *q = pdata->q; + void *key_info = NULL; + struct timeval cur_tval; + float time, speed; + int key_size = key_bits >> 3; + char m[] = {0x54, 0x85, 0x9b, 0x34, 0x2c, 0x49, 0xea, 0x2a}; + + if (performance_test && (!t_times && !t_seconds)) { + HPRE_TST_PRT("t_times or t_seconds err\n"); + return -1; + } + +new_test_again: + + memset(&setup, 0, sizeof(setup)); + memset(&opdata, 0, sizeof(opdata)); + setup.key_bits = key_bits; + setup.br.alloc = (void *)wd_alloc_blk; + setup.br.free = (void *)wd_free_blk; + setup.br.iova_map = (void *)wd_blk_iova_map; + setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + setup.br.get_bufsize = (void *)wd_blksize; + setup.br.usr = pdata->pool; + + if (!strcmp(g_mode, "-crt")) + setup.is_crt = true; + else + setup.is_crt = false; + + ctx = wcrypto_create_rsa_ctx(q, &setup); + if (!ctx) { + HPRE_TST_PRT("Proc-%d, %d-TD:create %s ctx fail!\n", + pid, thread_id, q->capa.alg); + ret = -EINVAL; + goto fail_release; + } + + /* Just make sure memory size is enough */ + key_info = malloc(key_size * 16); + if (!key_info) { + HPRE_TST_PRT("thrd-%d:malloc key!\n", thread_id); + goto fail_release; + } + + rsa_key_in = malloc(2 * key_size + sizeof(struct hpre_rsa_test_key_in)); + if (!rsa_key_in) { + HPRE_TST_PRT("thrd-%d:malloc err!\n", thread_id); + goto fail_release; + } + + rsa_key_in->e = rsa_key_in + 1; + rsa_key_in->p = rsa_key_in->e + key_size; + rsa_key_in->q = rsa_key_in->p + (key_size >> 1); + + memset(key_info, 0, key_size * 16); + ret = test_rsa_key_gen(ctx, NULL, key_info, key_info, 0); + if (ret) { + HPRE_TST_PRT("thrd-%d:Openssl key gen fail!\n", thread_id); + goto fail_release; + } + + /* always key size bytes input */ + opdata.in_bytes = key_size; + if (pdata->op_type == RSA_KEY_GEN) { + opdata.op_type = WCRYPTO_RSA_GENKEY; + } else if (pdata->op_type == RSA_PUB_EN) { + opdata.op_type = WCRYPTO_RSA_VERIFY; + } else if (pdata->op_type == RSA_PRV_DE) { + opdata.op_type = WCRYPTO_RSA_SIGN; + } else { + HPRE_TST_PRT("thrd-%d:optype=%d err!\n", + thread_id, pdata->op_type); + goto fail_release; + } + + if (opdata.op_type == WCRYPTO_RSA_GENKEY) { + ret = hpre_test_fill_keygen_opdata(ctx, &opdata); + if (ret){ + HPRE_TST_PRT("fill key gen opdata fail!\n"); + goto fail_release; + } + } else { + opdata.in = wd_alloc_blk(pdata->pool); + if (!opdata.in) { + HPRE_TST_PRT("alloc in buffer fail!\n"); + goto fail_release; + } + memset(opdata.in, 0, opdata.in_bytes); + memcpy(opdata.in + key_size - sizeof(m), m, sizeof(m)); + opdata.out = wd_alloc_blk(pdata->pool); + if (!opdata.out) { + HPRE_TST_PRT("alloc out buffer fail!\n"); + goto fail_release; + } + opdata.out_bytes = key_size; + } + + do { + if (!only_soft) { + ret = wcrypto_do_rsa(ctx, &opdata, tag); + if (ret || opdata.status) { + HPRE_TST_PRT("Proc-%d, T-%d:hpre %s %dth status=%d fail!\n", + pid, thread_id, + rsa_op_str[opdata.op_type], i, opdata.status); + goto fail_release; + } + } + + pdata->send_task_num++; + i++; + if (openssl_check) { + void *check_key; + + if (opdata.op_type == WCRYPTO_RSA_SIGN) + check_key = key_info; + if (opdata.op_type == WCRYPTO_RSA_VERIFY) + if (wcrypto_rsa_is_crt(ctx)) + check_key = key_info + 5 * (key_bits >> 4); + else + check_key = key_info + 2 * key_size; + else + check_key = key_info; + ret = hpre_test_result_check(ctx, &opdata, check_key); + if (ret) { + HPRE_TST_PRT("P-%d,T-%d:hpre %s %dth mismth\n", + pid, thread_id, + rsa_op_str[opdata.op_type], i); + goto fail_release; + } + else { + if (opdata.op_type == WCRYPTO_RSA_GENKEY) { + if (is_allow_print(i, WCRYPTO_RSA_GENKEY, pdata->thread_num)) + HPRE_TST_PRT("HPRE hardware key generate successfully!\n"); + } + } + } + + /* clean output buffer remainings in the last time operation */ + if (opdata.op_type == WCRYPTO_RSA_GENKEY) { + char *data; + int len; + + len = wcrypto_rsa_kg_out_data((void *)opdata.out, &data); + if (len < 0) { + HPRE_TST_PRT("wd rsa get key gen out data fail!\n"); + goto fail_release; + } + memset(data, 0, len); + } else { +#ifdef DEBUG + print_data(opdata.out, 16, "out"); +#endif + } + if (is_allow_print(i, pdata->op_type, pdata->thread_num)) { + gettimeofday(&cur_tval, NULL); + time = (float)((cur_tval.tv_sec - pdata->start_tval.tv_sec) * 1000000 + + (cur_tval.tv_usec - pdata->start_tval.tv_usec)); + speed = 1 / (time / i) * 1000; + HPRE_TST_PRT("Proc-%d, %d-TD %s %dtimes,%0.0fus, %0.3fkops\n", + pid, thread_id, rsa_op_str[opdata.op_type], + i, time, speed); + } + + if (!performance_test && !only_soft) { + if (opdata.op_type == WCRYPTO_RSA_GENKEY) { + if (opdata.in) + wcrypto_del_kg_in(ctx, opdata.in); + if (opdata.out) + wcrypto_del_kg_out(ctx, opdata.out); + } else { + if (opdata.in) + wd_free_blk(pdata->pool, opdata.in); + if (opdata.out) + wd_free_blk(pdata->pool, opdata.out); + } + + if (ctx) + wcrypto_del_rsa_ctx(ctx); + + if (rsa_key_in) + free(rsa_key_in); + + if (key_info) + free(key_info); + + goto new_test_again; + } + }while(!is_exit(pdata)); + + pdata->recv_task_num = pdata->send_task_num; + + if (performance_test) { + gettimeofday(&cur_tval, NULL); + time = (float)((cur_tval.tv_sec -pdata->start_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - pdata->start_tval.tv_usec); + + if (t_seconds) { + speed = pdata->send_task_num / time * 1000000; + HPRE_TST_PRT("Proc-%d, %d-TD: dh do %s send %u task, recv %u task, run %0.1f s at %0.3f ops\n", + pid, thread_id, rsa_op_str_perf[opdata.op_type], + pdata->send_task_num, pdata->recv_task_num, + time / 1000000, speed); + } else if (t_times) { + speed = 1 / (time / t_times) * 1000; + HPRE_TST_PRT("\r\nPID(%d)-thread-%d:%s CRT mode %dbits %s time %0.0f us, pkt len =" + " %d bytes, %0.3f Kops\n", getpid(), (int)syscall(__NR_gettid), "rsa", + key_bits, rsa_op_str_perf[opdata.op_type], time, key_bits / 8, speed); + } + } + +fail_release: + if (opdata.op_type == WCRYPTO_RSA_GENKEY) { + if (opdata.in) + wcrypto_del_kg_in(ctx, opdata.in); + if (opdata.out) + wcrypto_del_kg_out(ctx, opdata.out); + } else { + if (opdata.in) + wd_free_blk(pdata->pool, opdata.in); + if (opdata.out) + wd_free_blk(pdata->pool, opdata.out); + } + if (ctx) + wcrypto_del_rsa_ctx(ctx); + if (key_info) + free(key_info); + if (rsa_key_in) + free(rsa_key_in); + + + return ret; +} + +void *_hpre_rsa_sys_test_thread(void *data) +{ + int ret, cpuid; + struct test_hpre_pthread_dt *pdata = data; + cpu_set_t mask; + enum alg_op_type op_type; + int thread_num; + int pid = getpid(); + int thread_id = (int)syscall(__NR_gettid); + + CPU_ZERO(&mask); + cpuid = pdata->cpu_id; + op_type = pdata->op_type; + thread_num = pdata->thread_num; + CPU_SET(cpuid, &mask); + if (cpuid) { + ret = pthread_setaffinity_np(pthread_self(), + sizeof(mask), &mask); + if (ret < 0) { + HPRE_TST_PRT("Proc-%d, thrd-%d:set affinity fail!\n", + pid, thread_id); + return NULL; + } + HPRE_TST_PRT("Proc-%d, thrd-%d bind to cpu-%d!\n", + pid, thread_id, cpuid); + } + if (op_type == HPRE_ALG_INVLD_TYPE) { + ret = hpre_sys_qmng_test(thread_num); + if (ret) + return NULL; + } else { + ret = hpre_sys_func_test(pdata); + if (ret) + return NULL; + } + return NULL; +} + +static int hpre_sys_test(int thread_num, __u64 lcore_mask, + __u64 hcore_mask, enum alg_op_type op_type, + char *dev_path, unsigned int node_msk) +{ + void **pool; + struct wd_blkpool_setup setup; + int i, ret, cnt = 0, j; + int block_num = 512; + struct wd_queue *q; + int h_cpuid, qidx; + + q = malloc(q_num * sizeof(struct wd_queue)); + if (!q) { + HPRE_TST_PRT("malloc q memory fail!\n"); + return -ENOMEM; + } + memset(q, 0, q_num * sizeof(struct wd_queue)); + + /* create pool for every queue */ + pool = malloc(q_num * sizeof(pool)); + if (!pool) { + HPRE_TST_PRT("malloc pool memory fail!\n"); + return -ENOMEM; + } + + memset(pool, 0, q_num * sizeof(pool)); + + if (op_type != HPRE_ALG_INVLD_TYPE) { + for (j = 0; j < q_num; j++) { + if (op_type > MAX_RSA_ASYNC_TYPE && op_type < MAX_DH_TYPE) + q[j].capa.alg = "dh"; + else if (op_type > HPRE_ALG_INVLD_TYPE && op_type < MAX_RSA_ASYNC_TYPE) + q[j].capa.alg = "rsa"; + else if (op_type > MAX_DH_TYPE && op_type < MAX_ECDH_TYPE) + q[j].capa.alg = "ecdh"; + else if (op_type > MAX_ECDH_TYPE && op_type < MAX_ECDSA_TYPE) + q[j].capa.alg = "ecdsa"; + else if (op_type >= X25519_GEN && op_type <= X25519_ASYNC_COMPUTE) + q[j].capa.alg = "x25519"; + else if (op_type >= X448_GEN && op_type <= X448_ASYNC_COMPUTE) + q[j].capa.alg = "x448"; + else + q[j].capa.alg = "sm2"; + + if (dev_path) + strncpy(q[j].dev_path, dev_path, sizeof(q[j].dev_path)); + q[j].node_mask = node_msk; + ret = wd_request_queue(&q[j]); + if (ret) { + HPRE_TST_PRT("request queue %d fail!\n", j); + return ret; + } + memset(&setup, 0, sizeof(setup)); + if (!strncmp(q[j].capa.alg, "dh", 2)) + setup.block_size = key_bits >> 2; + else if (!strncmp(q[j].capa.alg, "rsa", 3)) + setup.block_size = (key_bits >> 4) * 20; + else if (!strncmp(q[j].capa.alg, "ecdh", 4) || + !strncmp(q[j].capa.alg, "x25519", 6) || + !strncmp(q[j].capa.alg, "x448", 4) || + !strncmp(q[j].capa.alg, "sm2", 3) || + !strncmp(q[j].capa.alg, "ecdsa", 5)) + setup.block_size = get_ecc_min_blocksize(key_bits) * 8; + + if (!strncmp(q[j].capa.alg, "sm2", 3)) + setup.block_size = BITS_TO_BYTES(set_plaintext_len) + get_ecc_min_blocksize(key_bits) * 8; + + setup.block_num = block_num; + setup.align_size = 64; + + pool[j] = wd_blkpool_create(&q[j], &setup); + if (!pool[j]) { + HPRE_TST_PRT("%s(): create %dth pool fail!\n", __func__, j); + return -ENOMEM; + } + } + } + if (_get_one_bits(lcore_mask) > 0) + cnt = _get_one_bits(lcore_mask); + else if (_get_one_bits(lcore_mask) == 0 && + _get_one_bits(hcore_mask) == 0) + cnt = thread_num; + for (i = 0; i < cnt; i++) { + qidx = i / ctx_num_per_q; + test_thrds_data[i].pool = pool[qidx]; + test_thrds_data[i].q = &q[qidx]; + test_thrds_data[i].thread_num = thread_num; + test_thrds_data[i].op_type = op_type; + test_thrds_data[i].cpu_id = _get_cpu_id(i, lcore_mask); + gettimeofday(&test_thrds_data[i].start_tval, NULL); + ret = pthread_create(&system_test_thrds[i], NULL, + _hpre_sys_test_thread, &test_thrds_data[i]); + if (ret) { + HPRE_TST_PRT("Create %dth thread fail!\n", i); + return ret; + } + } + for (i = 0; i < thread_num - cnt; i++) { + h_cpuid = _get_cpu_id(i, hcore_mask); + if (h_cpuid > 0) + h_cpuid += 64; + + qidx = (i + cnt) / ctx_num_per_q; + test_thrds_data[i + cnt].pool = pool[qidx]; + test_thrds_data[i + cnt].q = &q[qidx]; + test_thrds_data[i + cnt].thread_num = thread_num; + test_thrds_data[i + cnt].op_type = op_type; + test_thrds_data[i + cnt].cpu_id = h_cpuid; + gettimeofday(&test_thrds_data[i + cnt].start_tval, NULL); + ret = pthread_create(&system_test_thrds[i + cnt], NULL, + _hpre_sys_test_thread, &test_thrds_data[i + cnt]); + if (ret) { + HPRE_TST_PRT("Create %dth thread fail!\n", i); + return ret; + } + } + for (i = 0; i < thread_num; i++) { + ret = pthread_join(system_test_thrds[i], NULL); + if (ret) { + HPRE_TST_PRT("Join %dth thread fail!\n", i); + return ret; + } + } + + if (op_type != HPRE_ALG_INVLD_TYPE) { + for (j = 0; j < q_num; j++) { + wd_release_queue(&q[j]); + } + } + + return 0; +} + +static void *_rsa_async_poll_test_thread(void *data) +{ + struct test_hpre_pthread_dt *pdata = data; + struct wd_queue *q = pdata->q; + int ret; + + while (1) { + ret = wcrypto_rsa_poll(q, 1); + if (ret < 0) { + break; + } + + if (asyn_thread_exit) + break; + } + + return NULL; +} + +static void _rsa_cb(void *message, void *rsa_tag) +{ + int keybits, key_size; + struct rsa_async_tag *tag = rsa_tag; + void *ctx = tag->ctx; + int thread_id = tag->thread_id; + int cnt = tag->cnt; + struct wcrypto_rsa_msg *msg = message; + void *out = msg->out; + enum wcrypto_rsa_op_type op_type = msg->op_type; + struct wcrypto_rsa_prikey *prikey; + struct test_hpre_pthread_dt *thread_info = tag->thread_info; + + wcrypto_get_rsa_prikey(ctx, &prikey); + keybits = wcrypto_rsa_key_bits(ctx); + key_size = keybits >> 3; + + thread_info->recv_task_num++; + + if (op_type == WCRYPTO_RSA_GENKEY) { + struct wcrypto_rsa_kg_out *kout = out; + + if (wcrypto_rsa_is_crt(ctx)) { + struct wd_dtb qinv, dq, dp; + struct wd_dtb *s_qinv, *s_dq, *s_dp; + + wcrypto_get_rsa_crt_prikey_params(prikey, &s_dq, &s_dp, + &s_qinv, NULL, NULL); + wcrypto_get_rsa_kg_out_crt_params(kout, &qinv, &dq, &dp); + if (memcmp(s_qinv->data, qinv.data, s_qinv->bsize)) { + HPRE_TST_PRT("keygen qinv mismatch!\n"); + return; + } + if (memcmp(s_dq->data, dq.data, s_dq->bsize)) { + HPRE_TST_PRT("keygen dq mismatch!\n"); + return; + } + if (memcmp(s_dp->data, dp.data, s_dp->bsize)) { + HPRE_TST_PRT("keygen dp mismatch!\n"); + return; + } + + } else { + struct wd_dtb d, n; + struct wd_dtb *s_d, *s_n; + + wcrypto_get_rsa_prikey_params(prikey, &s_d, &s_n); + wcrypto_get_rsa_kg_out_params(kout, &d, &n); + + /* check D */ + if (memcmp(s_d->data, d.data, s_d->bsize)) { + HPRE_TST_PRT("key generate D result mismatching!\n"); + return; + } + if (memcmp(s_n->data, n.data, s_n->bsize)) { + HPRE_TST_PRT("key generate N result mismatching!\n"); + return; + } + } + if (is_allow_print(cnt, DH_ASYNC_GEN, 1)) + HPRE_TST_PRT("HPRE hardware key generate successfully!\n"); + } else if (op_type == WCRYPTO_RSA_VERIFY) { + if (!only_soft && memcmp(ssl_params.ssl_verify_result, out, key_size)) { + HPRE_TST_PRT("pub encrypto result mismatch!\n"); + return; + } + } else { + if (wcrypto_rsa_is_crt(ctx)) + if (!only_soft && memcmp(ssl_params.ssl_sign_result, out, key_size)) { + HPRE_TST_PRT("prv decrypto result mismatch!\n"); + return; + } + } + + if (is_allow_print(cnt, op_type, 1)) + HPRE_TST_PRT("thread %d do RSA %dth time success!\n", thread_id, cnt); + if (op_type == WCRYPTO_RSA_GENKEY && out) { + wcrypto_del_kg_out(ctx, out); + } + free(rsa_tag); +} + +void *_rsa_async_op_test_thread(void *data) +{ + int ret = 0, i = 0, cpuid; + struct test_hpre_pthread_dt *pdata = data; + cpu_set_t mask; + enum alg_op_type op_type; + int pid = getpid(); + int thread_id = (int)syscall(__NR_gettid); + void *pool; + struct wcrypto_rsa_ctx_setup setup; + struct wcrypto_rsa_op_data opdata; + void *ctx = NULL; + struct wd_queue *q; + void *key_info = NULL; + struct wcrypto_rsa_prikey *prikey; + struct wcrypto_rsa_pubkey *pubkey; + struct rsa_async_tag *tag; + struct wd_dtb *wd_e, *wd_d, *wd_n, *wd_dq, *wd_dp, *wd_qinv, *wd_q, *wd_p; + struct wd_dtb t_e, t_p, t_q; + u32 key_size = key_bits >> 3; + + if (performance_test && (!t_times && !t_seconds)) { + HPRE_TST_PRT("t_times or t_seconds err\n"); + return NULL; + } + + CPU_ZERO(&mask); + cpuid = pdata->cpu_id; + op_type = pdata->op_type; + q = pdata->q; + pool = pdata->pool; + CPU_SET(cpuid, &mask); + if (cpuid) { + ret = pthread_setaffinity_np(pthread_self(), + sizeof(mask), &mask); + if (ret < 0) { + HPRE_TST_PRT("Proc-%d, thrd-%d:set affinity fail!\n", + pid, thread_id); + return NULL; + } + HPRE_TST_PRT("Proc-%d, thrd-%d bind to cpu-%d!\n", + pid, thread_id, cpuid); + } + memset(&setup, 0, sizeof(setup)); + memset(&opdata, 0, sizeof(opdata)); + setup.key_bits = key_bits; + setup.cb = (void *)_rsa_cb; + setup.br.alloc = (void *)wd_alloc_blk; + setup.br.free = (void *)wd_free_blk; + setup.br.iova_map = (void *)wd_blk_iova_map; + setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + setup.br.get_bufsize = (void *)wd_blksize; + setup.br.usr = pool; + if (!strcmp(g_mode, "-crt")) + setup.is_crt = true; + else + setup.is_crt = false; + + ctx = wcrypto_create_rsa_ctx(q, &setup); + if (!ctx) { + HPRE_TST_PRT("Proc-%d, %d-TD:create %s ctx fail!\n", + pid, thread_id, q->capa.alg); + goto fail_release; + } + + rsa_key_in = malloc(2 * key_size + sizeof(struct hpre_rsa_test_key_in)); + if (!rsa_key_in) { + HPRE_TST_PRT("thrd-%d:malloc err!\n", thread_id); + goto fail_release; + } + + rsa_key_in->e = rsa_key_in + 1; + rsa_key_in->p = rsa_key_in->e + key_size; + rsa_key_in->q = rsa_key_in->p + (key_size >> 1); + + wcrypto_get_rsa_pubkey(ctx, &pubkey); + wcrypto_get_rsa_pubkey_params(pubkey, &wd_e, &wd_n); + wd_e->dsize = BN_bn2bin(ssl_params.e, (unsigned char *)wd_e->data); + if (wd_e->dsize > wd_e->bsize) { + HPRE_TST_PRT("e bn to bin overflow!\n"); + goto fail_release; + } + wd_n->dsize = BN_bn2bin(ssl_params.n, (unsigned char *)wd_n->data); + if (wd_n->dsize > wd_n->bsize) { + HPRE_TST_PRT("n bn to bin overflow!\n"); + goto fail_release; + } + + wcrypto_get_rsa_prikey(ctx, &prikey); + if (wcrypto_rsa_is_crt(ctx)) { + wcrypto_get_rsa_crt_prikey_params(prikey, &wd_dq, &wd_dp, &wd_qinv, &wd_q, &wd_p); + /* CRT mode private key */ + wd_dq->dsize = BN_bn2bin(ssl_params.dq, (unsigned char *)wd_dq->data); + if (wd_dq->dsize > wd_dq->bsize) { + HPRE_TST_PRT("dq bn to bin overflow!\n"); + goto fail_release; + } + wd_dp->dsize = BN_bn2bin(ssl_params.dp, (unsigned char *)wd_dp->data); + if (wd_dp->dsize > wd_dp->bsize) { + HPRE_TST_PRT("dp bn to bin overflow!\n"); + goto fail_release; + } + wd_qinv->dsize = BN_bn2bin(ssl_params.qinv, (unsigned char *)wd_qinv->data); + if (wd_qinv->dsize > wd_qinv->bsize) { + HPRE_TST_PRT("qinv bn to bin overflow!\n"); + goto fail_release; + } + wd_q->dsize = BN_bn2bin(ssl_params.q, (unsigned char *)wd_q->data); + if (wd_q->dsize > wd_q->bsize) { + HPRE_TST_PRT("q bn to bin overflow!\n"); + goto fail_release; + } + wd_p->dsize = BN_bn2bin(ssl_params.p, (unsigned char *)wd_p->data); + if (wd_p->dsize > wd_p->bsize) { + HPRE_TST_PRT("p bn to bin overflow!\n"); + goto fail_release; + } + + } else { + wcrypto_get_rsa_prikey_params(prikey, &wd_d, &wd_n); + + wd_d->dsize = BN_bn2bin(ssl_params.d, (unsigned char *)wd_d->data); + wd_n->dsize = BN_bn2bin(ssl_params.n, (unsigned char *)wd_n->data); + wd_e = &t_e; + wd_p = &t_p; + wd_q = &t_q; + memset(rsa_key_in->e, 0, key_size); + memset(rsa_key_in->p, 0, key_size >> 1); + memset(rsa_key_in->q, 0, key_size >> 1); + rsa_key_in->e_size = BN_bn2bin(ssl_params.e, (unsigned char *)rsa_key_in->e); + rsa_key_in->p_size = BN_bn2bin(ssl_params.p, (unsigned char *)rsa_key_in->p); + rsa_key_in->q_size = BN_bn2bin(ssl_params.q, (unsigned char *)rsa_key_in->q); + wd_e->data = rsa_key_in->e; + wd_e->dsize = rsa_key_in->e_size; + wd_p->data = rsa_key_in->p; + wd_p->dsize = rsa_key_in->p_size; + wd_q->data = rsa_key_in->q; + wd_q->dsize = rsa_key_in->q_size; + } + + /* always key size bytes input */ + opdata.in_bytes = key_size; + if (op_type == RSA_KEY_GEN || op_type == RSA_ASYNC_GEN) { + opdata.op_type = WCRYPTO_RSA_GENKEY; + } else if (op_type == RSA_PUB_EN || op_type == RSA_ASYNC_EN) { + opdata.op_type = WCRYPTO_RSA_VERIFY; + } else if (op_type == RSA_PRV_DE || op_type == RSA_ASYNC_DE) { + opdata.op_type = WCRYPTO_RSA_SIGN; + } else { + HPRE_TST_PRT("thrd-%d:optype=%d err!\n", + thread_id, op_type); + goto fail_release; + } + + if (opdata.op_type == WCRYPTO_RSA_GENKEY) { + opdata.in = (__u8 *)wcrypto_new_kg_in(ctx, wd_e, wd_p, wd_q); + if (!opdata.in) { + HPRE_TST_PRT("thrd-%d:fill key gen opdata fail!\n", + thread_id); + goto fail_release; + } + //opdata.out = wcrypto_new_kg_out(ctx); + //if (!opdata.out) { + // HPRE_TST_PRT("create rsa kgen out fail!\n"); + // goto fail_release; + //} + } else { + opdata.in = wd_alloc_blk(pool); + if (!opdata.in) { + HPRE_TST_PRT("alloc in buffer fail!\n"); + goto fail_release; + } + memset(opdata.in, 0, opdata.in_bytes); + opdata.out = wd_alloc_blk(pool); + if (!opdata.out) { + HPRE_TST_PRT("alloc out buffer fail!\n"); + goto fail_release; + } + memset(opdata.out, 0, opdata.in_bytes); + opdata.out_bytes = opdata.in_bytes; + } + + do { + if (opdata.op_type == WCRYPTO_RSA_GENKEY) { + opdata.out = wcrypto_new_kg_out(ctx); + if (!opdata.out) { + HPRE_TST_PRT("create rsa kgen out fail!\n"); + goto fail_release; + } + } + /* set the user tag */ + tag = malloc(sizeof(*tag)); + if (!tag) + goto fail_release; + tag->ctx = ctx; + tag->thread_id = thread_id; + tag->cnt = i; + tag->thread_info = pdata; +try_do_again: + ret = wcrypto_do_rsa(ctx, &opdata, tag); + if (ret == -WD_EBUSY) { + usleep(100); + goto try_do_again; + } else if (ret) { + HPRE_TST_PRT("Proc-%d, T-%d:hpre %s %dth fail!\n", + pid, thread_id, + rsa_op_str[opdata.op_type], i); + goto fail_release; + } + //usleep(100); + i++; + pdata->send_task_num++; + }while (!is_exit(pdata)); + + if (performance_test) { + struct timeval cur_tval; + float speed = 0.0, time_used = 0.0; + gettimeofday(&cur_tval, NULL); + + printf("start: s %lu, us %lu\n", pdata->start_tval.tv_sec, pdata->start_tval.tv_usec); + printf("now: s %lu, us %lu\n", cur_tval.tv_sec, cur_tval.tv_usec); + + time_used = (float)((cur_tval.tv_sec -pdata->start_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - pdata->start_tval.tv_usec); + + if (t_seconds) { + speed = pdata->recv_task_num / time_used * 1000000; + HPRE_TST_PRT("Proc-%d, %d-TD: rsa do %s send %u task, recv %u task, run %0.1f s at %0.3f ops\n", + pid, thread_id, rsa_op_str[opdata.op_type], + pdata->send_task_num, pdata->recv_task_num, + time_used / 1000000, speed); + } else if (t_times) { + speed = 1 / (time_used / t_times) * 1000; + HPRE_TST_PRT("\r\nPID(%d)-thread-%d:%s CRT mode %dbits %s time %0.0f us, pkt len =" + " %d bytes, %0.3f Kops\n", getpid(), (int)syscall(__NR_gettid), "rsa", + key_bits, rsa_op_str_perf[opdata.op_type], time_used, key_bits / 8, speed); + } + } + + /* wait for recv finish */ + while (pdata->send_task_num != pdata->recv_task_num) + usleep(1000); + + +fail_release: + if (opdata.op_type == WCRYPTO_RSA_GENKEY) { + if (opdata.in) + wcrypto_del_kg_in(ctx, opdata.in); + //if (opdata.out) + // wcrypto_del_kg_out(ctx, opdata.out); + } else { + if (opdata.in) + wd_free_blk(pool, opdata.in); + if (opdata.out) + wd_free_blk(pool, opdata.out); + } + if (ctx) + wcrypto_del_rsa_ctx(ctx); + if (key_info) + free(key_info); + if (rsa_key_in) + free(rsa_key_in); + return NULL; +} + +static int set_ssl_plantext(void) +{ + ssl_params.size = key_bits >> 3; + ssl_params.plantext = malloc(ssl_params.size); + if (!ssl_params.plantext) + return -ENOMEM; + memset(ssl_params.plantext, 0, ssl_params.size); + return 0; +} + +static int rsa_openssl_key_gen_for_async_test(void) +{ + int ret; + + ssl_params.rsa = RSA_new(); + if (!ssl_params.rsa) { + HPRE_TST_PRT("RSA new fail!\n"); + return -ENOMEM; + } + ssl_params.e = BN_new(); + if (!ssl_params.e) { + RSA_free(ssl_params.rsa); + ssl_params.rsa = NULL; + HPRE_TST_PRT("BN new e fail!\n"); + ret = -ENOMEM; + goto gen_fail; + } + ret = BN_set_word(ssl_params.e, 65537); + if (ret != 1) { + HPRE_TST_PRT("BN_set_word fail!\n"); + ret = -1; + goto gen_fail; + } + + /* Generate OpenSSL SW rsa parameters */ + ret = RSA_generate_key_ex(ssl_params.rsa, key_bits, ssl_params.e, NULL); + if (ret != 1) { + HPRE_TST_PRT("RSA_generate_key_ex fail!\n"); + ret = -1; + goto gen_fail; + } + RSA_get0_key((const RSA *)ssl_params.rsa, (const BIGNUM **)&ssl_params.n, + (const BIGNUM **)&ssl_params.e, (const BIGNUM **)&ssl_params.d); + RSA_get0_factors((const RSA *)ssl_params.rsa, (const BIGNUM **)&ssl_params.p, + (const BIGNUM **)&ssl_params.q); + RSA_get0_crt_params((const RSA *)ssl_params.rsa, (const BIGNUM **)&ssl_params.dp, + (const BIGNUM **)&ssl_params.dq, (const BIGNUM **)&ssl_params.qinv); + + /* Generate OpenSSL SW rsa verify and sign standard result + * for check in the next tests + */ + ret = set_ssl_plantext(); + if (ret) { + HPRE_TST_PRT("set ssl plantext fail!!\n"); + ret = -1; + goto gen_fail; + } + ssl_params.ssl_verify_result = malloc(ssl_params.size); + if (!ssl_params.ssl_verify_result) { + HPRE_TST_PRT("malloc verify result buffer fail!!\n"); + ret = -1; + goto gen_fail; + } + ret = RSA_public_encrypt(ssl_params.size, ssl_params.plantext, + ssl_params.ssl_verify_result, + ssl_params.rsa, RSA_NO_PADDING); + if (ret != ssl_params.size) { + HPRE_TST_PRT("openssl pub encrypto fail!ret=%d\n", ret); + ret = -1; + return ret; + } + ssl_params.ssl_sign_result = malloc(ssl_params.size); + if (!ssl_params.ssl_sign_result) { + HPRE_TST_PRT("malloc sign result buffer fail!!\n"); + ret = -1; + goto gen_fail; + } + ret = RSA_private_decrypt(ssl_params.size, ssl_params.plantext, + ssl_params.ssl_sign_result, + ssl_params.rsa, RSA_NO_PADDING); + if (ret != ssl_params.size) { + HPRE_TST_PRT("openssl priv decrypto fail!ret=%d\n", ret); + ret = -1; + goto gen_fail; + } + + return 0; +gen_fail: + RSA_free(ssl_params.rsa); + BN_free(ssl_params.e); + if (ssl_params.plantext) + free(ssl_params.plantext); + if (ssl_params.ssl_verify_result) + free(ssl_params.ssl_verify_result); + if (ssl_params.ssl_sign_result) + free(ssl_params.ssl_sign_result); + return ret; +} + +static int rsa_async_test(int thread_num, __u64 lcore_mask, + __u64 hcore_mask, enum alg_op_type op_type) +{ + unsigned int block_num = 2048; + void *pool; + struct wd_blkpool_setup setup; + struct wd_queue q; + int ret = 0, cnt = 0, i; + int h_cpuid; + + memset(&q, 0, sizeof(q)); + q.capa.alg = "rsa"; + ret = wd_request_queue(&q); + if (ret) { + HPRE_TST_PRT("%s:request queue fail!\n", __func__); + return ret; + } + memset(&setup, 0, sizeof(setup)); + setup.block_size = (key_bits >> 4) * 20; + setup.block_num = block_num; + setup.align_size = 64; + + pool = wd_blkpool_create(&q, &setup); + if (!pool) { + HPRE_TST_PRT("%s(): create pool fail!\n", __func__); + return -ENOMEM; + } + + /* Create poll thread at first */ + test_thrds_data[0].pool = pool; + test_thrds_data[0].q = &q; + test_thrds_data[0].thread_num = 1; + test_thrds_data[0].op_type = op_type; + test_thrds_data[0].cpu_id = 0; + ret = pthread_create(&system_test_thrds[0], NULL, + _rsa_async_poll_test_thread, &test_thrds_data[0]); + if (ret) { + HPRE_TST_PRT("Create poll thread fail!\n"); + return ret; + } + + ret = rsa_openssl_key_gen_for_async_test(); + if(ret) { + HPRE_TST_PRT("openssl genkey for async thread test fail!"); + return 0; + } + + if (_get_one_bits(lcore_mask) > 0) + cnt = _get_one_bits(lcore_mask); + else if (_get_one_bits(lcore_mask) == 0 && + _get_one_bits(hcore_mask) == 0) + cnt = thread_num; + for (i = 1; i <= cnt; i++) { + test_thrds_data[i].pool = pool; + test_thrds_data[i].q = &q; + test_thrds_data[i].thread_num = thread_num; + test_thrds_data[i].op_type = op_type; + test_thrds_data[i].cpu_id = _get_cpu_id(i - 1, lcore_mask); + gettimeofday(&test_thrds_data[i].start_tval, NULL); + ret = pthread_create(&system_test_thrds[i], NULL, + _rsa_async_op_test_thread, &test_thrds_data[i]); + if (ret) { + HPRE_TST_PRT("Create %dth thread fail!\n", i); + return ret; + } + } + for (i = 1; i <= thread_num - cnt; i++) { + h_cpuid = _get_cpu_id(i - 1, hcore_mask); + if (h_cpuid > 0) + h_cpuid += 64; + test_thrds_data[i + cnt].pool = pool; + test_thrds_data[i + cnt].q = &q; + test_thrds_data[i + cnt].thread_num = thread_num; + test_thrds_data[i + cnt].op_type = op_type; + test_thrds_data[i + cnt].cpu_id = h_cpuid; + gettimeofday(&test_thrds_data[i + cnt].start_tval, NULL); + ret = pthread_create(&system_test_thrds[i + cnt], NULL, + _rsa_async_op_test_thread, &test_thrds_data[i + cnt]); + if (ret) { + HPRE_TST_PRT("Create %dth thread fail!\n", i); + return ret; + } + } + for (i = 1; i <= thread_num; i++) { + ret = pthread_join(system_test_thrds[i], NULL); + if (ret) { + HPRE_TST_PRT("Join %dth thread fail!\n", i); + return ret; + } + } + + asyn_thread_exit = 1; + + ret = pthread_join(system_test_thrds[0], NULL); + if (ret) { + HPRE_TST_PRT("Join %dth thread fail!\n", i); + return ret; + } + + wd_release_queue(&q); + wd_blkpool_destroy(pool); + return 0; +} + +static void *_dh_async_poll_test_thread(void *data) +{ + struct test_hpre_pthread_dt *pdata = data; + struct wd_queue *q = pdata->q; + int ret, cpuid; + int pid = getpid(); + cpu_set_t mask; + int thread_id = (int)syscall(__NR_gettid); + + CPU_ZERO(&mask); + cpuid = pdata->cpu_id; + CPU_SET(cpuid, &mask); + if (cpuid) { + ret = pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask); + if (ret < 0) { + HPRE_TST_PRT("Proc-%d, thrd-%d:set affinity fail!\n", + pid, thread_id); + return NULL; + } + HPRE_TST_PRT("Proc-%d, poll thrd-%d bind to cpu-%d!\n", + pid, thread_id, cpuid); + } + + while (1) { + ret = wcrypto_dh_poll(q, 1); + if (ret < 0) { + break; + } + + if (asyn_thread_exit) + break; + } + + HPRE_TST_PRT("%s exit!\n", __func__); + return NULL; +} + +static int dh_async_test(int thread_num, __u64 lcore_mask, + __u64 hcore_mask, enum alg_op_type op_type) +{ + void *bufPool; + struct wd_blkpool_setup setup; + int i, ret, cnt = 0; + int block_num = 1024*16; + struct wd_queue *q; + int h_cpuid; + + q = malloc(sizeof(struct wd_queue)); + if (!q) { + HPRE_TST_PRT("malloc q memory fail!\n"); + return -ENOMEM; + } + memset(q, 0, sizeof(struct wd_queue)); + + q->capa.alg = "dh"; + ret = wd_request_queue(q); + if (ret) { + HPRE_TST_PRT("request queue fail!\n"); + return ret; + } + memset(&setup, 0, sizeof(setup)); + setup.block_size = key_bits >> 2; // block_size; + setup.block_num = block_num; + setup.align_size = 64; + + bufPool = wd_blkpool_create(q, &setup); + if (!bufPool) { + HPRE_TST_PRT("%s(): create pool fail!\n", __func__); + return -ENOMEM; + } + + if (_get_one_bits(lcore_mask) > 0) + cnt = _get_one_bits(lcore_mask); + else if (_get_one_bits(lcore_mask) == 0 && + _get_one_bits(hcore_mask) == 0) + cnt = thread_num; + + /* Create poll thread at first */ + test_thrds_data[0].pool = bufPool; + test_thrds_data[0].q = q; + test_thrds_data[0].thread_num = 1; + test_thrds_data[0].op_type = op_type; + test_thrds_data[0].cpu_id = 0; + ret = pthread_create(&system_test_thrds[0], NULL, + _dh_async_poll_test_thread, &test_thrds_data[0]); + if (ret) { + HPRE_TST_PRT("Create poll thread fail!\n"); + return ret; + } + + for (i = 1; i <= cnt; i++) { + test_thrds_data[i].pool = bufPool; + test_thrds_data[i].q = q; + test_thrds_data[i].thread_num = thread_num; + test_thrds_data[i].op_type = op_type; + test_thrds_data[i].cpu_id = _get_cpu_id(i - 1, lcore_mask); + gettimeofday(&test_thrds_data[i].start_tval, NULL); + ret = pthread_create(&system_test_thrds[i], NULL, + _hpre_dh_sys_test_thread, &test_thrds_data[i]); + if (ret) { + HPRE_TST_PRT("Create %dth thread fail!\n", i); + return ret; + } + } + + for (i = 1; i <= thread_num - cnt; i++) { + h_cpuid = _get_cpu_id(i - 1, hcore_mask); + if (h_cpuid > 0) + h_cpuid += 64; + + test_thrds_data[i + cnt].pool = bufPool; + test_thrds_data[i + cnt].q = q; + test_thrds_data[i + cnt].thread_num = thread_num; + test_thrds_data[i + cnt].op_type = op_type; + test_thrds_data[i + cnt].cpu_id = h_cpuid; + gettimeofday(&test_thrds_data[i + cnt].start_tval, NULL); + ret = pthread_create(&system_test_thrds[i + cnt], NULL, + _hpre_dh_sys_test_thread, &test_thrds_data[i + cnt]); + if (ret) { + HPRE_TST_PRT("Create %dth thread fail!\n", i); + return ret; + } + } + + for (i = 1; i <= thread_num; i++) { + ret = pthread_join(system_test_thrds[i], NULL); + if (ret) { + HPRE_TST_PRT("Join %dth thread fail!\n", i); + return ret; + } + } + + asyn_thread_exit = 1; + + ret = pthread_join(system_test_thrds[0], NULL); + if (ret) { + HPRE_TST_PRT("Join %dth thread fail!\n", i); + return ret; + } + + return 0; +} + +static void *_ecc_async_poll_test_thread(void *data) +{ + struct test_hpre_pthread_dt *pdata = data; + struct wd_queue *q = pdata->q; + __u16 op = pdata->op_type; + int ret, cpuid; + int pid = getpid(); + cpu_set_t mask; + int thread_id = (int)syscall(__NR_gettid); + + CPU_ZERO(&mask); + cpuid = pdata->cpu_id; + CPU_SET(cpuid, &mask); + if (cpuid) { + ret = pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask); + if (ret < 0) { + HPRE_TST_PRT("Proc-%d, thrd-%d:set affinity fail!\n", + pid, thread_id); + return NULL; + } + HPRE_TST_PRT("Proc-%d, poll thrd-%d bind to cpu-%d!\n", + pid, thread_id, cpuid); + } + + while (1) { + if (op == ECDH_ASYNC_GEN || op == ECDH_ASYNC_COMPUTE || + op == X25519_ASYNC_GEN || op == X25519_ASYNC_COMPUTE || + op == X448_ASYNC_GEN || op == X448_ASYNC_COMPUTE) { + ret = wcrypto_ecxdh_poll(q, 1); + } else if (op == ECDSA_ASYNC_SIGN || op == ECDSA_ASYNC_VERF) { + ret = wcrypto_ecdsa_poll(q, 1); + } else if (op == SM2_ASYNC_SIGN || op == SM2_ASYNC_VERF || + op == SM2_ASYNC_DEC || op == SM2_ASYNC_ENC || op == SM2_ASYNC_KG) { + ret = wcrypto_sm2_poll(q, 1); + } else { + ret = -1; + } + + if (ret < 0) { + break; + } + + if (asyn_thread_exit) + break; + } + + HPRE_TST_PRT("%s exit!\n", __func__); + return NULL; +} + +static int ecc_async_test(int thread_num, __u64 lcore_mask, + __u64 hcore_mask, enum alg_op_type op_type) +{ + void *bufPool; + struct wd_blkpool_setup setup; + int i, ret, cnt = 0; + int block_num = 1024*16; + struct wd_queue *q; + int h_cpuid; + + q = malloc(sizeof(struct wd_queue)); + if (!q) { + HPRE_TST_PRT("malloc q memory fail!\n"); + return -ENOMEM; + } + memset(q, 0, sizeof(struct wd_queue)); + + if (op_type == ECDH_ASYNC_GEN || op_type == ECDH_ASYNC_COMPUTE) { + q->capa.alg = "ecdh"; + } else if (op_type == X25519_ASYNC_GEN || op_type == X25519_ASYNC_COMPUTE) { + q->capa.alg = "x25519"; + } else if (op_type == X448_ASYNC_GEN || op_type == X448_ASYNC_COMPUTE) { + q->capa.alg = "x448"; + } else if (op_type == ECDSA_ASYNC_SIGN || op_type == ECDSA_ASYNC_VERF) { + q->capa.alg = "ecdsa"; + } else { + q->capa.alg = "sm2"; + } + + ret = wd_request_queue(q); + if (ret) { + HPRE_TST_PRT("request queue fail!\n"); + return ret; + } + + memset(&setup, 0, sizeof(setup)); + if (!strncmp(q->capa.alg, "sm2", 3)) + setup.block_size = BITS_TO_BYTES(set_plaintext_len) + get_ecc_min_blocksize(key_bits) * 8; + else + setup.block_size = get_ecc_min_blocksize(key_bits) * 8; + + setup.block_num = block_num; + setup.align_size = 64; + + bufPool = wd_blkpool_create(q, &setup); + if (!bufPool) { + HPRE_TST_PRT("%s(): create pool fail!\n", __func__); + return -ENOMEM; + } + + if (_get_one_bits(lcore_mask) > 0) + cnt = _get_one_bits(lcore_mask); + else if (_get_one_bits(lcore_mask) == 0 && + _get_one_bits(hcore_mask) == 0) + cnt = thread_num; + + /* Create poll thread at first */ + test_thrds_data[0].pool = bufPool; + test_thrds_data[0].q = q; + test_thrds_data[0].thread_num = 1; + test_thrds_data[0].op_type = op_type; + test_thrds_data[0].cpu_id = 0; + ret = pthread_create(&system_test_thrds[0], NULL, + _ecc_async_poll_test_thread, &test_thrds_data[0]); + if (ret) { + HPRE_TST_PRT("Create poll thread fail!\n"); + return ret; + } + + for (i = 1; i <= cnt; i++) { + test_thrds_data[i].pool = bufPool; + test_thrds_data[i].q = q; + test_thrds_data[i].thread_num = thread_num; + test_thrds_data[i].op_type = op_type; + test_thrds_data[i].cpu_id = _get_cpu_id(i - 1, lcore_mask); + gettimeofday(&test_thrds_data[i].start_tval, NULL); + ret = pthread_create(&system_test_thrds[i], NULL, + _ecc_sys_test_thread, &test_thrds_data[i]); + if (ret) { + HPRE_TST_PRT("Create %dth thread fail!\n", i); + return ret; + } + } + + for (i = 1; i <= thread_num - cnt; i++) { + h_cpuid = _get_cpu_id(i - 1, hcore_mask); + if (h_cpuid > 0) + h_cpuid += 64; + + test_thrds_data[i + cnt].pool = bufPool; + test_thrds_data[i + cnt].q = q; + test_thrds_data[i + cnt].thread_num = thread_num; + test_thrds_data[i + cnt].op_type = op_type; + test_thrds_data[i + cnt].cpu_id = h_cpuid; + gettimeofday(&test_thrds_data[i + cnt].start_tval, NULL); + ret = pthread_create(&system_test_thrds[i + cnt], NULL, + _ecc_sys_test_thread, &test_thrds_data[i + cnt]); + if (ret) { + HPRE_TST_PRT("Create %dth thread fail!\n", i); + return ret; + } + } + + for (i = 1; i <= thread_num; i++) { + ret = pthread_join(system_test_thrds[i], NULL); + if (ret) { + HPRE_TST_PRT("Join %dth thread fail!\n", i); + return ret; + } + } + + asyn_thread_exit = 1; + + ret = pthread_join(system_test_thrds[0], NULL); + if (ret) { + HPRE_TST_PRT("Join %dth thread fail!\n", i); + return ret; + } + + wd_release_queue(q); + + return 0; +} + +void *_hpre_sys_test_thread(void *data) +{ + enum alg_op_type op_type; + struct test_hpre_pthread_dt *pdata = data; + + op_type = pdata->op_type; + if (op_type > MAX_DH_TYPE && op_type < MAX_ECC_TYPE) { + return _ecc_sys_test_thread(data); + } else if (op_type > MAX_RSA_ASYNC_TYPE && op_type < MAX_DH_TYPE) { + return _hpre_dh_sys_test_thread(data); + } else { + return _hpre_rsa_sys_test_thread(data); + } +} + +void normal_register(const char *format, ...) +{ + printf("wd log:%s", format); + return ; +} + +void redirect_log_2_file(const char *format, ...) +{ + pthread_mutex_lock(&mute); + FILE *fp; + fp = fopen("file.txt", "a+"); + fprintf(fp,format,__FILE__, __LINE__, __func__); + fclose(fp); + pthread_mutex_unlock(&mute); + return ; +} + +void segmant_fault_register(const char *format, ...) +{ + int *ptr = NULL; + *ptr = 0; + return ; +} +int main(int argc, char *argv[]) +{ + void *pool = NULL; + enum alg_op_type alg_op_type = HPRE_ALG_INVLD_TYPE; + enum alg_op_mode mode; + __u8 *in = NULL, *tp_in, *temp_in = NULL; + __u8 *out = NULL; + __u8 *key = NULL; + char *in_file = NULL; + char *out_file = NULL; + char *key_file = NULL; + int ret = 0, in_size = 0, op_size; + int priv_key_size, pub_key_size, key_info_size; + int read_size, out_fd = -1, try_close = 1; + int block_num = 1024; + struct wd_queue q; + struct wcrypto_rsa_ctx_setup setup; + struct wcrypto_dh_ctx_setup dh_setup; + void *ctx = NULL; + int thread_num, bits; + __u64 core_mask[2]; + u32 value = 0; + char dev_path[PATH_STR_SIZE] = {0}; + unsigned int node_msk = 0; + + if (!argv[1] || !argv[6]) { + HPRE_TST_PRT("pls use ./test_hisi_hpre -help get details!\n"); + return -EINVAL; + } + + if (argv[7] && !strcmp(argv[7], "-check")) + openssl_check = 1; + if (argv[7] && !strcmp(argv[7], "-soft")) + only_soft = 1; + + if (!strcmp(argv[argc-1], "-registerlog-0")){ + ret = wd_register_log(NULL); + if (!ret){ + printf("illegel to register null log interface"); + return -EINVAL; + } + return 0; + } + if (!strcmp(argv[argc-1], "-registerlog-1")){ + ret = wd_register_log(redirect_log_2_file); + if (ret){ + printf("fail to register log interface"); + return -EINVAL; + } + if (argc == 2){ + char *error_info = "q, info or dev_info NULL!"; + struct wd_queue *q = NULL; + char content[1024]; + wd_get_node_id(q); + FILE *fp = NULL; + fp = fopen("file.txt", "r"); + if (fgets(content,1024,fp) == NULL) + return -EINVAL; + if (strstr(content,error_info) == NULL){ + return -EINVAL; + } + return 0; + } + } + if (!strcmp(argv[argc-1], "-registerlog-2")){ + ret = wd_register_log(normal_register); + if (ret){ + printf("fail to register log interface"); + return -EINVAL; + } + if (!wd_register_log(normal_register)){ + printf("illegel to register dumplicate log interface"); + return -EINVAL; + } + return 0; + } + if (!strcmp(argv[argc-1], "-registerlog-3")){ + ret = wd_register_log(segmant_fault_register); + if (ret){ + printf("fail to register log interface"); + return -EINVAL; + } + WD_ERR("segment fault"); + return 0; + } + if (!strcmp(argv[1], "-system-qt")) { + is_system_test = 1; + HPRE_TST_PRT("Now doing system queue mng test!\n"); + } else if (!strcmp(argv[1], "-system-gen")) { + alg_op_type = RSA_KEY_GEN; + is_system_test = 1; + HPRE_TST_PRT("Now doing system key gen test!\n"); + } else if (!strcmp(argv[1], "-system-vrf")) { + alg_op_type = RSA_PUB_EN; + is_system_test = 1; + HPRE_TST_PRT("Now doing system verify test!\n"); + } else if (!strcmp(argv[1], "-system-sgn")) { + alg_op_type = RSA_PRV_DE; + is_system_test = 1; + HPRE_TST_PRT("Now doing system sign test!\n"); + } else if (!strcmp(argv[1], "-system-asgn")) { + alg_op_type = RSA_ASYNC_DE; + is_system_test = 1; + HPRE_TST_PRT("Now doing system rsa async sign test!\n"); + } else if (!strcmp(argv[1], "-system-avrf")) { + alg_op_type = RSA_ASYNC_EN; + is_system_test = 1; + HPRE_TST_PRT("Now doing system rsa async verify test!\n"); + } else if (!strcmp(argv[1], "-system-agen")) { + alg_op_type = RSA_ASYNC_GEN; + is_system_test = 1; + HPRE_TST_PRT("Now doing system rsa async kgerate test!\n"); + } else if (!strcmp(argv[1], "-system-gen1")) { + HPRE_TST_PRT("DH key generation\n"); + alg_op_type = DH_GEN; + is_system_test = 1; + } else if (!strcmp(argv[1], "-system-agen1")) { + HPRE_TST_PRT("DH gen async\n"); + alg_op_type = DH_ASYNC_GEN; + is_system_test = 1; + } else if (!strcmp(argv[1], "-system-gen2")) { + HPRE_TST_PRT("DH key generation\n"); + alg_op_type = DH_COMPUTE; + is_system_test = 1; + } else if (!strcmp(argv[1], "-system-agen2")) { + HPRE_TST_PRT("DH gen async\n"); + alg_op_type = DH_ASYNC_COMPUTE; + is_system_test = 1; + } else if (!strcmp(argv[1], "-system-gen1-ecc")) { + HPRE_TST_PRT("ECDH gen sync\n"); + alg_op_type = ECDH_GEN; + is_system_test = 1; + } else if (!strcmp(argv[1], "-system-gen2-ecc")) { + HPRE_TST_PRT("ECDH gen2 sync\n"); + alg_op_type = ECDH_COMPUTE; + is_system_test = 1; + } else if (!strcmp(argv[1], "-system-agen1-ecc")) { + HPRE_TST_PRT("ECDH agen sync\n"); + alg_op_type = ECDH_ASYNC_GEN; + is_system_test = 1; + } else if (!strcmp(argv[1], "-system-agen2-ecc")) { + HPRE_TST_PRT("ECDH agen2 sync\n"); + alg_op_type = ECDH_ASYNC_COMPUTE; + is_system_test = 1; + } else if (!strcmp(argv[1], "-system-sign-ecc")) { + HPRE_TST_PRT("ecdsa sign sync\n"); + alg_op_type = ECDSA_SIGN; + is_system_test = 1; + } else if (!strcmp(argv[1], "-system-verf-ecc")) { + HPRE_TST_PRT("ecdsa verf sync\n"); + alg_op_type = ECDSA_VERF; + is_system_test = 1; + } else if (!strcmp(argv[1], "-system-asign-ecc")) { + HPRE_TST_PRT("ecdsa sign async\n"); + alg_op_type = ECDSA_ASYNC_SIGN; + is_system_test = 1; + } else if (!strcmp(argv[1], "-system-averf-ecc")) { + HPRE_TST_PRT("ecdsa verf async\n"); + alg_op_type = ECDSA_ASYNC_VERF; + is_system_test = 1; + } else if (!strcmp(argv[1], "-system-gen1-x25519")) { + HPRE_TST_PRT("X25519 gen sync\n"); + alg_op_type = X25519_GEN; + is_system_test = 1; + } else if (!strcmp(argv[1], "-system-gen2-x25519")) { + HPRE_TST_PRT("X25519 gen2 sync\n"); + alg_op_type = X25519_COMPUTE; + is_system_test = 1; + } else if (!strcmp(argv[1], "-system-agen1-x25519")) { + HPRE_TST_PRT("X25519 agen sync\n"); + alg_op_type = X25519_ASYNC_GEN; + is_system_test = 1; + } else if (!strcmp(argv[1], "-system-agen2-x25519")) { + HPRE_TST_PRT("X25519 agen2 sync\n"); + alg_op_type = X25519_ASYNC_COMPUTE; + is_system_test = 1; + } else if (!strcmp(argv[1], "-system-gen1-x448")) { + HPRE_TST_PRT("X448 gen sync\n"); + alg_op_type = X448_GEN; + is_system_test = 1; + } else if (!strcmp(argv[1], "-system-gen2-x448")) { + HPRE_TST_PRT("X448 gen2 sync\n"); + alg_op_type = X448_COMPUTE; + is_system_test = 1; + } else if (!strcmp(argv[1], "-system-agen1-x448")) { + HPRE_TST_PRT("X448 agen sync\n"); + alg_op_type = X448_ASYNC_GEN; + is_system_test = 1; + } else if (!strcmp(argv[1], "-system-agen2-x448")) { + HPRE_TST_PRT("x448 agen2 sync\n"); + alg_op_type = X448_ASYNC_COMPUTE; + is_system_test = 1; + } else if (!strcmp(argv[1], "-system-sign-sm2")) { + HPRE_TST_PRT("sm2 sign sync\n"); + alg_op_type = SM2_SIGN; + is_system_test = 1; + } else if (!strcmp(argv[1], "-system-verf-sm2")) { + HPRE_TST_PRT("sm2 verf sync\n"); + alg_op_type = SM2_VERF; + is_system_test = 1; + } else if (!strcmp(argv[1], "-system-asign-sm2")) { + HPRE_TST_PRT("sm2 sign async\n"); + alg_op_type = SM2_ASYNC_SIGN; + is_system_test = 1; + } else if (!strcmp(argv[1], "-system-averf-sm2")) { + HPRE_TST_PRT("sm2 verf async\n"); + alg_op_type = SM2_ASYNC_VERF; + is_system_test = 1; + } else if (!strcmp(argv[1], "-system-enc-sm2")) { + HPRE_TST_PRT("sm2 enc sync\n"); + alg_op_type = SM2_ENC; + is_system_test = 1; + } else if (!strcmp(argv[1], "-system-dec-sm2")) { + HPRE_TST_PRT("sm2 dec sync\n"); + alg_op_type = SM2_DEC; + is_system_test = 1; + } else if (!strcmp(argv[1], "-system-aenc-sm2")) { + HPRE_TST_PRT("sm2 enc async\n"); + alg_op_type = SM2_ASYNC_ENC; + is_system_test = 1; + } else if (!strcmp(argv[1], "-system-adec-sm2")) { + HPRE_TST_PRT("sm2 dec async\n"); + alg_op_type = SM2_ASYNC_DEC; + is_system_test = 1; + } else if (!strcmp(argv[1], "-system-kg-sm2")) { + HPRE_TST_PRT("sm2 kg sync\n"); + alg_op_type = SM2_KG; + is_system_test = 1; + } else if (!strcmp(argv[1], "-system-akg-sm2")) { + HPRE_TST_PRT("sm2 kg async\n"); + alg_op_type = SM2_ASYNC_KG; + is_system_test = 1; + } else { + goto basic_function_test; + } + + if (argv[8]) { + key_bits = strtoul(argv[8], NULL, 10); + } else { + key_bits = 2048; + } + if (alg_op_type >= X25519_GEN && alg_op_type <= X25519_ASYNC_COMPUTE) + key_bits = 256; + else if (alg_op_type >= X448_GEN && alg_op_type <= X448_ASYNC_COMPUTE) + key_bits = 448; + + /* Do sys test for performance and mult threads/process scenarioes */ + if (is_system_test) { + if (!strcmp(argv[2], "-t")) { + thread_num = strtoul((char *)argv[3], NULL, 10); + if (thread_num <= 0 || thread_num > TEST_MAX_THRD) { + HPRE_TST_PRT("Invalid threads num:%d!\n", + thread_num); + HPRE_TST_PRT("Now set threads num as 2\n"); + thread_num = 2; + } + } else { + HPRE_TST_PRT("./test_hisi_hpre --help get details\n"); + return -EINVAL; + } + if (strcmp(argv[4], "-c")) { + HPRE_TST_PRT("./test_hisi_hpre --help get details\n"); + return -EINVAL; + } + + if (argv[5][0] != '0' || argv[5][1] != 'x') { + HPRE_TST_PRT("Err:coremask should be hex!\n"); + return -EINVAL; + } + if (strlen(argv[5]) > 34) { + HPRE_TST_PRT("Warning: coremask is cut!\n"); + argv[5][34] = 0; + } + if (strlen(argv[5]) <= 18) { + core_mask[0] = strtoull(argv[5], NULL, 16); + if (core_mask[0] & 0x1) { + HPRE_TST_PRT("Warn:cannot bind to core 0,\n"); + HPRE_TST_PRT("now run without binding\n"); + core_mask[0] = 0x0; /* no binding */ + } + core_mask[1] = 0; + } else { + int offset = 0; + char *temp; + + offset = strlen(argv[5]) - 16; + core_mask[0] = strtoull(&argv[5][offset], NULL, 16); + if (core_mask[0] & 0x1) { + HPRE_TST_PRT("Warn:cannot bind to core 0,\n"); + HPRE_TST_PRT("now run without binding\n"); + core_mask[0] = 0x0; /* no binding */ + } + temp = malloc(64); + strcpy(temp, argv[5]); + temp[offset] = 0; + core_mask[1] = strtoull(temp, NULL, 16); + } + bits = _get_one_bits(core_mask[0]); + bits += _get_one_bits(core_mask[1]); + if (thread_num > bits) { + HPRE_TST_PRT("Coremask not covers all thrds,\n"); + HPRE_TST_PRT("Bind first %d thrds!\n", bits); + } else if (thread_num < bits) { + HPRE_TST_PRT("Coremask overflow,\n"); + HPRE_TST_PRT("Just try to bind all thrds!\n"); + } + if (!strcmp(argv[6], "-log")) { + with_log = 1; + performance_test = 0; + t_times = 0; + t_seconds = 0; + } else if (!strcmp(argv[6], "-performance")) { + with_log = 0; + openssl_check = 0; + performance_test = 1; + } else { + with_log = 0; + performance_test = 0; + } + + if (argv[9]) { + ctx_num_per_q = strtoul(argv[9], NULL, 10); + if (ctx_num_per_q <= 0) { + HPRE_TST_PRT("Invalid ctx num per queue:%s!\n", + argv[9]); + HPRE_TST_PRT("Now ctx num per queue is set as 1!\n"); + ctx_num_per_q = 1; + } + } else { + HPRE_TST_PRT("Now ctx num per queue is set as 1!\n"); + ctx_num_per_q = 1; + } + + q_num = (thread_num - 1) / ctx_num_per_q + 1; + + if (argc == 13 || argc == 14 || argc == 16) { + if (alg_op_type > MAX_DH_TYPE && alg_op_type < MAX_ECDSA_TYPE) { + ecc_curve_name = argv[10]; + /* curve x25519/x448 has th only param which is denoted in drv */ + } else if (alg_op_type >= X25519_GEN && alg_op_type <= X25519_ASYNC_COMPUTE) { + ecc_curve_name = ""; + key_bits = 256; + } else if (alg_op_type >= X448_GEN && alg_op_type <= X448_ASYNC_COMPUTE) { + ecc_curve_name = ""; + key_bits = 448; + } else if (alg_op_type >= SM2_SIGN && alg_op_type <= SM2_ASYNC_KG) { + ecc_curve_name = ""; + if (!strcmp(argv[10], "set-rand-non")) + set_rand = RAND_NON; + else if (!strcmp(argv[10], "set-rand-param")) + set_rand = RAND_PARAM; + else if (!strcmp(argv[10], "set-rand-cb")) + set_rand = RAND_CB; + + if (!strcmp(argv[8], "set-dgst")) + set_msg = MSG_DIGEST; + else if (!strcmp(argv[8], "set-ptext-short")) + set_msg = MSG_SHORT_PTEXT; + else if (!strcmp(argv[8], "set-ptext-long")) + set_msg = MSG_LONG_PTEXT; + key_bits = 256; + } else { + if (!strcmp(argv[10], "-g2")) { + g_mode = "-g2"; + } else if (!strcmp(argv[10], "-com")) { + g_mode = "-com"; + } else if (!strcmp(argv[10], "-crt")) { + g_mode = "-crt"; + } else { + HPRE_TST_PRT("pls use ./test_hisi_hpre -help get details!\n"); + return -EINVAL; + } + } + + if (!strcmp(argv[11], "-seconds") || + !strcmp(argv[11], "-cycles")) { + value = strtoul(argv[12], NULL, 10); + if (!strcmp(argv[11], "-seconds")) { + t_seconds = value; + } else if (!strcmp(argv[11], "-cycles")) { + t_times = value; + } else { + HPRE_TST_PRT("pls use ./test_hisi_hpre -help get details!\n"); + return -EINVAL; + } + } else if (!strcmp(argv[11], "-dev")) { + strcpy(dev_path, argv[12]); + } else if (!strcmp(argv[11], "-node")) { + node_msk = strtoul(argv[12], NULL, 16); + } else { + HPRE_TST_PRT("pls use ./test_hisi_hpre -help get details!\n"); + return -EINVAL; + } + + if (argc >= 14) { + if (!strcmp(argv[13], "set-sha1")) + set_hash = HASH_SHA1; + else if (!strcmp(argv[13], "set-sha224")) + set_hash = HASH_SHA224; + else if (!strcmp(argv[13], "set-sha256")) + set_hash = HASH_SHA256; + else if (!strcmp(argv[13], "set-sha384")) + set_hash = HASH_SHA384; + else if (!strcmp(argv[13], "set-sha512")) + set_hash = HASH_SHA512; + else if (!strcmp(argv[13], "set-sm3")) + set_hash = HASH_SM3; + else if (!strcmp(argv[13], "set-md4")) + set_hash = HASH_MD4; + else if (!strcmp(argv[13], "set-md5")) + set_hash = HASH_MD5; + else if (!strcmp(argv[13], "set-hash-non")) + set_hash = HASH_NON; + } + + if (argc >= 16) { + value = strtoul(argv[15], NULL, 10); + if (!strcmp(argv[14], "set-plaintext-len")) { + set_plaintext_len = value; + if (value > 32768) { + HPRE_TST_PRT("pls use ./test_hisi_hpre -help get details!\n"); + return -EINVAL; + } + } else if (!strcmp(argv[14], "set-rand-len")) { + if (set_rand != RAND_PARAM || value > 512) { + HPRE_TST_PRT("pls use ./test_hisi_hpre -help get details!\n"); + return -EINVAL; + } + set_randparam_len = value; + } else { + HPRE_TST_PRT("pls use ./test_hisi_hpre -help get details!\n"); + return -EINVAL; + } + } + } + + if (argc == 12) { + if (!strcmp(argv[10], "-seconds") || + !strcmp(argv[10], "-cycles")) { + value = strtoul(argv[11], NULL, 10); + if (!strcmp(argv[10], "-seconds")) { + t_seconds = value; + } else if (!strcmp(argv[10], "-cycles")) { + t_times = value; + } else { + HPRE_TST_PRT("pls use ./test_hisi_hpre -help get details!\n"); + return -EINVAL; + } + } else if (!strcmp(argv[10], "-dev")) { + strcpy(dev_path, argv[11]); + } else if (!strcmp(argv[10], "-node")) { + node_msk = strtoul(argv[11], NULL, 16); + } else { + HPRE_TST_PRT("pls use ./test_hisi_hpre -help get details!\n"); + return -EINVAL; + } + } + + if (argc == 11) { + if (alg_op_type > MAX_DH_TYPE && alg_op_type < MAX_ECDSA_TYPE) { + ecc_curve_name = argv[10]; + } else if (alg_op_type >= X25519_GEN && alg_op_type <= X25519_ASYNC_COMPUTE) { + ecc_curve_name = ""; + key_bits = 256; + } else if (alg_op_type >= X448_GEN && alg_op_type <= X448_ASYNC_COMPUTE) { + ecc_curve_name = ""; + key_bits = 448; + } else if (alg_op_type >= SM2_SIGN && alg_op_type <= SM2_ASYNC_KG) { + ecc_curve_name = ""; + if (!strcmp(argv[10], "set-rand-non")) + set_rand = RAND_NON; + else if (!strcmp(argv[10], "set-rand-param")) + set_rand = RAND_PARAM; + else if (!strcmp(argv[10], "set-rand-cb")) + set_rand = RAND_CB; + + if (!strcmp(argv[8], "set-dgst")) + set_msg = MSG_DIGEST; + else if (!strcmp(argv[8], "set-ptext-short")) + set_msg = MSG_SHORT_PTEXT; + else if (!strcmp(argv[8], "set-ptext-long")) + set_msg = MSG_LONG_PTEXT; + key_bits = 256; + } else { + if (!strcmp(argv[10], "-g2")) { + g_mode = "-g2"; + } else if (!strcmp(argv[10], "-com")) { + g_mode = "-com"; + } else if (!strcmp(argv[10], "-crt")) { + g_mode = "-crt"; + } else { + HPRE_TST_PRT("pls use ./test_hisi_hpre -help get details!\n"); + return -EINVAL; + } + } + } + + HPRE_TST_PRT("Proc-%d: starts %d threads bind to %s\n", + getpid(), thread_num, argv[5]); + HPRE_TST_PRT(" lcoremask=0x%llx, hcoremask=0x%llx\n", + core_mask[0], core_mask[1]); + if (alg_op_type < MAX_RSA_SYNC_TYPE || + alg_op_type == DH_GEN || alg_op_type == DH_COMPUTE || + alg_op_type == ECDH_GEN || alg_op_type == ECDH_COMPUTE || + alg_op_type == ECDSA_SIGN || alg_op_type == ECDSA_VERF || + alg_op_type == X25519_GEN || alg_op_type == X25519_COMPUTE || + alg_op_type == X448_GEN || alg_op_type == X448_COMPUTE || + alg_op_type == SM2_SIGN || alg_op_type == SM2_VERF || + alg_op_type == SM2_ENC || alg_op_type == SM2_DEC || + alg_op_type == SM2_KG) + return hpre_sys_test(thread_num, core_mask[0], + core_mask[1], alg_op_type, dev_path, node_msk); + else if (alg_op_type > MAX_RSA_SYNC_TYPE && alg_op_type < MAX_RSA_ASYNC_TYPE) + return rsa_async_test(thread_num, core_mask[0], + core_mask[1], alg_op_type); + else if (alg_op_type == DH_ASYNC_GEN || alg_op_type == DH_ASYNC_COMPUTE) + return dh_async_test(thread_num, core_mask[0], + core_mask[1], alg_op_type); + else if (alg_op_type == ECDH_ASYNC_GEN || alg_op_type == ECDH_ASYNC_COMPUTE || + alg_op_type == ECDSA_ASYNC_SIGN || alg_op_type == ECDSA_ASYNC_VERF || + alg_op_type == X25519_ASYNC_GEN || alg_op_type == X25519_ASYNC_COMPUTE || + alg_op_type == X448_ASYNC_GEN || alg_op_type == X448_ASYNC_COMPUTE || + alg_op_type == SM2_ASYNC_SIGN || alg_op_type == SM2_ASYNC_VERF || + alg_op_type == SM2_ASYNC_ENC || alg_op_type == SM2_ASYNC_DEC || + alg_op_type == SM2_ASYNC_KG) + return ecc_async_test(thread_num, core_mask[0], + core_mask[1], alg_op_type); + else + return -1; /* to extend other test samples */ + } +basic_function_test: + if (!strcmp(argv[1], "-en")) { + alg_op_type = RSA_PUB_EN; + HPRE_TST_PRT("RSA public key encrypto\n"); + } else if (!strcmp(argv[1], "-de")) { + alg_op_type = RSA_PRV_DE; + HPRE_TST_PRT("RSA private key decrypto\n"); + } else if (!strcmp(argv[1], "-gen")) { + HPRE_TST_PRT("RSA key generation\n"); + alg_op_type = RSA_KEY_GEN; + } else if (!strcmp(argv[1], "-gen1")) { + HPRE_TST_PRT("DH key generation\n"); + alg_op_type = DH_GEN; + } else if (!strcmp(argv[1], "-x25519-gen1")) { + alg_op_type = X25519_GEN; + HPRE_TST_PRT("X25519 phase1 key generate.\n"); + } else if (!strcmp(argv[1], "-x25519-gen2")) { + alg_op_type = X25519_COMPUTE; + HPRE_TST_PRT("X25519 phase2 share-key generate.\n"); + } else if (!strcmp(argv[1], "-x448-gen1")) { + alg_op_type = X448_GEN; + HPRE_TST_PRT("X448 phase1 key generate.\n"); + } else if (!strcmp(argv[1], "-x448-gen2")) { + alg_op_type = X448_COMPUTE; + HPRE_TST_PRT("X448 phase2 share-key generate.\n"); + } else if (!strcmp(argv[1], "-rsa-num")) { + printf("num %d\n", wd_get_available_dev_num("rsa")); + return 0; + } else if (!strcmp(argv[1], "-dh-num")) { + printf("num %d\n", wd_get_available_dev_num("dh")); + return 0; + } else if (!strcmp(argv[1], "-zip-num")) { + printf("num %d\n", wd_get_available_dev_num("zip")); + return 0; + } else if (!strcmp(argv[1], "-ecxdh-num")) { + printf("num %d\n", wd_get_available_dev_num("ecdh")); + return 0; + } else if (!strcmp(argv[1], "-ec-num")) { + printf("num %d\n", wd_get_available_dev_num("ec")); + return 0; + } else if (!strcmp(argv[1], "-xx-num")) { + printf("num %d\n", wd_get_available_dev_num("xx")); + return 0; + } else if (!strcmp(argv[1], "--help")) { + HPRE_TST_PRT("[version]:1.0\n"); + HPRE_TST_PRT("NAME\n"); + HPRE_TST_PRT(" test_hisi_hpre: test wd hpre function,etc\n"); + HPRE_TST_PRT(" example 1: test_hisi_hpre -system-asgn -t 1 -c 0x2 -performance -nocheck 2048 2\n"); + HPRE_TST_PRT(" example 2: test_hisi_hpre -gen1 256 -g2 public private crt_private -check hisi_hpre-0\n"); + HPRE_TST_PRT(" example 3: test_hisi_hpre -system-gen1-ecc -t 1 -c 0x2 -log -check 256 2 secp128R1\n"); + HPRE_TST_PRT("SYNOPSIS\n"); + HPRE_TST_PRT(" test_hisi_hpre [op_type] -t [thread_num] -c [core_mask] [log] [openssl_check] [key_bits]...[ctx_num_per_q] [mode] [others]\n"); + HPRE_TST_PRT(" test_hisi_hpre [op_type] -t [thread_num] -c [core_mask] [log] [openssl_check] [key_bits]...[ctx_num_per_q] [curve] [others]\n"); + HPRE_TST_PRT(" test_hisi_hpre [op_type] [key_bits] [mode] [in] [out] [key_file] [openssl_check] [dev_path]...[others]\n"); + HPRE_TST_PRT("DESCRIPTION\n"); + HPRE_TST_PRT(" [op_type]:\n"); + HPRE_TST_PRT(" -system-qt = queue request and release test\n"); + HPRE_TST_PRT(" -system-gen = RSA key generate synchronize test\n"); + HPRE_TST_PRT(" -system-agen = RSA key generate c test\n"); + HPRE_TST_PRT(" -system-sgn = RSA signature synchronize test\n"); + HPRE_TST_PRT(" -system-asgn = RSA signature asynchronize test\n"); + HPRE_TST_PRT(" -system-vrf = RSA verification synchronize test\n"); + HPRE_TST_PRT(" -system-avrf = RSA verification asynchronize test\n"); + HPRE_TST_PRT(" -system-gen1 = DH phase 1 key generate synchronize test\n"); + HPRE_TST_PRT(" -system-agen1 = DH phase 1 key generate asynchronize test\n"); + HPRE_TST_PRT(" -system-gen2 = DH phase 2 key generate synchronize test\n"); + HPRE_TST_PRT(" -system-agen2 = DH phase 2 key generate asynchronize test\n"); + HPRE_TST_PRT(" -system-gen1-ecc = ECXDH phase 1 key generate synchronize test\n"); + HPRE_TST_PRT(" -system-agen1-ecc = ECXDH phase 1 key generate asynchronize test\n"); + HPRE_TST_PRT(" -system-gen2-ecc = ECXDH phase 2 key generate synchronize test\n"); + HPRE_TST_PRT(" -system-agen2-ecc = ECXDH phase 2 key generate asynchronize test\n"); + HPRE_TST_PRT(" -gen1 = DH share key generate test\n"); + HPRE_TST_PRT(" -registerlog-0 = register null log interface\n"); + HPRE_TST_PRT(" -registerlog-1 = register normal log interface\n"); + HPRE_TST_PRT(" -registerlog-2 = register dumplicate log interface\n"); + HPRE_TST_PRT(" -registerlog-3 = register unnormal log interface\n"); + HPRE_TST_PRT(" [thread_num]: start thread total\n"); + HPRE_TST_PRT(" [core_mask]: mask for bind cpu core, as 0x3 bind to cpu-1 and cpu-2\n"); + HPRE_TST_PRT(" [log]:\n"); + HPRE_TST_PRT(" -log\n"); + HPRE_TST_PRT(" -nolog\n"); + HPRE_TST_PRT(" -performance: use test DH and RSA perf\n"); + HPRE_TST_PRT(" [openssl_check]:\n"); + HPRE_TST_PRT(" 1: check result compared with openssl\n"); + HPRE_TST_PRT(" 0: no check\n"); + HPRE_TST_PRT(" [key_bits]:key size (bits)\n"); + HPRE_TST_PRT(" [ctx_num_per_q]:run ctx number per queue\n"); + HPRE_TST_PRT(" [mode]:\n"); + HPRE_TST_PRT(" -g2 = DH G2 mode\n"); + HPRE_TST_PRT(" -com = common mode\n"); + HPRE_TST_PRT(" -crt = RSA CRT mode\n"); + HPRE_TST_PRT(" [curve]:\n"); + HPRE_TST_PRT(" secp128R1 = 128 bit\n"); + HPRE_TST_PRT(" secp192K1 = 192 bit\n"); + HPRE_TST_PRT(" secp256K1 = 256bit\n"); + HPRE_TST_PRT(" brainpoolP320R1 = 320bit\n"); + HPRE_TST_PRT(" brainpoolP384R1 = 384bit\n"); + HPRE_TST_PRT(" secp521R1 = 521bit\n"); + HPRE_TST_PRT(" null = by set parameters\n"); + HPRE_TST_PRT(" [dev_path]: designed dev path\n"); + HPRE_TST_PRT(" [others]:\n"); + HPRE_TST_PRT(" -seconds [10] = test time set (s), for 10s\n"); + HPRE_TST_PRT(" -cycles [10] = test cycle set (times), for 10 times\n"); + HPRE_TST_PRT(" -dev [hisi_hpre-0] = denote device path\n"); + HPRE_TST_PRT(" -node [1] = denote device numa node\n"); + HPRE_TST_PRT(" [--help] = usage\n"); + return 0; + } else { + HPRE_TST_PRT("Unknown option\n"); + HPRE_TST_PRT("<>\n"); + return -EINVAL; + } + if (argv[2]) { + key_bits = strtoul(argv[2], NULL, 10); + if (key_bits != 1024 && key_bits != 2048 && + key_bits != 3072 && key_bits != 4096) { + key_bits = 2048; + } + } else { + key_bits = 2048; + } + HPRE_TST_PRT("RSA/DH key size=%d bits\n", key_bits); + if (!strcmp(argv[3], "-crt")) { + HPRE_TST_PRT("RSA CRT mode\n"); + mode = RSA_CRT_MD; + } else if (!strcmp(argv[3], "-com") && alg_op_type < MAX_RSA_ASYNC_TYPE) { + HPRE_TST_PRT("RSA Common mode\n"); + mode = RSA_COM_MD; + } else if (!strcmp(argv[3], "-com") && alg_op_type > MAX_RSA_ASYNC_TYPE) { + HPRE_TST_PRT("DH Common mode\n"); + mode = DH_COM_MD; + } else if (!strcmp(argv[3], "-g2")) { + HPRE_TST_PRT("DH g2 mode\n"); + mode = DH_G2; + } else { + HPRE_TST_PRT("please input a mode:<-crt> <-com>for rsa!\n"); + HPRE_TST_PRT("and:<-g2> <-com>for dh!\n"); + return -EINVAL; + } + in_file = argv[4]; + out_file = argv[5]; + key_file = argv[6]; + memset((void *)&q, 0, sizeof(q)); + if (argc >= 9) { + strcpy(q.dev_path, argv[8]); + HPRE_TST_PRT("denote dev path:%s\n", argv[8]); + } + + if (argc >= 10) { + q.node_mask = strtoul(argv[9], NULL, 16); + HPRE_TST_PRT("denote node_id %d\n", q.node_mask); + } + + if (alg_op_type < MAX_RSA_ASYNC_TYPE && alg_op_type > HPRE_ALG_INVLD_TYPE) { + q.capa.alg = "rsa"; + } else if (alg_op_type < MAX_DH_TYPE && + alg_op_type > MAX_RSA_ASYNC_TYPE) { + q.capa.alg = "dh"; + } else { + HPRE_TST_PRT("op type err!\n"); + return -EINVAL; + } + ret = wd_request_queue(&q); + if (ret) { + HPRE_TST_PRT("request queue fail!\n"); + return ret; + } + HPRE_TST_PRT("Get a WD HPRE queue of %s successfully!\n", q.capa.alg); + memset(&dh_setup, 0, sizeof(dh_setup)); + memset(&setup, 0, sizeof(setup)); + if (alg_op_type < MAX_RSA_ASYNC_TYPE && mode == RSA_CRT_MD) { + setup.is_crt = 1; + } else if (alg_op_type < MAX_RSA_ASYNC_TYPE && mode == RSA_COM_MD) { + setup.is_crt = 0; + } else if (alg_op_type > MAX_RSA_ASYNC_TYPE && + alg_op_type < HPRE_MAX_OP_TYPE && mode == DH_COM_MD) { + dh_setup.is_g2 = 0; + } else if (alg_op_type > MAX_RSA_ASYNC_TYPE && + alg_op_type < HPRE_MAX_OP_TYPE && mode == DH_G2) { + dh_setup.is_g2 = 1; + } else { + HPRE_TST_PRT("op type or mode err!\n"); + ret = -ENOMEM; + goto release_q; + } + + struct wd_blkpool_setup wsetup; + memset(&wsetup, 0, sizeof(wsetup)); + if (!strncmp(q.capa.alg, "rsa", 3)) + wsetup.block_size = (key_bits >> 4) * 7; + else if (!strncmp(q.capa.alg, "dh", 2)) + wsetup.block_size = key_bits >> 2; + wsetup.block_num = block_num; + wsetup.align_size = 64; + + pool = wd_blkpool_create(&q, &wsetup); + if (!pool) { + HPRE_TST_PRT("%s(): create ctx pool fail!\n", __func__); + return -EINVAL; + } + + if (!strncmp(q.capa.alg, "rsa", 3)) { + setup.key_bits = key_bits; + + setup.br.alloc = (void *)wd_alloc_blk; + setup.br.free = (void *)wd_free_blk; + setup.br.iova_map = (void *)wd_blk_iova_map; + setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + setup.br.get_bufsize = (void *)wd_blksize; + setup.br.usr = pool; + ctx = wcrypto_create_rsa_ctx(&q, &setup); + if (!ctx) { + ret = -ENOMEM; + HPRE_TST_PRT("create rsa ctx fail!\n"); + goto release_q; + } + } else if (!strncmp(q.capa.alg, "dh", 2)) { + dh_setup.key_bits = key_bits; + + dh_setup.br.alloc = (void *)wd_alloc_blk; + dh_setup.br.free = (void *)wd_free_blk; + dh_setup.br.iova_map = (void *)wd_blk_iova_map; + dh_setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + dh_setup.br.get_bufsize = (void *)wd_blksize; + dh_setup.br.usr = pool; + ctx = wcrypto_create_dh_ctx(&q, &dh_setup); + if (!ctx) { + ret = -ENOMEM; + HPRE_TST_PRT("create dh ctx fail!\n"); + goto release_q; + } + } + + if (alg_op_type == RSA_KEY_GEN) { + /* As generate key, we take in_file for storing public key + * and out_file for storing private key. + */ +#ifdef RSA_OP_DEBUG + return hpre_test_rsa_op(alg_op_type, ctx, (__u8 *)in_file, + key_bits >> 3, (__u8 *)out_file, (__u8 *)key_file); +#else + HPRE_TST_PRT("hpre_test_rsa_op not supported currently!\n"); + return 0; +#endif + } else if (alg_op_type == DH_GEN) { + ret = hpre_dh_test(ctx, pool); + wcrypto_del_dh_ctx(ctx); + return ret; + } else if (alg_op_type == RSA_PUB_EN && (mode == RSA_CRT_MD || + mode == RSA_COM_MD)) { + read_size = pub_key_size = key_bits >> 2; + } else if (alg_op_type == RSA_PRV_DE && mode == RSA_CRT_MD) { + read_size = priv_key_size = (key_bits >> 4) * 5; + } else if (alg_op_type == RSA_PRV_DE && mode == RSA_COM_MD) { + read_size = priv_key_size = key_bits >> 2; + } else { + HPRE_TST_PRT("op=%d mode=%d CMD err!\n", alg_op_type, mode); + ret = -EINVAL; + goto release_q; + } + if (openssl_check && alg_op_type != RSA_PUB_EN) + key_info_size = read_size + (key_bits >> 2); + else + key_info_size = read_size; + + /* while we check the hw result, we need more info such as n and e */ + key = malloc(key_info_size); + if (!key) { + HPRE_TST_PRT("malloc key fail!\n"); + ret = -ENOMEM; + goto release_q; + } + ret = hpre_test_read_from_file(key, key_file, key_info_size); + if (ret < 0 || key_info_size != ret) { + HPRE_TST_PRT("Fail to get key from %s!\n", key_file); + HPRE_TST_PRT("Please input right RSA key!\n"); + goto release_q; + } + + /* Try to get the input file size */ + read_size = hpre_test_get_file_size(in_file); + if (read_size <= 0) { + HPRE_TST_PRT("%s file is not valid!\n", in_file); + goto release_q; + } + + in = malloc(read_size + (key_bits >> 3)); + if (!in) { + HPRE_TST_PRT("Fail to malloc mem for %s!\n", in_file); + goto release_q; + } + memset(in, 0, read_size + (key_bits >> 3)); + ret = hpre_test_read_from_file(in, in_file, read_size); + if (ret != read_size) { + HPRE_TST_PRT("Fail to get data from %s!\n", in_file); + goto release_q; + } + out = malloc(key_bits >> 3); + if (!out) { + HPRE_TST_PRT("Fail to malloc mem for output!\n"); + goto release_q; + } + memset(out, 0, key_bits >> 3); + + /* Initiated input Size */ + if (alg_op_type == RSA_PRV_DE) { + in_size = key_bits >> 3; + } else { + in_size = (key_bits >> 3) - HPRE_PADDING_SZ; + temp_in = malloc(key_bits >> 3); + if (!temp_in) { + HPRE_TST_PRT("Fail to malloc mem for temp in!\n"); + goto release_q; + } + memset(temp_in, 0, key_bits >> 3); + } + tp_in = in; + do { + /* While read_size is small the key size, it is finished */ + if (read_size - in_size > 0) { + op_size = in_size; + try_close = 0; + } else { + op_size = read_size; + try_close = 1; + } +#ifdef RSA_OP_DEBUG + if (alg_op_type == RSA_PUB_EN) { + memcpy(temp_in, tp_in, op_size); + ret = hpre_test_rsa_op(alg_op_type, ctx, temp_in, op_size, out, key); + } else { + ret = hpre_test_rsa_op(alg_op_type, ctx, tp_in, op_size, out, key); + } +#endif + if (ret < 0) { + HPRE_TST_PRT("HPRE operates failing!\n"); + goto release_q; + } + + ret = hpre_test_write_to_file(out, ret, out_file, + out_fd, try_close); + if (ret < 0) { + HPRE_TST_PRT("Fail to write output buffer to %s!\n", + out_file); + goto release_q; + } + if (key) { + free(key); + key = NULL; + } + if (try_close && openssl_check) { + if (alg_op_type == RSA_PUB_EN) + HPRE_TST_PRT("HPRE pub encrypt"\ + " %s to %s success!\n", in_file, out_file); + else + HPRE_TST_PRT("HPRE priv decrypt"\ + " %s to %s success!\n", in_file, out_file); + } else if (try_close) { + if (alg_op_type == RSA_PUB_EN) + HPRE_TST_PRT("HPRE pub encrypt"\ + " %s to %s finished!\n", in_file, out_file); + else + HPRE_TST_PRT("HPRE priv decrypt"\ + " %s to %s finished!\n", in_file, out_file); + } + out_fd = ret; + tp_in += op_size; + read_size -= op_size; + } while (!try_close); +release_q: + if (in) + free(in); + if (out) + free(out); + if (key) + free(key); + if (temp_in) + free(temp_in); + + wcrypto_del_rsa_ctx(ctx); + wd_blkpool_destroy(pool); + wd_release_queue(&q); + + return ret; +} diff --git a/uadk/v1/test/hisi_hpre_test/test_hisi_hpre.h b/uadk/v1/test/hisi_hpre_test/test_hisi_hpre.h new file mode 100644 index 0000000..567a816 --- /dev/null +++ b/uadk/v1/test/hisi_hpre_test/test_hisi_hpre.h @@ -0,0 +1,100 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#ifndef __HISI_TEST_HPRE_H +#define __HISI_TEST_HPRE_H + + + +enum alg_op_type { + HPRE_ALG_INVLD_TYPE, + RSA_KEY_GEN, + RSA_PUB_EN, + RSA_PRV_DE, + MAX_RSA_SYNC_TYPE, + RSA_ASYNC_EN, + RSA_ASYNC_DE, + RSA_ASYNC_GEN, + MAX_RSA_ASYNC_TYPE, + DH_GEN, + DH_ASYNC_GEN, + DH_COMPUTE, + DH_ASYNC_COMPUTE, + MAX_DH_TYPE, + ECDH_GEN, + ECDH_COMPUTE, + ECDH_ASYNC_GEN, + ECDH_ASYNC_COMPUTE, + MAX_ECDH_TYPE, + ECDSA_SIGN, + ECDSA_VERF, + ECDSA_ASYNC_SIGN, + ECDSA_ASYNC_VERF, + MAX_ECDSA_TYPE, + X25519_GEN, + X25519_COMPUTE, + X25519_ASYNC_GEN, + X25519_ASYNC_COMPUTE, + X448_GEN, + X448_COMPUTE, + X448_ASYNC_GEN, + X448_ASYNC_COMPUTE, + SM2_SIGN, + SM2_VERF, + SM2_ENC, + SM2_DEC, + SM2_KG, + SM2_ASYNC_SIGN, + SM2_ASYNC_VERF, + SM2_ASYNC_ENC, + SM2_ASYNC_DEC, + SM2_ASYNC_KG, + MAX_ECC_TYPE, + HPRE_MAX_OP_TYPE +}; + +enum alg_op_mode { + HPRE_ALG_INVLD_MODE, + RSA_COM_MD, + RSA_CRT_MD, + DH_COM_MD, + DH_G2, + HPRE_MAX_OP_MODE, +}; + + + +struct hpre_queue_mempool { + struct wd_queue *q; + void *base; + unsigned int *bitmap; + unsigned int block_size; + unsigned int block_num; + unsigned int mem_size; + unsigned int block_align_size; + unsigned int free_num; + unsigned int fail_times; + unsigned long long index; + sem_t sem; + int dev; +}; + +struct hpre_queue_mempool *hpre_test_mempool_create(struct wd_queue *q, + unsigned int block_size, unsigned int block_num); +void hpre_test_mempool_destroy(struct hpre_queue_mempool *pool); +void *hpre_test_alloc_buf(struct hpre_queue_mempool *pool, size_t sz); +void hpre_test_free_buf(struct hpre_queue_mempool *pool, void *buf); +#endif diff --git a/uadk/v1/test/hisi_hpre_test/test_hisi_hpre_times.c b/uadk/v1/test/hisi_hpre_test/test_hisi_hpre_times.c new file mode 100644 index 0000000..4a8009c --- /dev/null +++ b/uadk/v1/test/hisi_hpre_test/test_hisi_hpre_times.c @@ -0,0 +1,4909 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +//#define DEBUG + +#include +#include +#include +#define __USE_GNU +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "test_hisi_hpre.h" +#include "../../wd.h" +#include "../../wd_rsa.h" +#include "../../wd_dh.h" +#include "../../wd_bmm.h" +#include "../../wd_util.h" + +#define HPRE_TST_PRT printf +#define BN_ULONG unsigned long +#define RSA_NO_PADDING 3 +#define HPRE_TST_MAX_Q 1 +#define HPRE_PADDING_SZ 16 +#define TEST_MAX_THRD 128 +#define MAX_TRY_TIMES 10000 +#define LOG_INTVL_NUM 8 +#define WD_RSA_CTX_MSG_NUM 64 +#define WD_DH_CTX_MSG_NUM 64 +#define DH_GENERATOR_2 2 +#define DH_GENERATOR_5 5 +#define TEST_CNT 10 + +typedef unsigned int u32; + +struct big_number { + BN_ULONG *n; + int latest; + int size_d; + int flag_neg; + int flags; +}; + +/* stub structures */ +struct rsa_st { + int xxx; +}; + +struct dh_st { + int xxx; +}; + +struct bn_gencb_st { + int xxx; +}; + +struct test_hpre_pthread_dt { + int cpu_id; + enum alg_op_type op_type; + int thread_num; + void *pool; + void *q; + struct timeval start_tval; + u32 send_task_num; + u32 recv_task_num; +}; + +/* stub definitions */ +typedef struct rsa_st RSA; +typedef struct dh_st DH; +typedef struct big_number BIGNUM; +typedef struct bn_gencb_st BN_GENCB; + +enum dh_check_index { + DH_INVALID, + DH_ALICE_PUBKEY, + DH_BOB_PUBKEY, + DH_ALICE_PRIVKEY +}; + +struct rsa_async_tag { + void *ctx; + int thread_id; + int cnt; + struct test_hpre_pthread_dt *thread_info; +}; + +struct dh_user_tag_info { + u32 op; + int pid; + int thread_id; + void *test_ctx; + void *thread_data; +}; + +struct async_test_openssl_param { + RSA *rsa; + BIGNUM *p; + BIGNUM *q; + BIGNUM *e; + BIGNUM *n; + BIGNUM *d; + BIGNUM *dp; + BIGNUM *dq; + BIGNUM *qinv; + void *ssl_verify_result; + void *ssl_sign_result; + void *plantext; + int size; +}; + +static int key_bits = 2048; +static int openssl_check; +static int only_soft; +static int performance_test = 1; +static int t_times = 10; +static int t_seconds = 0; +static int with_log; +static int is_system_test; +static int ctx_num_per_q = 1; +static int q_num = 1; +static char *g_mode = "-crt"; +static volatile int asyn_thread_exit = 0; + +static __thread RSA *hpre_test_rsa; +static pthread_t system_test_thrds[TEST_MAX_THRD]; +static struct test_hpre_pthread_dt test_thrds_data[TEST_MAX_THRD]; +static struct async_test_openssl_param ssl_params; + +static char *rsa_op_str[WCRYPTO_RSA_GENKEY + 1] = { + "invalid_op", + "rsa_sign", + "rsa_verify", + "rsa_keygen", +}; + +static char *dh_op_str[WCRYPTO_DH_PHASE2] = { + "ph1", + "ph2" +}; + +static char *rsa_op_str_perf[WCRYPTO_RSA_GENKEY + 1] = { + "invalid_op", + "sign", + "verify", + "gen", +}; + +char dh_g_5[] = {0x05}; +char dh_g_2[] = {0x02}; + +char dh_p_768[] = { + 0xdd, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x01, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7 +}; + +char dh_xa_768[] = { + 0xe0, 0x80, 0x86, 0x24, 0xe2, 0x20, 0x35, 0x97, 0xda, 0x0e, 0x68, 0x39, 0x01, 0xdd, 0x01, 0x87, + 0xa2, 0x47, 0xd2, 0x0d, 0xee, 0xfe, 0xdc, 0x5a, 0x37, 0x23, 0xeb, 0x3d, 0xe8, 0x1e, 0x39, 0x2d, + 0xbf, 0xa6, 0xe9, 0x17, 0x48, 0xe2, 0xea, 0xef, 0x1d, 0x2f, 0xe2, 0xaf, 0x3c, 0xbc, 0xae, 0xa7, + 0x42, 0x9b, 0xa5, 0x7d, 0x47, 0x8a, 0x20, 0xc5, 0xae, 0xa1, 0xe4, 0xe8, 0x1c, 0x05, 0xc0, 0x0a, + 0x05, 0xdc, 0x01, 0x74, 0xde, 0xad, 0xad, 0x07, 0xec, 0x6e, 0x6a, 0xc7, 0xee, 0x0f, 0xb8, 0xbe, + 0xaa, 0x46, 0x61, 0x8c, 0x12, 0x5a, 0xaf, 0x05, 0xff, 0x1b, 0x35, 0x6b, 0xe2, 0x3d, 0x48, 0x4f +}; + +char dh_xb_768[] = { + 0x8b, 0xd9, 0xf8, 0x14, 0xe6, 0x42, 0x95, 0xbd, 0x9a, 0x96, 0xbe, 0xf4, 0x7d, 0x26, 0x5d, 0xa1, + 0x81, 0x9b, 0x1c, 0xec, 0xfe, 0xce, 0x9, 0x1d, 0xb7, 0x7a, 0xba, 0xca, 0x7f, 0x54, 0xee, 0x36, + 0x54, 0x65, 0x4a, 0xd0, 0x5c, 0x84, 0x8c, 0x3e, 0x1b, 0xfe, 0x91, 0x6f, 0x95, 0xb5, 0x76, 0xbf, + 0x61, 0x2a, 0x7, 0x23, 0x86, 0xb9, 0xe0, 0x19, 0x29, 0xcf, 0xea, 0x3a, 0x1, 0xbf, 0xee, 0x1b, + 0x5e, 0x3c, 0x4, 0xff, 0x1d, 0xcf, 0xa6, 0x56, 0xb3, 0x22, 0xbb, 0x45, 0x4b, 0x7f, 0x83, 0x87, + 0xef, 0x21, 0x5, 0xf7, 0x38, 0x1f, 0x6, 0x4d, 0x71, 0x0b, 0xe3, 0xe1, 0xb7, 0x7e, 0xae, 0x18 +}; + +char dh_except_a_pubkey_768[] = { + 0xba, 0xe7, 0x3, 0x5b, 0xe4, 0x70, 0x8b, 0xe0, 0xe1, 0x92, 0x13, 0x86, 0x74, 0x4, 0xdc, 0x6a, + 0x0a, 0x2a, 0x20, 0xec, 0x6d, 0xbf, 0xf0, 0x46, 0xf7, 0x9, 0x2, 0xdb, 0x2f, 0x70, 0x11, 0xdd, + 0xb0, 0x13, 0xa2, 0xc1, 0x58, 0x74, 0x29, 0x19, 0x8d, 0x4a, 0x94, 0x80, 0x0b, 0xd7, 0x25, 0x85, + 0x10, 0x35, 0x97, 0x48, 0x6e, 0x70, 0x28, 0xae, 0x58, 0x97, 0x7d, 0xf2, 0x19, 0x27, 0x13, 0xab, + 0x47, 0x9b, 0x54, 0xdf, 0xc3, 0x5b, 0x5f, 0x5e, 0xb4, 0x64, 0x47, 0xce, 0x40, 0x3b, 0x0c, 0x4a, + 0x62, 0x52, 0xba, 0xc7, 0xf0, 0x36, 0x87, 0x9c, 0x79, 0x9a, 0x83, 0x11, 0x61, 0x0c, 0x1b, 0x6b +}; + +char dh_except_b_pubkey_768[] = { + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x1, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7 +}; + +char dh_share_key_768[] = { + 0x55, 0x9, 0x6b, 0x9c, 0xc6, 0x37, 0xa9, 0x9b, 0xdf, 0x67, 0x73, 0x7b, 0x46, 0xf9, 0x63, 0x47, + 0xcb, 0xa0, 0x57, 0x2a, 0xed, 0x97, 0x2f, 0xfe, 0x92, 0xf2, 0x20, 0x2c, 0x7e, 0xee, 0x7d, 0x11, + 0x78, 0xe6, 0xb9, 0x9, 0xd1, 0x94, 0xce, 0xd1, 0x5b, 0xf4, 0x44, 0xa9, 0xcb, 0x26, 0x2, 0x36, + 0x57, 0x2c, 0xa2, 0xbe, 0x37, 0xde, 0x86, 0x46, 0x20, 0x27, 0x9d, 0xa0, 0x2f, 0x4, 0xc1, 0xcd, + 0xff, 0x81, 0xe5, 0xe6, 0x2c, 0x9e, 0x39, 0x82, 0x31, 0x54, 0x33, 0xf8, 0xe7, 0xa0, 0xe5, 0x96, + 0xa4, 0x40, 0xc4, 0x44, 0xfe, 0x93, 0x66, 0xe2, 0xda, 0xaa, 0xb8, 0xfb, 0x2f, 0x3b, 0x8c, 0xce, +}; + +char dh_p_1024[] = { + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x07, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x03, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x01, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7 +}; + +char dh_xa_1024[] = { + 0x0f, 0x2a, 0x77, 0x25, 0x4b, 0xb3, 0xd3, 0x2d, 0xfd, 0x94, 0x8b, 0x53, 0x02, 0x21, 0x40, 0xd7, + 0x36, 0x76, 0xf3, 0xc8, 0xc0, 0x36, 0x3d, 0x23, 0xc9, 0xbd, 0x92, 0x51, 0xf2, 0x4b, 0x83, 0x15, + 0xe0, 0x80, 0x86, 0x24, 0xe2, 0x20, 0x35, 0x97, 0xda, 0x0e, 0x68, 0x39, 0x01, 0xdd, 0x01, 0x87, + 0xa2, 0x47, 0xd2, 0x0d, 0xee, 0xfe, 0xdc, 0x5a, 0x37, 0x23, 0xeb, 0x3d, 0xe8, 0x1e, 0x39, 0x2d, + 0xbf, 0xa6, 0xe9, 0x17, 0x48, 0xe2, 0xea, 0xef, 0x1d, 0x2f, 0xe2, 0xaf, 0x3c, 0xbc, 0xae, 0xa7, + 0x42, 0x9b, 0xa5, 0x7d, 0x47, 0x8a, 0x20, 0xc5, 0xae, 0xa1, 0xe4, 0xe8, 0x1c, 0x05, 0xc0, 0x0a, + 0x05, 0xdc, 0x01, 0x74, 0xde, 0xad, 0xad, 0x07, 0xec, 0x6e, 0x6a, 0xc7, 0xee, 0x0f, 0xb8, 0xbe, + 0xaa, 0x46, 0x61, 0x8c, 0x12, 0x5a, 0xaf, 0x05, 0xff, 0x1b, 0x35, 0x6b, 0xe2, 0x3d, 0x48, 0x4f +}; + +char dh_xb_1024[] = { + 0x5e, 0x21, 0x0a, 0x9e, 0x3, 0xdd, 0x3f, 0xcc, 0x38, 0xf6, 0xa9, 0xa6, 0xf8, 0xfd, 0x15, 0x7d, + 0x67, 0x4e, 0x14, 0xae, 0x4d, 0xe2, 0x1f, 0x78, 0x77, 0xfb, 0x83, 0x5f, 0x48, 0xa8, 0xc8, 0x21, + 0x8b, 0xd9, 0xf8, 0x14, 0xe6, 0x42, 0x95, 0xbd, 0x9a, 0x96, 0xbe, 0xf4, 0x7d, 0x26, 0x5d, 0xa1, + 0x81, 0x9b, 0x1c, 0xec, 0xfe, 0xce, 0x9, 0x1d, 0xb7, 0x7a, 0xba, 0xca, 0x7f, 0x54, 0xee, 0x36, + 0x54, 0x65, 0x4a, 0xd0, 0x5c, 0x84, 0x8c, 0x3e, 0x1b, 0xfe, 0x91, 0x6f, 0x95, 0xb5, 0x76, 0xbf, + 0x61, 0x2a, 0x7, 0x23, 0x86, 0xb9, 0xe0, 0x19, 0x29, 0xcf, 0xea, 0x3a, 0x1, 0xbf, 0xee, 0x1b, + 0x5e, 0x3c, 0x4, 0xff, 0x1d, 0xcf, 0xa6, 0x56, 0xb3, 0x22, 0xbb, 0x45, 0x4b, 0x7f, 0x83, 0x87, + 0xef, 0x21, 0x5, 0xf7, 0x38, 0x1f, 0x6, 0x4d, 0x71, 0x0b, 0xe3, 0xe1, 0xb7, 0x7e, 0xae, 0x18 +}; + +char dh_except_a_pubkey_1024[] = { + 0x5d, 0xa6, 0x7, 0x56, 0x93, 0x89, 0xe5, 0x0f, 0x2a, 0xb5, 0x67, 0x3a, 0xcf, 0xc3, 0x82, 0x83, + 0xf6, 0x88, 0x52, 0x0b, 0xfc, 0x6a, 0x5b, 0x1a, 0x57, 0x87, 0x86, 0xef, 0xda, 0x47, 0xdb, 0x4d, + 0xba, 0xe7, 0x3, 0x5b, 0xe4, 0x70, 0x8b, 0xe0, 0xe1, 0x92, 0x13, 0x86, 0x74, 0x4, 0xdc, 0x6a, + 0x0a, 0x2a, 0x20, 0xec, 0x6d, 0xbf, 0xf0, 0x46, 0xf7, 0x9, 0x2, 0xdb, 0x2f, 0x70, 0x11, 0xdd, + 0xb0, 0x13, 0xa2, 0xc1, 0x58, 0x74, 0x29, 0x19, 0x8d, 0x4a, 0x94, 0x80, 0x0b, 0xd7, 0x25, 0x85, + 0x10, 0x35, 0x97, 0x48, 0x6e, 0x70, 0x28, 0xae, 0x58, 0x97, 0x7d, 0xf2, 0x19, 0x27, 0x13, 0xab, + 0x47, 0x9b, 0x54, 0xdf, 0xc3, 0x5b, 0x5f, 0x5e, 0xb4, 0x64, 0x47, 0xce, 0x40, 0x3b, 0x0c, 0x4a, + 0x62, 0x52, 0xba, 0xc7, 0xf0, 0x36, 0x87, 0x9c, 0x79, 0x9a, 0x83, 0x11, 0x61, 0x0c, 0x1b, 0x6b +}; + +char dh_except_b_pubkey_1024[] = { + 0x4a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x7, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x3, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x1, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7 +}; + +char dh_share_key_1024[] = { + 0xcc, 0x48, 0x97, 0xe4, 0x21, 0x65, 0xa6, 0x55, 0xb8, 0xf3, 0xb2, 0x7b, 0x91, 0xd7, 0xca, 0xb9, + 0x17, 0x58, 0x31, 0x71, 0xc0, 0xc9, 0x69, 0x1e, 0xf0, 0x9e, 0x3f, 0xe2, 0x37, 0x4, 0x2d, 0xa8, + 0x55, 0x9, 0x6b, 0x9c, 0xc6, 0x37, 0xa9, 0x9b, 0xdf, 0x67, 0x73, 0x7b, 0x46, 0xf9, 0x63, 0x47, + 0xcb, 0xa0, 0x57, 0x2a, 0xed, 0x97, 0x2f, 0xfe, 0x92, 0xf2, 0x20, 0x2c, 0x7e, 0xee, 0x7d, 0x11, + 0x78, 0xe6, 0xb9, 0x9, 0xd1, 0x94, 0xce, 0xd1, 0x5b, 0xf4, 0x44, 0xa9, 0xcb, 0x26, 0x2, 0x36, + 0x57, 0x2c, 0xa2, 0xbe, 0x37, 0xde, 0x86, 0x46, 0x20, 0x27, 0x9d, 0xa0, 0x2f, 0x4, 0xc1, 0xcd, + 0xff, 0x81, 0xe5, 0xe6, 0x2c, 0x9e, 0x39, 0x82, 0x31, 0x54, 0x33, 0xf8, 0xe7, 0xa0, 0xe5, 0x96, + 0xa4, 0x40, 0xc4, 0x44, 0xfe, 0x93, 0x66, 0xe2, 0xda, 0xaa, 0xb8, 0xfb, 0x2f, 0x3b, 0x8c, 0xce, +}; + +char dh_p_1536[] = { + 0xe3,0x7d,0xa7,0x4a,0xcc,0xef,0xce,0xa6,0xde,0x1d,0x3d,0xc5,0x2b,0xaa,0x6b,0x83, + 0xec,0x87,0x60,0xcd,0xc6,0xe4,0x16,0x0d,0xe7,0xb9,0x20,0x0e,0x10,0x50,0x35,0x22, + 0xd6,0xdb,0xbf,0x6,0xcc,0x7b,0x8e,0xe1,0x68,0x38,0x76,0x5f,0x0a,0x68,0xa8,0xfd, + 0x3f,0x40,0x51,0x46,0x45,0x64,0x53,0x22,0xcf,0x8,0xe2,0xef,0xd2,0x6f,0x28,0x84, + 0x14,0xb3,0xa6,0x24,0x49,0x6f,0x49,0x6c,0x0a,0x13,0xb6,0x78,0x4f,0xa4,0xd0,0xc4, + 0x20,0x6c,0x7,0x4c,0x6b,0xf7,0x8c,0x72,0x16,0x6c,0x99,0xd2,0x44,0x9e,0x63,0x5, + 0xfc,0x3a,0xa9,0x33,0x16,0x0b,0xc4,0x1a,0xf0,0xc7,0x25,0xcd,0xc6,0x3a,0x8e,0x66, + 0xa2,0xeb,0x70,0xb9,0x59,0xd9,0xb7,0xdd,0x68,0x45,0x26,0x20,0xfa,0x58,0x6f,0xd6, + 0x3f,0xd8,0xf2,0x52,0xd5,0x3a,0x16,0x7,0xdd,0xb4,0x63,0x0c,0xfe,0x8,0x67,0xd0, + 0x9f,0x8a,0xe0,0xe9,0x25,0xa0,0x0e,0x5,0x8e,0xe5,0x56,0xa6,0xc3,0x5b,0x0b,0xb5, + 0x41,0x33,0xd0,0xdb,0x89,0xbd,0x3b,0xaf,0x33,0x7e,0xae,0xff,0x20,0xef,0xa9,0x3c, + 0xd7,0xb5,0x45,0x61,0x50,0x76,0x60,0x89,0x6a,0xbb,0x9c,0x3e,0xcb,0xcb,0xdb,0x0b, +}; + +char dh_xa_1536[] = { + 0x56,0x68,0x23,0x22,0x49,0x24,0xf2,0x21,0xee,0x5f,0x12,0x46,0xe2,0xea,0x69,0x93, + 0x0,0xf5,0x10,0x1d,0x4d,0x96,0x7b,0xa4,0x9d,0xab,0xbe,0xdf,0x8e,0xcc,0xa5,0x0e, + 0x84,0x12,0x4e,0x77,0xc0,0x46,0x6b,0x51,0x11,0x46,0x4f,0x73,0x1e,0x1c,0x1c,0xd1, + 0x3,0xea,0x0e,0x11,0xdb,0xa3,0xa6,0x14,0xdb,0xdc,0x3e,0xc5,0x7f,0x7d,0x7a,0x69, + 0xa1,0x38,0x70,0x95,0xa5,0x2d,0x47,0xa3,0x0f,0xcf,0xf9,0x7c,0x2,0x4e,0x52,0x4c, + 0xd6,0x5b,0x9e,0xf3,0x7f,0x64,0x70,0x13,0x59,0x8e,0x44,0x31,0x92,0x1b,0xb4,0xaa, + 0xf9,0x64,0xfd,0xb7,0x3c,0x81,0xc0,0xf9,0x66,0x5d,0xff,0x9,0x3e,0x26,0xaf,0x1a, + 0xc0,0xd2,0xd9,0x7c,0x0e,0x6f,0x81,0x12,0x82,0x90,0x1b,0x37,0xb7,0x1a,0x7e,0x36, + 0x79,0x15,0xb1,0xe1,0xd5,0x2d,0x72,0xd4,0x47,0xf7,0x30,0x3c,0x17,0xe1,0x76,0x15, + 0xbc,0x17,0xdc,0x9d,0xd9,0xfc,0xfd,0xb6,0xe6,0xbd,0x8e,0x47,0x8d,0xbb,0xa8,0x8a, + 0xe7,0xe7,0x57,0xf2,0xd8,0x80,0x4c,0xdd,0xe7,0xaf,0x29,0xee,0x40,0x4e,0x2,0xad, + 0xec,0xb3,0x18,0x8e,0x4b,0x2d,0xd2,0x28,0x4e,0x58,0x85,0x29,0xe3,0x93,0x1b,0xa7, +}; + +char dh_xb_1536[] = { + 0x5c, 0xdf, 0x3, 0x2f, 0x18, 0xac, 0xbc, 0xeb, 0x95, 0xa2, 0x33, 0x70, 0x39, 0x13, 0x92, 0x7e, + 0x91, 0x19, 0x89, 0xd4, 0x0, 0xd1, 0xc5, 0x7e, 0x32, 0xb7, 0x4a, 0xd2, 0xff, 0x11, 0x7a, 0x9b, + 0x2, 0x84, 0xd0, 0x8e, 0x19, 0x91, 0x34, 0xc2, 0x5, 0xff, 0xe4, 0xf4, 0xd8, 0xcf, 0xc8, 0xa0, + 0xeb, 0x19, 0xb9, 0x69, 0x60, 0xcd, 0xa8, 0xda, 0x33, 0xbc, 0xa7, 0x80, 0x0, 0x92, 0x27, 0xe0, + 0xe7, 0x34, 0x77, 0x1f, 0xfd, 0x56, 0x0, 0x0c, 0x57, 0x0, 0x6d, 0x47, 0xe4, 0x32, 0xd7, 0x22, + 0x64, 0xa5, 0x33, 0x65, 0x33, 0x3e, 0x7c, 0x4e, 0x9d, 0xa6, 0xb7, 0x8b, 0xd7, 0xaa, 0x72, 0xe5, + 0x9d, 0xd5, 0xb4, 0x25, 0xcb, 0x30, 0x2, 0xfc, 0xb5, 0xae, 0xb3, 0x88, 0x67, 0x55, 0x0a, 0x7e, + 0x9d, 0xe8, 0x32, 0xfb, 0x50, 0x79, 0x4e, 0x9b, 0x21, 0x92, 0x25, 0x3, 0xa0, 0x15, 0x52, 0x3d, + 0x5e, 0x21, 0x0a, 0x9e, 0x3, 0xdd, 0x3f, 0xcc, 0x38, 0xf6, 0xa9, 0xa6, 0xf8, 0xfd, 0x15, 0x7d, + 0x67, 0x4e, 0x14, 0xae, 0x4d, 0xe2, 0x1f, 0x78, 0x77, 0xfb, 0x83, 0x5f, 0x48, 0xa8, 0xc8, 0x21, + 0x8b, 0xd9, 0xf8, 0x14, 0xe6, 0x42, 0x95, 0xbd, 0x9a, 0x96, 0xbe, 0xf4, 0x7d, 0x26, 0x5d, 0xa1, + 0x81, 0x9b, 0x1c, 0xec, 0xfe, 0xce, 0x9, 0x1d, 0xb7, 0x7a, 0xba, 0xca, 0x7f, 0x54, 0xee, 0x36, +}; + +char dh_except_a_pubkey_1536[] = { + 0x97,0x1e,0x6d,0xf7,0xb1,0x2f,0xa7,0x82,0x9e,0x99,0x22,0xfb,0xf3,0x4e,0x2a,0x73, + 0xcc,0xd9,0x2b,0x10,0x1,0xfb,0xac,0xf1,0x81,0xfe,0x78,0x3d,0x23,0xb0,0xcf,0x5c, + 0x95,0x69,0x36,0xc0,0x99,0x6a,0xd2,0x9c,0xf0,0x85,0x8d,0xda,0x5d,0xba,0x8e,0x0f, + 0xa3,0xce,0xbe,0x9b,0xe8,0x3b,0xad,0x71,0xfd,0xfd,0x53,0x25,0xee,0x61,0x26,0x15, + 0x0a,0x46,0x9e,0xce,0x85,0xb1,0x5c,0xf1,0xa0,0x8f,0xe7,0x89,0xe3,0x4f,0x7c,0xea, + 0x18,0xd3,0xa9,0x44,0xce,0x35,0x9,0x86,0x80,0x8c,0x30,0x1,0xbc,0x6d,0xf6,0x6a, + 0x3a,0xa6,0xad,0xbe,0xfa,0x73,0x6b,0xb0,0x35,0x8c,0x63,0x80,0xb6,0x58,0x51,0x6e, + 0x4c,0x5d,0x4a,0xe9,0xa9,0x72,0x6,0x9f,0xa2,0x3e,0x64,0xaf,0x70,0x63,0xee,0x2a, + 0x5d,0x73,0xf3,0xdc,0xa3,0x32,0x0f,0x8,0x48,0xcf,0x13,0x80,0x0d,0xdb,0x91,0xdf, + 0x87,0x99,0xa4,0x8a,0x50,0xe9,0x75,0x43,0xfb,0x56,0xd7,0x89,0xc3,0x10,0x7e,0xd0, + 0xb7,0x46,0xd8,0x41,0x91,0xdf,0xb1,0x91,0x8e,0xc1,0x58,0xd7,0x7c,0x33,0x1e,0xb3, + 0xa3,0xda,0xcb,0xf5,0x0,0x76,0xe4,0xee,0x20,0xd6,0x9d,0x8a,0x28,0xa4,0xdb,0xf9, +}; + +char dh_except_b_pubkey_1536[] = { + 0x44, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x9, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x4, 0xe8, 0x9a, 0xd2, 0x0, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x0, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x5, + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x7, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x3, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, +}; + +char dh_share_key_1536[] = { + 0xaf, 0xd4, 0xf6, 0x45, 0x63, 0x21, 0x8d, 0x98, 0xc4, 0xab, 0x18, 0xd7, 0x2b, 0x3c, 0x1d, 0xde, + 0xe7, 0x1f, 0xe1, 0xc5, 0x79, 0x57, 0x60, 0x20, 0xfa, 0x99, 0xbd, 0x7b, 0xa2, 0x94, 0x0b, 0xa3, + 0xb4, 0xb3, 0x33, 0x4a, 0x2f, 0xd0, 0x17, 0x7, 0x2e, 0x70, 0x19, 0x84, 0x1f, 0x8e, 0xe9, 0x61, + 0xe5, 0x52, 0x3, 0x96, 0xea, 0xd8, 0xb6, 0x3, 0x9f, 0xc4, 0x3e, 0x23, 0x77, 0x17, 0x54, 0xfb, + 0x13, 0xf0, 0x3e, 0x9a, 0x27, 0x5d, 0x12, 0x99, 0x58, 0x8d, 0x41, 0x46, 0xd9, 0xc9, 0x29, 0xbd, + 0x40, 0xd1, 0x4f, 0xef, 0x63, 0x7b, 0x54, 0xe6, 0x59, 0x6d, 0xe2, 0x30, 0xe8, 0x2c, 0x2f, 0xf9, + 0x66, 0xa2, 0x12, 0xf5, 0x58, 0x61, 0xac, 0x43, 0xec, 0x7e, 0xf9, 0x2e, 0x27, 0x70, 0x35, 0x75, + 0xb4, 0x10, 0x29, 0xac, 0x0a, 0xab, 0x59, 0xb6, 0x68, 0x4c, 0x16, 0xaf, 0xf0, 0x4f, 0x21, 0xcd, + 0xcc, 0x48, 0x97, 0xe4, 0x21, 0x65, 0xa6, 0x55, 0xb8, 0xf3, 0xb2, 0x7b, 0x91, 0xd7, 0xca, 0xb9, + 0x17, 0x58, 0x31, 0x71, 0xc0, 0xc9, 0x69, 0x1e, 0xf0, 0x9e, 0x3f, 0xe2, 0x37, 0x4, 0x2d, 0xa8, + 0x55, 0x9, 0x6b, 0x9c, 0xc6, 0x37, 0xa9, 0x9b, 0xdf, 0x67, 0x73, 0x7b, 0x46, 0xf9, 0x63, 0x47, + 0xcb, 0xa0, 0x57, 0x2a, 0xed, 0x97, 0x2f, 0xfe, 0x92, 0xf2, 0x20, 0x2c, 0x7e, 0xee, 0x7d, 0x11, +}; + +char dh_p_2048[] = { + 0xce, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x09, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x04, 0xe8, 0x9a, 0xd2, 0x00, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x00, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x05, + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x07, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x03, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x01, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7 +}; + +char dh_xa_2048[] = { + 0x6b, 0x1f, 0xc4, 0x85, 0x98, 0xc3, 0x01, 0xda, 0x39, 0xf0, 0x1b, 0x76, 0x5d, 0x81, 0x1d, 0x1f, + 0xc9, 0x93, 0x95, 0xc1, 0xf8, 0xd1, 0x67, 0x2c, 0xd4, 0x0a, 0x67, 0xf0, 0x40, 0x86, 0x82, 0x7f, + 0x8f, 0x9d, 0x79, 0x04, 0xee, 0x4a, 0x54, 0xc9, 0x9c, 0x7f, 0xda, 0x15, 0x13, 0xc6, 0x95, 0xfb, + 0xfc, 0x7b, 0xe7, 0xd8, 0xde, 0x2a, 0xd8, 0xfd, 0xff, 0xdb, 0xa4, 0x7f, 0x4b, 0x37, 0x5d, 0x42, + 0xb6, 0x46, 0x4c, 0xbc, 0x34, 0x23, 0x99, 0x74, 0xf8, 0x80, 0x1b, 0xc1, 0x97, 0x34, 0xdf, 0x23, + 0x15, 0xa2, 0x8b, 0xec, 0xf3, 0x3e, 0x20, 0x93, 0x63, 0x88, 0x17, 0x70, 0x75, 0xbb, 0x9d, 0xb8, + 0x32, 0xb0, 0xae, 0xb5, 0x24, 0x6a, 0x86, 0xf6, 0xc1, 0x60, 0x41, 0xc4, 0xf4, 0x95, 0x6e, 0x10, + 0x2f, 0xd8, 0x58, 0x56, 0x42, 0x82, 0x71, 0x85, 0x19, 0xde, 0x91, 0xf0, 0x2f, 0x30, 0x0c, 0x63, + 0x0f, 0x2a, 0x77, 0x25, 0x4b, 0xb3, 0xd3, 0x2d, 0xfd, 0x94, 0x8b, 0x53, 0x02, 0x21, 0x40, 0xd7, + 0x36, 0x76, 0xf3, 0xc8, 0xc0, 0x36, 0x3d, 0x23, 0xc9, 0xbd, 0x92, 0x51, 0xf2, 0x4b, 0x83, 0x15, + 0xe0, 0x80, 0x86, 0x24, 0xe2, 0x20, 0x35, 0x97, 0xda, 0x0e, 0x68, 0x39, 0x01, 0xdd, 0x01, 0x87, + 0xa2, 0x47, 0xd2, 0x0d, 0xee, 0xfe, 0xdc, 0x5a, 0x37, 0x23, 0xeb, 0x3d, 0xe8, 0x1e, 0x39, 0x2d, + 0xbf, 0xa6, 0xe9, 0x17, 0x48, 0xe2, 0xea, 0xef, 0x1d, 0x2f, 0xe2, 0xaf, 0x3c, 0xbc, 0xae, 0xa7, + 0x42, 0x9b, 0xa5, 0x7d, 0x47, 0x8a, 0x20, 0xc5, 0xae, 0xa1, 0xe4, 0xe8, 0x1c, 0x05, 0xc0, 0x0a, + 0x05, 0xdc, 0x01, 0x74, 0xde, 0xad, 0xad, 0x07, 0xec, 0x6e, 0x6a, 0xc7, 0xee, 0x0f, 0xb8, 0xbe, + 0xaa, 0x46, 0x61, 0x8c, 0x12, 0x5a, 0xaf, 0x05, 0xff, 0x1b, 0x35, 0x6b, 0xe2, 0x3d, 0x48, 0x4f +}; + +char dh_xb_2048[] = { + 0x5c, 0xdf, 0x3, 0x2f, 0x18, 0xac, 0xbc, 0xeb, 0x95, 0xa2, 0x33, 0x70, 0x39, 0x13, 0x92, 0x7e, + 0x91, 0x19, 0x89, 0xd4, 0x0, 0xd1, 0xc5, 0x7e, 0x32, 0xb7, 0x4a, 0xd2, 0xff, 0x11, 0x7a, 0x9b, + 0x2, 0x84, 0xd0, 0x8e, 0x19, 0x91, 0x34, 0xc2, 0x5, 0xff, 0xe4, 0xf4, 0xd8, 0xcf, 0xc8, 0xa0, + 0xeb, 0x19, 0xb9, 0x69, 0x60, 0xcd, 0xa8, 0xda, 0x33, 0xbc, 0xa7, 0x80, 0x0, 0x92, 0x27, 0xe0, + 0xe7, 0x34, 0x77, 0x1f, 0xfd, 0x56, 0x0, 0x0c, 0x57, 0x0, 0x6d, 0x47, 0xe4, 0x32, 0xd7, 0x22, + 0x64, 0xa5, 0x33, 0x65, 0x33, 0x3e, 0x7c, 0x4e, 0x9d, 0xa6, 0xb7, 0x8b, 0xd7, 0xaa, 0x72, 0xe5, + 0x9d, 0xd5, 0xb4, 0x25, 0xcb, 0x30, 0x2, 0xfc, 0xb5, 0xae, 0xb3, 0x88, 0x67, 0x55, 0x0a, 0x7e, + 0x9d, 0xe8, 0x32, 0xfb, 0x50, 0x79, 0x4e, 0x9b, 0x21, 0x92, 0x25, 0x3, 0xa0, 0x15, 0x52, 0x3d, + 0x5e, 0x21, 0x0a, 0x9e, 0x3, 0xdd, 0x3f, 0xcc, 0x38, 0xf6, 0xa9, 0xa6, 0xf8, 0xfd, 0x15, 0x7d, + 0x67, 0x4e, 0x14, 0xae, 0x4d, 0xe2, 0x1f, 0x78, 0x77, 0xfb, 0x83, 0x5f, 0x48, 0xa8, 0xc8, 0x21, + 0x8b, 0xd9, 0xf8, 0x14, 0xe6, 0x42, 0x95, 0xbd, 0x9a, 0x96, 0xbe, 0xf4, 0x7d, 0x26, 0x5d, 0xa1, + 0x81, 0x9b, 0x1c, 0xec, 0xfe, 0xce, 0x9, 0x1d, 0xb7, 0x7a, 0xba, 0xca, 0x7f, 0x54, 0xee, 0x36, + 0x54, 0x65, 0x4a, 0xd0, 0x5c, 0x84, 0x8c, 0x3e, 0x1b, 0xfe, 0x91, 0x6f, 0x95, 0xb5, 0x76, 0xbf, + 0x61, 0x2a, 0x7, 0x23, 0x86, 0xb9, 0xe0, 0x19, 0x29, 0xcf, 0xea, 0x3a, 0x1, 0xbf, 0xee, 0x1b, + 0x5e, 0x3c, 0x4, 0xff, 0x1d, 0xcf, 0xa6, 0x56, 0xb3, 0x22, 0xbb, 0x45, 0x4b, 0x7f, 0x83, 0x87, + 0xef, 0x21, 0x5, 0xf7, 0x38, 0x1f, 0x6, 0x4d, 0x71, 0x0b, 0xe3, 0xe1, 0xb7, 0x7e, 0xae, 0x18 +}; + +char dh_except_a_pubkey_2048[] = { + 0xa5, 0x24, 0x63, 0x20, 0xb2, 0x56, 0x9a, 0x94, 0x97, 0xf7, 0x88, 0x41, 0x35, 0xeb, 0x52, 0x37, + 0xa4, 0xf2, 0x74, 0x1b, 0x38, 0xe4, 0x4c, 0x8b, 0x4b, 0xd2, 0xa5, 0xad, 0xb8, 0x2f, 0x7b, 0x5a, + 0xfd, 0xbc, 0x9c, 0xe0, 0xea, 0x9e, 0x82, 0x3, 0x62, 0xe2, 0xdc, 0x6c, 0x56, 0x9, 0x2, 0x28, + 0xb8, 0x2d, 0xb8, 0x46, 0xaf, 0x3a, 0xf4, 0x51, 0xf7, 0x4d, 0xc4, 0xd9, 0xa9, 0x1d, 0x67, 0x9d, + 0x2b, 0x18, 0x56, 0x86, 0x2a, 0x3, 0x19, 0xe9, 0x6, 0xeb, 0x4a, 0x6f, 0x2a, 0x40, 0x28, 0xbb, + 0x3e, 0x87, 0xc1, 0xce, 0x39, 0x6e, 0x3b, 0x1f, 0xb0, 0x9, 0x33, 0x67, 0x19, 0x0e, 0x1a, 0xb2, + 0xb3, 0x7d, 0xd3, 0xe6, 0x33, 0xf4, 0x7c, 0x82, 0x73, 0x7b, 0xb6, 0x16, 0x55, 0xff, 0x76, 0xaf, + 0x7f, 0xc2, 0x42, 0x51, 0xa9, 0xad, 0x1e, 0x72, 0xc9, 0x63, 0xab, 0x41, 0x5a, 0x26, 0x32, 0x39, + 0x5d, 0xa6, 0x7, 0x56, 0x93, 0x89, 0xe5, 0x0f, 0x2a, 0xb5, 0x67, 0x3a, 0xcf, 0xc3, 0x82, 0x83, + 0xf6, 0x88, 0x52, 0x0b, 0xfc, 0x6a, 0x5b, 0x1a, 0x57, 0x87, 0x86, 0xef, 0xda, 0x47, 0xdb, 0x4d, + 0xba, 0xe7, 0x3, 0x5b, 0xe4, 0x70, 0x8b, 0xe0, 0xe1, 0x92, 0x13, 0x86, 0x74, 0x4, 0xdc, 0x6a, + 0x0a, 0x2a, 0x20, 0xec, 0x6d, 0xbf, 0xf0, 0x46, 0xf7, 0x9, 0x2, 0xdb, 0x2f, 0x70, 0x11, 0xdd, + 0xb0, 0x13, 0xa2, 0xc1, 0x58, 0x74, 0x29, 0x19, 0x8d, 0x4a, 0x94, 0x80, 0x0b, 0xd7, 0x25, 0x85, + 0x10, 0x35, 0x97, 0x48, 0x6e, 0x70, 0x28, 0xae, 0x58, 0x97, 0x7d, 0xf2, 0x19, 0x27, 0x13, 0xab, + 0x47, 0x9b, 0x54, 0xdf, 0xc3, 0x5b, 0x5f, 0x5e, 0xb4, 0x64, 0x47, 0xce, 0x40, 0x3b, 0x0c, 0x4a, + 0x62, 0x52, 0xba, 0xc7, 0xf0, 0x36, 0x87, 0x9c, 0x79, 0x9a, 0x83, 0x11, 0x61, 0x0c, 0x1b, 0x6b +}; + +char dh_except_b_pubkey_2048[] = { + 0x44, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x9, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x4, 0xe8, 0x9a, 0xd2, 0x0, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x0, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x5, + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x7, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x3, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x1, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7 +}; + +char dh_share_key_2048[] = { + 0xaf, 0xd4, 0xf6, 0x45, 0x63, 0x21, 0x8d, 0x98, 0xc4, 0xab, 0x18, 0xd7, 0x2b, 0x3c, 0x1d, 0xde, + 0xe7, 0x1f, 0xe1, 0xc5, 0x79, 0x57, 0x60, 0x20, 0xfa, 0x99, 0xbd, 0x7b, 0xa2, 0x94, 0x0b, 0xa3, + 0xb4, 0xb3, 0x33, 0x4a, 0x2f, 0xd0, 0x17, 0x7, 0x2e, 0x70, 0x19, 0x84, 0x1f, 0x8e, 0xe9, 0x61, + 0xe5, 0x52, 0x3, 0x96, 0xea, 0xd8, 0xb6, 0x3, 0x9f, 0xc4, 0x3e, 0x23, 0x77, 0x17, 0x54, 0xfb, + 0x13, 0xf0, 0x3e, 0x9a, 0x27, 0x5d, 0x12, 0x99, 0x58, 0x8d, 0x41, 0x46, 0xd9, 0xc9, 0x29, 0xbd, + 0x40, 0xd1, 0x4f, 0xef, 0x63, 0x7b, 0x54, 0xe6, 0x59, 0x6d, 0xe2, 0x30, 0xe8, 0x2c, 0x2f, 0xf9, + 0x66, 0xa2, 0x12, 0xf5, 0x58, 0x61, 0xac, 0x43, 0xec, 0x7e, 0xf9, 0x2e, 0x27, 0x70, 0x35, 0x75, + 0xb4, 0x10, 0x29, 0xac, 0x0a, 0xab, 0x59, 0xb6, 0x68, 0x4c, 0x16, 0xaf, 0xf0, 0x4f, 0x21, 0xcd, + 0xcc, 0x48, 0x97, 0xe4, 0x21, 0x65, 0xa6, 0x55, 0xb8, 0xf3, 0xb2, 0x7b, 0x91, 0xd7, 0xca, 0xb9, + 0x17, 0x58, 0x31, 0x71, 0xc0, 0xc9, 0x69, 0x1e, 0xf0, 0x9e, 0x3f, 0xe2, 0x37, 0x4, 0x2d, 0xa8, + 0x55, 0x9, 0x6b, 0x9c, 0xc6, 0x37, 0xa9, 0x9b, 0xdf, 0x67, 0x73, 0x7b, 0x46, 0xf9, 0x63, 0x47, + 0xcb, 0xa0, 0x57, 0x2a, 0xed, 0x97, 0x2f, 0xfe, 0x92, 0xf2, 0x20, 0x2c, 0x7e, 0xee, 0x7d, 0x11, + 0x78, 0xe6, 0xb9, 0x9, 0xd1, 0x94, 0xce, 0xd1, 0x5b, 0xf4, 0x44, 0xa9, 0xcb, 0x26, 0x2, 0x36, + 0x57, 0x2c, 0xa2, 0xbe, 0x37, 0xde, 0x86, 0x46, 0x20, 0x27, 0x9d, 0xa0, 0x2f, 0x4, 0xc1, 0xcd, + 0xff, 0x81, 0xe5, 0xe6, 0x2c, 0x9e, 0x39, 0x82, 0x31, 0x54, 0x33, 0xf8, 0xe7, 0xa0, 0xe5, 0x96, + 0xa4, 0x40, 0xc4, 0x44, 0xfe, 0x93, 0x66, 0xe2, 0xda, 0xaa, 0xb8, 0xfb, 0x2f, 0x3b, 0x8c, 0xce, +}; + +char dh_p_3072[] = { + 0xce, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x09, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x04, 0xe8, 0x9a, 0xd2, 0x00, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x00, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x05, + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x07, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x03, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x01, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7, + 0xce, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x09, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x04, 0xe8, 0x9a, 0xd2, 0x00, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x00, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x05, +}; + +char dh_xa_3072[] = { + 0x6b, 0x1f, 0xc4, 0x85, 0x98, 0xc3, 0x01, 0xda, 0x39, 0xf0, 0x1b, 0x76, 0x5d, 0x81, 0x1d, 0x1f, + 0xc9, 0x93, 0x95, 0xc1, 0xf8, 0xd1, 0x67, 0x2c, 0xd4, 0x0a, 0x67, 0xf0, 0x40, 0x86, 0x82, 0x7f, + 0x8f, 0x9d, 0x79, 0x04, 0xee, 0x4a, 0x54, 0xc9, 0x9c, 0x7f, 0xda, 0x15, 0x13, 0xc6, 0x95, 0xfb, + 0xfc, 0x7b, 0xe7, 0xd8, 0xde, 0x2a, 0xd8, 0xfd, 0xff, 0xdb, 0xa4, 0x7f, 0x4b, 0x37, 0x5d, 0x42, + 0xb6, 0x46, 0x4c, 0xbc, 0x34, 0x23, 0x99, 0x74, 0xf8, 0x80, 0x1b, 0xc1, 0x97, 0x34, 0xdf, 0x23, + 0x15, 0xa2, 0x8b, 0xec, 0xf3, 0x3e, 0x20, 0x93, 0x63, 0x88, 0x17, 0x70, 0x75, 0xbb, 0x9d, 0xb8, + 0x32, 0xb0, 0xae, 0xb5, 0x24, 0x6a, 0x86, 0xf6, 0xc1, 0x60, 0x41, 0xc4, 0xf4, 0x95, 0x6e, 0x10, + 0x2f, 0xd8, 0x58, 0x56, 0x42, 0x82, 0x71, 0x85, 0x19, 0xde, 0x91, 0xf0, 0x2f, 0x30, 0x0c, 0x63, + 0x0f, 0x2a, 0x77, 0x25, 0x4b, 0xb3, 0xd3, 0x2d, 0xfd, 0x94, 0x8b, 0x53, 0x02, 0x21, 0x40, 0xd7, + 0x36, 0x76, 0xf3, 0xc8, 0xc0, 0x36, 0x3d, 0x23, 0xc9, 0xbd, 0x92, 0x51, 0xf2, 0x4b, 0x83, 0x15, + 0xe0, 0x80, 0x86, 0x24, 0xe2, 0x20, 0x35, 0x97, 0xda, 0x0e, 0x68, 0x39, 0x01, 0xdd, 0x01, 0x87, + 0xa2, 0x47, 0xd2, 0x0d, 0xee, 0xfe, 0xdc, 0x5a, 0x37, 0x23, 0xeb, 0x3d, 0xe8, 0x1e, 0x39, 0x2d, + 0xbf, 0xa6, 0xe9, 0x17, 0x48, 0xe2, 0xea, 0xef, 0x1d, 0x2f, 0xe2, 0xaf, 0x3c, 0xbc, 0xae, 0xa7, + 0x42, 0x9b, 0xa5, 0x7d, 0x47, 0x8a, 0x20, 0xc5, 0xae, 0xa1, 0xe4, 0xe8, 0x1c, 0x05, 0xc0, 0x0a, + 0x05, 0xdc, 0x01, 0x74, 0xde, 0xad, 0xad, 0x07, 0xec, 0x6e, 0x6a, 0xc7, 0xee, 0x0f, 0xb8, 0xbe, + 0xaa, 0x46, 0x61, 0x8c, 0x12, 0x5a, 0xaf, 0x05, 0xff, 0x1b, 0x35, 0x6b, 0xe2, 0x3d, 0x48, 0x4f, + 0x6b, 0x1f, 0xc4, 0x85, 0x98, 0xc3, 0x01, 0xda, 0x39, 0xf0, 0x1b, 0x76, 0x5d, 0x81, 0x1d, 0x1f, + 0xc9, 0x93, 0x95, 0xc1, 0xf8, 0xd1, 0x67, 0x2c, 0xd4, 0x0a, 0x67, 0xf0, 0x40, 0x86, 0x82, 0x7f, + 0x8f, 0x9d, 0x79, 0x04, 0xee, 0x4a, 0x54, 0xc9, 0x9c, 0x7f, 0xda, 0x15, 0x13, 0xc6, 0x95, 0xfb, + 0xfc, 0x7b, 0xe7, 0xd8, 0xde, 0x2a, 0xd8, 0xfd, 0xff, 0xdb, 0xa4, 0x7f, 0x4b, 0x37, 0x5d, 0x42, + 0xb6, 0x46, 0x4c, 0xbc, 0x34, 0x23, 0x99, 0x74, 0xf8, 0x80, 0x1b, 0xc1, 0x97, 0x34, 0xdf, 0x23, + 0x15, 0xa2, 0x8b, 0xec, 0xf3, 0x3e, 0x20, 0x93, 0x63, 0x88, 0x17, 0x70, 0x75, 0xbb, 0x9d, 0xb8, + 0x32, 0xb0, 0xae, 0xb5, 0x24, 0x6a, 0x86, 0xf6, 0xc1, 0x60, 0x41, 0xc4, 0xf4, 0x95, 0x6e, 0x10, + 0x2f, 0xd8, 0x58, 0x56, 0x42, 0x82, 0x71, 0x85, 0x19, 0xde, 0x91, 0xf0, 0x2f, 0x30, 0x0c, 0x63, +}; + +char dh_xb_3072[] = { + 0x5c, 0xdf, 0x3, 0x2f, 0x18, 0xac, 0xbc, 0xeb, 0x95, 0xa2, 0x33, 0x70, 0x39, 0x13, 0x92, 0x7e, + 0x91, 0x19, 0x89, 0xd4, 0x0, 0xd1, 0xc5, 0x7e, 0x32, 0xb7, 0x4a, 0xd2, 0xff, 0x11, 0x7a, 0x9b, + 0x2, 0x84, 0xd0, 0x8e, 0x19, 0x91, 0x34, 0xc2, 0x5, 0xff, 0xe4, 0xf4, 0xd8, 0xcf, 0xc8, 0xa0, + 0xeb, 0x19, 0xb9, 0x69, 0x60, 0xcd, 0xa8, 0xda, 0x33, 0xbc, 0xa7, 0x80, 0x0, 0x92, 0x27, 0xe0, + 0xe7, 0x34, 0x77, 0x1f, 0xfd, 0x56, 0x0, 0x0c, 0x57, 0x0, 0x6d, 0x47, 0xe4, 0x32, 0xd7, 0x22, + 0x64, 0xa5, 0x33, 0x65, 0x33, 0x3e, 0x7c, 0x4e, 0x9d, 0xa6, 0xb7, 0x8b, 0xd7, 0xaa, 0x72, 0xe5, + 0x9d, 0xd5, 0xb4, 0x25, 0xcb, 0x30, 0x2, 0xfc, 0xb5, 0xae, 0xb3, 0x88, 0x67, 0x55, 0x0a, 0x7e, + 0x9d, 0xe8, 0x32, 0xfb, 0x50, 0x79, 0x4e, 0x9b, 0x21, 0x92, 0x25, 0x3, 0xa0, 0x15, 0x52, 0x3d, + 0x5e, 0x21, 0x0a, 0x9e, 0x3, 0xdd, 0x3f, 0xcc, 0x38, 0xf6, 0xa9, 0xa6, 0xf8, 0xfd, 0x15, 0x7d, + 0x67, 0x4e, 0x14, 0xae, 0x4d, 0xe2, 0x1f, 0x78, 0x77, 0xfb, 0x83, 0x5f, 0x48, 0xa8, 0xc8, 0x21, + 0x8b, 0xd9, 0xf8, 0x14, 0xe6, 0x42, 0x95, 0xbd, 0x9a, 0x96, 0xbe, 0xf4, 0x7d, 0x26, 0x5d, 0xa1, + 0x81, 0x9b, 0x1c, 0xec, 0xfe, 0xce, 0x9, 0x1d, 0xb7, 0x7a, 0xba, 0xca, 0x7f, 0x54, 0xee, 0x36, + 0x54, 0x65, 0x4a, 0xd0, 0x5c, 0x84, 0x8c, 0x3e, 0x1b, 0xfe, 0x91, 0x6f, 0x95, 0xb5, 0x76, 0xbf, + 0x61, 0x2a, 0x7, 0x23, 0x86, 0xb9, 0xe0, 0x19, 0x29, 0xcf, 0xea, 0x3a, 0x1, 0xbf, 0xee, 0x1b, + 0x5e, 0x3c, 0x4, 0xff, 0x1d, 0xcf, 0xa6, 0x56, 0xb3, 0x22, 0xbb, 0x45, 0x4b, 0x7f, 0x83, 0x87, + 0xef, 0x21, 0x5, 0xf7, 0x38, 0x1f, 0x6, 0x4d, 0x71, 0x0b, 0xe3, 0xe1, 0xb7, 0x7e, 0xae, 0x18, + 0x5c, 0xdf, 0x3, 0x2f, 0x18, 0xac, 0xbc, 0xeb, 0x95, 0xa2, 0x33, 0x70, 0x39, 0x13, 0x92, 0x7e, + 0x91, 0x19, 0x89, 0xd4, 0x0, 0xd1, 0xc5, 0x7e, 0x32, 0xb7, 0x4a, 0xd2, 0xff, 0x11, 0x7a, 0x9b, + 0x2, 0x84, 0xd0, 0x8e, 0x19, 0x91, 0x34, 0xc2, 0x5, 0xff, 0xe4, 0xf4, 0xd8, 0xcf, 0xc8, 0xa0, + 0xeb, 0x19, 0xb9, 0x69, 0x60, 0xcd, 0xa8, 0xda, 0x33, 0xbc, 0xa7, 0x80, 0x0, 0x92, 0x27, 0xe0, + 0xe7, 0x34, 0x77, 0x1f, 0xfd, 0x56, 0x0, 0x0c, 0x57, 0x0, 0x6d, 0x47, 0xe4, 0x32, 0xd7, 0x22, + 0x64, 0xa5, 0x33, 0x65, 0x33, 0x3e, 0x7c, 0x4e, 0x9d, 0xa6, 0xb7, 0x8b, 0xd7, 0xaa, 0x72, 0xe5, + 0x9d, 0xd5, 0xb4, 0x25, 0xcb, 0x30, 0x2, 0xfc, 0xb5, 0xae, 0xb3, 0x88, 0x67, 0x55, 0x0a, 0x7e, + 0x9d, 0xe8, 0x32, 0xfb, 0x50, 0x79, 0x4e, 0x9b, 0x21, 0x92, 0x25, 0x3, 0xa0, 0x15, 0x52, 0x3d, +}; + +char dh_except_a_pubkey_3072[] = { + 0xa5, 0x24, 0x63, 0x20, 0xb2, 0x56, 0x9a, 0x94, 0x97, 0xf7, 0x88, 0x41, 0x35, 0xeb, 0x52, 0x37, + 0xa4, 0xf2, 0x74, 0x1b, 0x38, 0xe4, 0x4c, 0x8b, 0x4b, 0xd2, 0xa5, 0xad, 0xb8, 0x2f, 0x7b, 0x5a, + 0xfd, 0xbc, 0x9c, 0xe0, 0xea, 0x9e, 0x82, 0x3, 0x62, 0xe2, 0xdc, 0x6c, 0x56, 0x9, 0x2, 0x28, + 0xb8, 0x2d, 0xb8, 0x46, 0xaf, 0x3a, 0xf4, 0x51, 0xf7, 0x4d, 0xc4, 0xd9, 0xa9, 0x1d, 0x67, 0x9d, + 0x2b, 0x18, 0x56, 0x86, 0x2a, 0x3, 0x19, 0xe9, 0x6, 0xeb, 0x4a, 0x6f, 0x2a, 0x40, 0x28, 0xbb, + 0x3e, 0x87, 0xc1, 0xce, 0x39, 0x6e, 0x3b, 0x1f, 0xb0, 0x9, 0x33, 0x67, 0x19, 0x0e, 0x1a, 0xb2, + 0xb3, 0x7d, 0xd3, 0xe6, 0x33, 0xf4, 0x7c, 0x82, 0x73, 0x7b, 0xb6, 0x16, 0x55, 0xff, 0x76, 0xaf, + 0x7f, 0xc2, 0x42, 0x51, 0xa9, 0xad, 0x1e, 0x72, 0xc9, 0x63, 0xab, 0x41, 0x5a, 0x26, 0x32, 0x39, + 0x5d, 0xa6, 0x7, 0x56, 0x93, 0x89, 0xe5, 0x0f, 0x2a, 0xb5, 0x67, 0x3a, 0xcf, 0xc3, 0x82, 0x83, + 0xf6, 0x88, 0x52, 0x0b, 0xfc, 0x6a, 0x5b, 0x1a, 0x57, 0x87, 0x86, 0xef, 0xda, 0x47, 0xdb, 0x4d, + 0xba, 0xe7, 0x3, 0x5b, 0xe4, 0x70, 0x8b, 0xe0, 0xe1, 0x92, 0x13, 0x86, 0x74, 0x4, 0xdc, 0x6a, + 0x0a, 0x2a, 0x20, 0xec, 0x6d, 0xbf, 0xf0, 0x46, 0xf7, 0x9, 0x2, 0xdb, 0x2f, 0x70, 0x11, 0xdd, + 0xb0, 0x13, 0xa2, 0xc1, 0x58, 0x74, 0x29, 0x19, 0x8d, 0x4a, 0x94, 0x80, 0x0b, 0xd7, 0x25, 0x85, + 0x10, 0x35, 0x97, 0x48, 0x6e, 0x70, 0x28, 0xae, 0x58, 0x97, 0x7d, 0xf2, 0x19, 0x27, 0x13, 0xab, + 0x47, 0x9b, 0x54, 0xdf, 0xc3, 0x5b, 0x5f, 0x5e, 0xb4, 0x64, 0x47, 0xce, 0x40, 0x3b, 0x0c, 0x4a, + 0x62, 0x52, 0xba, 0xc7, 0xf0, 0x36, 0x87, 0x9c, 0x79, 0x9a, 0x83, 0x11, 0x61, 0x0c, 0x1b, 0x6b, + 0xa5, 0x24, 0x63, 0x20, 0xb2, 0x56, 0x9a, 0x94, 0x97, 0xf7, 0x88, 0x41, 0x35, 0xeb, 0x52, 0x37, + 0xa4, 0xf2, 0x74, 0x1b, 0x38, 0xe4, 0x4c, 0x8b, 0x4b, 0xd2, 0xa5, 0xad, 0xb8, 0x2f, 0x7b, 0x5a, + 0xfd, 0xbc, 0x9c, 0xe0, 0xea, 0x9e, 0x82, 0x3, 0x62, 0xe2, 0xdc, 0x6c, 0x56, 0x9, 0x2, 0x28, + 0xb8, 0x2d, 0xb8, 0x46, 0xaf, 0x3a, 0xf4, 0x51, 0xf7, 0x4d, 0xc4, 0xd9, 0xa9, 0x1d, 0x67, 0x9d, + 0x2b, 0x18, 0x56, 0x86, 0x2a, 0x3, 0x19, 0xe9, 0x6, 0xeb, 0x4a, 0x6f, 0x2a, 0x40, 0x28, 0xbb, + 0x3e, 0x87, 0xc1, 0xce, 0x39, 0x6e, 0x3b, 0x1f, 0xb0, 0x9, 0x33, 0x67, 0x19, 0x0e, 0x1a, 0xb2, + 0xb3, 0x7d, 0xd3, 0xe6, 0x33, 0xf4, 0x7c, 0x82, 0x73, 0x7b, 0xb6, 0x16, 0x55, 0xff, 0x76, 0xaf, + 0x7f, 0xc2, 0x42, 0x51, 0xa9, 0xad, 0x1e, 0x72, 0xc9, 0x63, 0xab, 0x41, 0x5a, 0x26, 0x32, 0x39, +}; + +char dh_except_b_pubkey_3072[] = { + 0x44, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x9, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x4, 0xe8, 0x9a, 0xd2, 0x0, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x0, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x5, + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x7, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x3, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x1, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7, + 0x44, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x9, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x4, 0xe8, 0x9a, 0xd2, 0x0, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x0, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x5, +}; + +char dh_share_key_3072[] = { + 0xaf, 0xd4, 0xf6, 0x45, 0x63, 0x21, 0x8d, 0x98, 0xc4, 0xab, 0x18, 0xd7, 0x2b, 0x3c, 0x1d, 0xde, + 0xe7, 0x1f, 0xe1, 0xc5, 0x79, 0x57, 0x60, 0x20, 0xfa, 0x99, 0xbd, 0x7b, 0xa2, 0x94, 0x0b, 0xa3, + 0xb4, 0xb3, 0x33, 0x4a, 0x2f, 0xd0, 0x17, 0x7, 0x2e, 0x70, 0x19, 0x84, 0x1f, 0x8e, 0xe9, 0x61, + 0xe5, 0x52, 0x3, 0x96, 0xea, 0xd8, 0xb6, 0x3, 0x9f, 0xc4, 0x3e, 0x23, 0x77, 0x17, 0x54, 0xfb, + 0x13, 0xf0, 0x3e, 0x9a, 0x27, 0x5d, 0x12, 0x99, 0x58, 0x8d, 0x41, 0x46, 0xd9, 0xc9, 0x29, 0xbd, + 0x40, 0xd1, 0x4f, 0xef, 0x63, 0x7b, 0x54, 0xe6, 0x59, 0x6d, 0xe2, 0x30, 0xe8, 0x2c, 0x2f, 0xf9, + 0x66, 0xa2, 0x12, 0xf5, 0x58, 0x61, 0xac, 0x43, 0xec, 0x7e, 0xf9, 0x2e, 0x27, 0x70, 0x35, 0x75, + 0xb4, 0x10, 0x29, 0xac, 0x0a, 0xab, 0x59, 0xb6, 0x68, 0x4c, 0x16, 0xaf, 0xf0, 0x4f, 0x21, 0xcd, + 0xcc, 0x48, 0x97, 0xe4, 0x21, 0x65, 0xa6, 0x55, 0xb8, 0xf3, 0xb2, 0x7b, 0x91, 0xd7, 0xca, 0xb9, + 0x17, 0x58, 0x31, 0x71, 0xc0, 0xc9, 0x69, 0x1e, 0xf0, 0x9e, 0x3f, 0xe2, 0x37, 0x4, 0x2d, 0xa8, + 0x55, 0x9, 0x6b, 0x9c, 0xc6, 0x37, 0xa9, 0x9b, 0xdf, 0x67, 0x73, 0x7b, 0x46, 0xf9, 0x63, 0x47, + 0xcb, 0xa0, 0x57, 0x2a, 0xed, 0x97, 0x2f, 0xfe, 0x92, 0xf2, 0x20, 0x2c, 0x7e, 0xee, 0x7d, 0x11, + 0x78, 0xe6, 0xb9, 0x9, 0xd1, 0x94, 0xce, 0xd1, 0x5b, 0xf4, 0x44, 0xa9, 0xcb, 0x26, 0x2, 0x36, + 0x57, 0x2c, 0xa2, 0xbe, 0x37, 0xde, 0x86, 0x46, 0x20, 0x27, 0x9d, 0xa0, 0x2f, 0x4, 0xc1, 0xcd, + 0xff, 0x81, 0xe5, 0xe6, 0x2c, 0x9e, 0x39, 0x82, 0x31, 0x54, 0x33, 0xf8, 0xe7, 0xa0, 0xe5, 0x96, + 0xa4, 0x40, 0xc4, 0x44, 0xfe, 0x93, 0x66, 0xe2, 0xda, 0xaa, 0xb8, 0xfb, 0x2f, 0x3b, 0x8c, 0xce, + 0xaf, 0xd4, 0xf6, 0x45, 0x63, 0x21, 0x8d, 0x98, 0xc4, 0xab, 0x18, 0xd7, 0x2b, 0x3c, 0x1d, 0xde, + 0xe7, 0x1f, 0xe1, 0xc5, 0x79, 0x57, 0x60, 0x20, 0xfa, 0x99, 0xbd, 0x7b, 0xa2, 0x94, 0x0b, 0xa3, + 0xb4, 0xb3, 0x33, 0x4a, 0x2f, 0xd0, 0x17, 0x7, 0x2e, 0x70, 0x19, 0x84, 0x1f, 0x8e, 0xe9, 0x61, + 0xe5, 0x52, 0x3, 0x96, 0xea, 0xd8, 0xb6, 0x3, 0x9f, 0xc4, 0x3e, 0x23, 0x77, 0x17, 0x54, 0xfb, + 0x13, 0xf0, 0x3e, 0x9a, 0x27, 0x5d, 0x12, 0x99, 0x58, 0x8d, 0x41, 0x46, 0xd9, 0xc9, 0x29, 0xbd, + 0x40, 0xd1, 0x4f, 0xef, 0x63, 0x7b, 0x54, 0xe6, 0x59, 0x6d, 0xe2, 0x30, 0xe8, 0x2c, 0x2f, 0xf9, + 0x66, 0xa2, 0x12, 0xf5, 0x58, 0x61, 0xac, 0x43, 0xec, 0x7e, 0xf9, 0x2e, 0x27, 0x70, 0x35, 0x75, + 0xb4, 0x10, 0x29, 0xac, 0x0a, 0xab, 0x59, 0xb6, 0x68, 0x4c, 0x16, 0xaf, 0xf0, 0x4f, 0x21, 0xcd, +}; + +char dh_p_4096[] = { + 0xce, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x09, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x04, 0xe8, 0x9a, 0xd2, 0x00, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x00, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x05, + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x07, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x03, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x01, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7, + 0xce, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x09, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x04, 0xe8, 0x9a, 0xd2, 0x00, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x00, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x05, + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x07, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x03, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x01, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7 +}; + +char dh_xa_4096[] = { + 0x6b, 0x1f, 0xc4, 0x85, 0x98, 0xc3, 0x01, 0xda, 0x39, 0xf0, 0x1b, 0x76, 0x5d, 0x81, 0x1d, 0x1f, + 0xc9, 0x93, 0x95, 0xc1, 0xf8, 0xd1, 0x67, 0x2c, 0xd4, 0x0a, 0x67, 0xf0, 0x40, 0x86, 0x82, 0x7f, + 0x8f, 0x9d, 0x79, 0x04, 0xee, 0x4a, 0x54, 0xc9, 0x9c, 0x7f, 0xda, 0x15, 0x13, 0xc6, 0x95, 0xfb, + 0xfc, 0x7b, 0xe7, 0xd8, 0xde, 0x2a, 0xd8, 0xfd, 0xff, 0xdb, 0xa4, 0x7f, 0x4b, 0x37, 0x5d, 0x42, + 0xb6, 0x46, 0x4c, 0xbc, 0x34, 0x23, 0x99, 0x74, 0xf8, 0x80, 0x1b, 0xc1, 0x97, 0x34, 0xdf, 0x23, + 0x15, 0xa2, 0x8b, 0xec, 0xf3, 0x3e, 0x20, 0x93, 0x63, 0x88, 0x17, 0x70, 0x75, 0xbb, 0x9d, 0xb8, + 0x32, 0xb0, 0xae, 0xb5, 0x24, 0x6a, 0x86, 0xf6, 0xc1, 0x60, 0x41, 0xc4, 0xf4, 0x95, 0x6e, 0x10, + 0x2f, 0xd8, 0x58, 0x56, 0x42, 0x82, 0x71, 0x85, 0x19, 0xde, 0x91, 0xf0, 0x2f, 0x30, 0x0c, 0x63, + 0x0f, 0x2a, 0x77, 0x25, 0x4b, 0xb3, 0xd3, 0x2d, 0xfd, 0x94, 0x8b, 0x53, 0x02, 0x21, 0x40, 0xd7, + 0x36, 0x76, 0xf3, 0xc8, 0xc0, 0x36, 0x3d, 0x23, 0xc9, 0xbd, 0x92, 0x51, 0xf2, 0x4b, 0x83, 0x15, + 0xe0, 0x80, 0x86, 0x24, 0xe2, 0x20, 0x35, 0x97, 0xda, 0x0e, 0x68, 0x39, 0x01, 0xdd, 0x01, 0x87, + 0xa2, 0x47, 0xd2, 0x0d, 0xee, 0xfe, 0xdc, 0x5a, 0x37, 0x23, 0xeb, 0x3d, 0xe8, 0x1e, 0x39, 0x2d, + 0xbf, 0xa6, 0xe9, 0x17, 0x48, 0xe2, 0xea, 0xef, 0x1d, 0x2f, 0xe2, 0xaf, 0x3c, 0xbc, 0xae, 0xa7, + 0x42, 0x9b, 0xa5, 0x7d, 0x47, 0x8a, 0x20, 0xc5, 0xae, 0xa1, 0xe4, 0xe8, 0x1c, 0x05, 0xc0, 0x0a, + 0x05, 0xdc, 0x01, 0x74, 0xde, 0xad, 0xad, 0x07, 0xec, 0x6e, 0x6a, 0xc7, 0xee, 0x0f, 0xb8, 0xbe, + 0xaa, 0x46, 0x61, 0x8c, 0x12, 0x5a, 0xaf, 0x05, 0xff, 0x1b, 0x35, 0x6b, 0xe2, 0x3d, 0x48, 0x4f, + 0x6b, 0x1f, 0xc4, 0x85, 0x98, 0xc3, 0x01, 0xda, 0x39, 0xf0, 0x1b, 0x76, 0x5d, 0x81, 0x1d, 0x1f, + 0xc9, 0x93, 0x95, 0xc1, 0xf8, 0xd1, 0x67, 0x2c, 0xd4, 0x0a, 0x67, 0xf0, 0x40, 0x86, 0x82, 0x7f, + 0x8f, 0x9d, 0x79, 0x04, 0xee, 0x4a, 0x54, 0xc9, 0x9c, 0x7f, 0xda, 0x15, 0x13, 0xc6, 0x95, 0xfb, + 0xfc, 0x7b, 0xe7, 0xd8, 0xde, 0x2a, 0xd8, 0xfd, 0xff, 0xdb, 0xa4, 0x7f, 0x4b, 0x37, 0x5d, 0x42, + 0xb6, 0x46, 0x4c, 0xbc, 0x34, 0x23, 0x99, 0x74, 0xf8, 0x80, 0x1b, 0xc1, 0x97, 0x34, 0xdf, 0x23, + 0x15, 0xa2, 0x8b, 0xec, 0xf3, 0x3e, 0x20, 0x93, 0x63, 0x88, 0x17, 0x70, 0x75, 0xbb, 0x9d, 0xb8, + 0x32, 0xb0, 0xae, 0xb5, 0x24, 0x6a, 0x86, 0xf6, 0xc1, 0x60, 0x41, 0xc4, 0xf4, 0x95, 0x6e, 0x10, + 0x2f, 0xd8, 0x58, 0x56, 0x42, 0x82, 0x71, 0x85, 0x19, 0xde, 0x91, 0xf0, 0x2f, 0x30, 0x0c, 0x63, + 0x0f, 0x2a, 0x77, 0x25, 0x4b, 0xb3, 0xd3, 0x2d, 0xfd, 0x94, 0x8b, 0x53, 0x02, 0x21, 0x40, 0xd7, + 0x36, 0x76, 0xf3, 0xc8, 0xc0, 0x36, 0x3d, 0x23, 0xc9, 0xbd, 0x92, 0x51, 0xf2, 0x4b, 0x83, 0x15, + 0xe0, 0x80, 0x86, 0x24, 0xe2, 0x20, 0x35, 0x97, 0xda, 0x0e, 0x68, 0x39, 0x01, 0xdd, 0x01, 0x87, + 0xa2, 0x47, 0xd2, 0x0d, 0xee, 0xfe, 0xdc, 0x5a, 0x37, 0x23, 0xeb, 0x3d, 0xe8, 0x1e, 0x39, 0x2d, + 0xbf, 0xa6, 0xe9, 0x17, 0x48, 0xe2, 0xea, 0xef, 0x1d, 0x2f, 0xe2, 0xaf, 0x3c, 0xbc, 0xae, 0xa7, + 0x42, 0x9b, 0xa5, 0x7d, 0x47, 0x8a, 0x20, 0xc5, 0xae, 0xa1, 0xe4, 0xe8, 0x1c, 0x05, 0xc0, 0x0a, + 0x05, 0xdc, 0x01, 0x74, 0xde, 0xad, 0xad, 0x07, 0xec, 0x6e, 0x6a, 0xc7, 0xee, 0x0f, 0xb8, 0xbe, + 0xaa, 0x46, 0x61, 0x8c, 0x12, 0x5a, 0xaf, 0x05, 0xff, 0x1b, 0x35, 0x6b, 0xe2, 0x3d, 0x48, 0x4f +}; + +char dh_xb_4096[] = { + 0x5c, 0xdf, 0x3, 0x2f, 0x18, 0xac, 0xbc, 0xeb, 0x95, 0xa2, 0x33, 0x70, 0x39, 0x13, 0x92, 0x7e, + 0x91, 0x19, 0x89, 0xd4, 0x0, 0xd1, 0xc5, 0x7e, 0x32, 0xb7, 0x4a, 0xd2, 0xff, 0x11, 0x7a, 0x9b, + 0x2, 0x84, 0xd0, 0x8e, 0x19, 0x91, 0x34, 0xc2, 0x5, 0xff, 0xe4, 0xf4, 0xd8, 0xcf, 0xc8, 0xa0, + 0xeb, 0x19, 0xb9, 0x69, 0x60, 0xcd, 0xa8, 0xda, 0x33, 0xbc, 0xa7, 0x80, 0x0, 0x92, 0x27, 0xe0, + 0xe7, 0x34, 0x77, 0x1f, 0xfd, 0x56, 0x0, 0x0c, 0x57, 0x0, 0x6d, 0x47, 0xe4, 0x32, 0xd7, 0x22, + 0x64, 0xa5, 0x33, 0x65, 0x33, 0x3e, 0x7c, 0x4e, 0x9d, 0xa6, 0xb7, 0x8b, 0xd7, 0xaa, 0x72, 0xe5, + 0x9d, 0xd5, 0xb4, 0x25, 0xcb, 0x30, 0x2, 0xfc, 0xb5, 0xae, 0xb3, 0x88, 0x67, 0x55, 0x0a, 0x7e, + 0x9d, 0xe8, 0x32, 0xfb, 0x50, 0x79, 0x4e, 0x9b, 0x21, 0x92, 0x25, 0x3, 0xa0, 0x15, 0x52, 0x3d, + 0x5e, 0x21, 0x0a, 0x9e, 0x3, 0xdd, 0x3f, 0xcc, 0x38, 0xf6, 0xa9, 0xa6, 0xf8, 0xfd, 0x15, 0x7d, + 0x67, 0x4e, 0x14, 0xae, 0x4d, 0xe2, 0x1f, 0x78, 0x77, 0xfb, 0x83, 0x5f, 0x48, 0xa8, 0xc8, 0x21, + 0x8b, 0xd9, 0xf8, 0x14, 0xe6, 0x42, 0x95, 0xbd, 0x9a, 0x96, 0xbe, 0xf4, 0x7d, 0x26, 0x5d, 0xa1, + 0x81, 0x9b, 0x1c, 0xec, 0xfe, 0xce, 0x9, 0x1d, 0xb7, 0x7a, 0xba, 0xca, 0x7f, 0x54, 0xee, 0x36, + 0x54, 0x65, 0x4a, 0xd0, 0x5c, 0x84, 0x8c, 0x3e, 0x1b, 0xfe, 0x91, 0x6f, 0x95, 0xb5, 0x76, 0xbf, + 0x61, 0x2a, 0x7, 0x23, 0x86, 0xb9, 0xe0, 0x19, 0x29, 0xcf, 0xea, 0x3a, 0x1, 0xbf, 0xee, 0x1b, + 0x5e, 0x3c, 0x4, 0xff, 0x1d, 0xcf, 0xa6, 0x56, 0xb3, 0x22, 0xbb, 0x45, 0x4b, 0x7f, 0x83, 0x87, + 0xef, 0x21, 0x5, 0xf7, 0x38, 0x1f, 0x6, 0x4d, 0x71, 0x0b, 0xe3, 0xe1, 0xb7, 0x7e, 0xae, 0x18, + 0x5c, 0xdf, 0x3, 0x2f, 0x18, 0xac, 0xbc, 0xeb, 0x95, 0xa2, 0x33, 0x70, 0x39, 0x13, 0x92, 0x7e, + 0x91, 0x19, 0x89, 0xd4, 0x0, 0xd1, 0xc5, 0x7e, 0x32, 0xb7, 0x4a, 0xd2, 0xff, 0x11, 0x7a, 0x9b, + 0x2, 0x84, 0xd0, 0x8e, 0x19, 0x91, 0x34, 0xc2, 0x5, 0xff, 0xe4, 0xf4, 0xd8, 0xcf, 0xc8, 0xa0, + 0xeb, 0x19, 0xb9, 0x69, 0x60, 0xcd, 0xa8, 0xda, 0x33, 0xbc, 0xa7, 0x80, 0x0, 0x92, 0x27, 0xe0, + 0xe7, 0x34, 0x77, 0x1f, 0xfd, 0x56, 0x0, 0x0c, 0x57, 0x0, 0x6d, 0x47, 0xe4, 0x32, 0xd7, 0x22, + 0x64, 0xa5, 0x33, 0x65, 0x33, 0x3e, 0x7c, 0x4e, 0x9d, 0xa6, 0xb7, 0x8b, 0xd7, 0xaa, 0x72, 0xe5, + 0x9d, 0xd5, 0xb4, 0x25, 0xcb, 0x30, 0x2, 0xfc, 0xb5, 0xae, 0xb3, 0x88, 0x67, 0x55, 0x0a, 0x7e, + 0x9d, 0xe8, 0x32, 0xfb, 0x50, 0x79, 0x4e, 0x9b, 0x21, 0x92, 0x25, 0x3, 0xa0, 0x15, 0x52, 0x3d, + 0x5e, 0x21, 0x0a, 0x9e, 0x3, 0xdd, 0x3f, 0xcc, 0x38, 0xf6, 0xa9, 0xa6, 0xf8, 0xfd, 0x15, 0x7d, + 0x67, 0x4e, 0x14, 0xae, 0x4d, 0xe2, 0x1f, 0x78, 0x77, 0xfb, 0x83, 0x5f, 0x48, 0xa8, 0xc8, 0x21, + 0x8b, 0xd9, 0xf8, 0x14, 0xe6, 0x42, 0x95, 0xbd, 0x9a, 0x96, 0xbe, 0xf4, 0x7d, 0x26, 0x5d, 0xa1, + 0x81, 0x9b, 0x1c, 0xec, 0xfe, 0xce, 0x9, 0x1d, 0xb7, 0x7a, 0xba, 0xca, 0x7f, 0x54, 0xee, 0x36, + 0x54, 0x65, 0x4a, 0xd0, 0x5c, 0x84, 0x8c, 0x3e, 0x1b, 0xfe, 0x91, 0x6f, 0x95, 0xb5, 0x76, 0xbf, + 0x61, 0x2a, 0x7, 0x23, 0x86, 0xb9, 0xe0, 0x19, 0x29, 0xcf, 0xea, 0x3a, 0x1, 0xbf, 0xee, 0x1b, + 0x5e, 0x3c, 0x4, 0xff, 0x1d, 0xcf, 0xa6, 0x56, 0xb3, 0x22, 0xbb, 0x45, 0x4b, 0x7f, 0x83, 0x87, + 0xef, 0x21, 0x5, 0xf7, 0x38, 0x1f, 0x6, 0x4d, 0x71, 0x0b, 0xe3, 0xe1, 0xb7, 0x7e, 0xae, 0x18 +}; + +char dh_except_a_pubkey_4096[] = { + 0xa5, 0x24, 0x63, 0x20, 0xb2, 0x56, 0x9a, 0x94, 0x97, 0xf7, 0x88, 0x41, 0x35, 0xeb, 0x52, 0x37, + 0xa4, 0xf2, 0x74, 0x1b, 0x38, 0xe4, 0x4c, 0x8b, 0x4b, 0xd2, 0xa5, 0xad, 0xb8, 0x2f, 0x7b, 0x5a, + 0xfd, 0xbc, 0x9c, 0xe0, 0xea, 0x9e, 0x82, 0x3, 0x62, 0xe2, 0xdc, 0x6c, 0x56, 0x9, 0x2, 0x28, + 0xb8, 0x2d, 0xb8, 0x46, 0xaf, 0x3a, 0xf4, 0x51, 0xf7, 0x4d, 0xc4, 0xd9, 0xa9, 0x1d, 0x67, 0x9d, + 0x2b, 0x18, 0x56, 0x86, 0x2a, 0x3, 0x19, 0xe9, 0x6, 0xeb, 0x4a, 0x6f, 0x2a, 0x40, 0x28, 0xbb, + 0x3e, 0x87, 0xc1, 0xce, 0x39, 0x6e, 0x3b, 0x1f, 0xb0, 0x9, 0x33, 0x67, 0x19, 0x0e, 0x1a, 0xb2, + 0xb3, 0x7d, 0xd3, 0xe6, 0x33, 0xf4, 0x7c, 0x82, 0x73, 0x7b, 0xb6, 0x16, 0x55, 0xff, 0x76, 0xaf, + 0x7f, 0xc2, 0x42, 0x51, 0xa9, 0xad, 0x1e, 0x72, 0xc9, 0x63, 0xab, 0x41, 0x5a, 0x26, 0x32, 0x39, + 0x5d, 0xa6, 0x7, 0x56, 0x93, 0x89, 0xe5, 0x0f, 0x2a, 0xb5, 0x67, 0x3a, 0xcf, 0xc3, 0x82, 0x83, + 0xf6, 0x88, 0x52, 0x0b, 0xfc, 0x6a, 0x5b, 0x1a, 0x57, 0x87, 0x86, 0xef, 0xda, 0x47, 0xdb, 0x4d, + 0xba, 0xe7, 0x3, 0x5b, 0xe4, 0x70, 0x8b, 0xe0, 0xe1, 0x92, 0x13, 0x86, 0x74, 0x4, 0xdc, 0x6a, + 0x0a, 0x2a, 0x20, 0xec, 0x6d, 0xbf, 0xf0, 0x46, 0xf7, 0x9, 0x2, 0xdb, 0x2f, 0x70, 0x11, 0xdd, + 0xb0, 0x13, 0xa2, 0xc1, 0x58, 0x74, 0x29, 0x19, 0x8d, 0x4a, 0x94, 0x80, 0x0b, 0xd7, 0x25, 0x85, + 0x10, 0x35, 0x97, 0x48, 0x6e, 0x70, 0x28, 0xae, 0x58, 0x97, 0x7d, 0xf2, 0x19, 0x27, 0x13, 0xab, + 0x47, 0x9b, 0x54, 0xdf, 0xc3, 0x5b, 0x5f, 0x5e, 0xb4, 0x64, 0x47, 0xce, 0x40, 0x3b, 0x0c, 0x4a, + 0x62, 0x52, 0xba, 0xc7, 0xf0, 0x36, 0x87, 0x9c, 0x79, 0x9a, 0x83, 0x11, 0x61, 0x0c, 0x1b, 0x6b, + 0xa5, 0x24, 0x63, 0x20, 0xb2, 0x56, 0x9a, 0x94, 0x97, 0xf7, 0x88, 0x41, 0x35, 0xeb, 0x52, 0x37, + 0xa4, 0xf2, 0x74, 0x1b, 0x38, 0xe4, 0x4c, 0x8b, 0x4b, 0xd2, 0xa5, 0xad, 0xb8, 0x2f, 0x7b, 0x5a, + 0xfd, 0xbc, 0x9c, 0xe0, 0xea, 0x9e, 0x82, 0x3, 0x62, 0xe2, 0xdc, 0x6c, 0x56, 0x9, 0x2, 0x28, + 0xb8, 0x2d, 0xb8, 0x46, 0xaf, 0x3a, 0xf4, 0x51, 0xf7, 0x4d, 0xc4, 0xd9, 0xa9, 0x1d, 0x67, 0x9d, + 0x2b, 0x18, 0x56, 0x86, 0x2a, 0x3, 0x19, 0xe9, 0x6, 0xeb, 0x4a, 0x6f, 0x2a, 0x40, 0x28, 0xbb, + 0x3e, 0x87, 0xc1, 0xce, 0x39, 0x6e, 0x3b, 0x1f, 0xb0, 0x9, 0x33, 0x67, 0x19, 0x0e, 0x1a, 0xb2, + 0xb3, 0x7d, 0xd3, 0xe6, 0x33, 0xf4, 0x7c, 0x82, 0x73, 0x7b, 0xb6, 0x16, 0x55, 0xff, 0x76, 0xaf, + 0x7f, 0xc2, 0x42, 0x51, 0xa9, 0xad, 0x1e, 0x72, 0xc9, 0x63, 0xab, 0x41, 0x5a, 0x26, 0x32, 0x39, + 0x5d, 0xa6, 0x7, 0x56, 0x93, 0x89, 0xe5, 0x0f, 0x2a, 0xb5, 0x67, 0x3a, 0xcf, 0xc3, 0x82, 0x83, + 0xf6, 0x88, 0x52, 0x0b, 0xfc, 0x6a, 0x5b, 0x1a, 0x57, 0x87, 0x86, 0xef, 0xda, 0x47, 0xdb, 0x4d, + 0xba, 0xe7, 0x3, 0x5b, 0xe4, 0x70, 0x8b, 0xe0, 0xe1, 0x92, 0x13, 0x86, 0x74, 0x4, 0xdc, 0x6a, + 0x0a, 0x2a, 0x20, 0xec, 0x6d, 0xbf, 0xf0, 0x46, 0xf7, 0x9, 0x2, 0xdb, 0x2f, 0x70, 0x11, 0xdd, + 0xb0, 0x13, 0xa2, 0xc1, 0x58, 0x74, 0x29, 0x19, 0x8d, 0x4a, 0x94, 0x80, 0x0b, 0xd7, 0x25, 0x85, + 0x10, 0x35, 0x97, 0x48, 0x6e, 0x70, 0x28, 0xae, 0x58, 0x97, 0x7d, 0xf2, 0x19, 0x27, 0x13, 0xab, + 0x47, 0x9b, 0x54, 0xdf, 0xc3, 0x5b, 0x5f, 0x5e, 0xb4, 0x64, 0x47, 0xce, 0x40, 0x3b, 0x0c, 0x4a, + 0x62, 0x52, 0xba, 0xc7, 0xf0, 0x36, 0x87, 0x9c, 0x79, 0x9a, 0x83, 0x11, 0x61, 0x0c, 0x1b, 0x6b +}; + +char dh_except_b_pubkey_4096[] = { + 0x44, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x9, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x4, 0xe8, 0x9a, 0xd2, 0x0, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x0, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x5, + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x7, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x3, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x1, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7, + 0x44, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x9, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x4, 0xe8, 0x9a, 0xd2, 0x0, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x0, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x5, + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x7, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x3, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x1, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7 +}; + +char dh_share_key_4096[] = { + 0xaf, 0xd4, 0xf6, 0x45, 0x63, 0x21, 0x8d, 0x98, 0xc4, 0xab, 0x18, 0xd7, 0x2b, 0x3c, 0x1d, 0xde, + 0xe7, 0x1f, 0xe1, 0xc5, 0x79, 0x57, 0x60, 0x20, 0xfa, 0x99, 0xbd, 0x7b, 0xa2, 0x94, 0x0b, 0xa3, + 0xb4, 0xb3, 0x33, 0x4a, 0x2f, 0xd0, 0x17, 0x7, 0x2e, 0x70, 0x19, 0x84, 0x1f, 0x8e, 0xe9, 0x61, + 0xe5, 0x52, 0x3, 0x96, 0xea, 0xd8, 0xb6, 0x3, 0x9f, 0xc4, 0x3e, 0x23, 0x77, 0x17, 0x54, 0xfb, + 0x13, 0xf0, 0x3e, 0x9a, 0x27, 0x5d, 0x12, 0x99, 0x58, 0x8d, 0x41, 0x46, 0xd9, 0xc9, 0x29, 0xbd, + 0x40, 0xd1, 0x4f, 0xef, 0x63, 0x7b, 0x54, 0xe6, 0x59, 0x6d, 0xe2, 0x30, 0xe8, 0x2c, 0x2f, 0xf9, + 0x66, 0xa2, 0x12, 0xf5, 0x58, 0x61, 0xac, 0x43, 0xec, 0x7e, 0xf9, 0x2e, 0x27, 0x70, 0x35, 0x75, + 0xb4, 0x10, 0x29, 0xac, 0x0a, 0xab, 0x59, 0xb6, 0x68, 0x4c, 0x16, 0xaf, 0xf0, 0x4f, 0x21, 0xcd, + 0xcc, 0x48, 0x97, 0xe4, 0x21, 0x65, 0xa6, 0x55, 0xb8, 0xf3, 0xb2, 0x7b, 0x91, 0xd7, 0xca, 0xb9, + 0x17, 0x58, 0x31, 0x71, 0xc0, 0xc9, 0x69, 0x1e, 0xf0, 0x9e, 0x3f, 0xe2, 0x37, 0x4, 0x2d, 0xa8, + 0x55, 0x9, 0x6b, 0x9c, 0xc6, 0x37, 0xa9, 0x9b, 0xdf, 0x67, 0x73, 0x7b, 0x46, 0xf9, 0x63, 0x47, + 0xcb, 0xa0, 0x57, 0x2a, 0xed, 0x97, 0x2f, 0xfe, 0x92, 0xf2, 0x20, 0x2c, 0x7e, 0xee, 0x7d, 0x11, + 0x78, 0xe6, 0xb9, 0x9, 0xd1, 0x94, 0xce, 0xd1, 0x5b, 0xf4, 0x44, 0xa9, 0xcb, 0x26, 0x2, 0x36, + 0x57, 0x2c, 0xa2, 0xbe, 0x37, 0xde, 0x86, 0x46, 0x20, 0x27, 0x9d, 0xa0, 0x2f, 0x4, 0xc1, 0xcd, + 0xff, 0x81, 0xe5, 0xe6, 0x2c, 0x9e, 0x39, 0x82, 0x31, 0x54, 0x33, 0xf8, 0xe7, 0xa0, 0xe5, 0x96, + 0xa4, 0x40, 0xc4, 0x44, 0xfe, 0x93, 0x66, 0xe2, 0xda, 0xaa, 0xb8, 0xfb, 0x2f, 0x3b, 0x8c, 0xce, + 0xaf, 0xd4, 0xf6, 0x45, 0x63, 0x21, 0x8d, 0x98, 0xc4, 0xab, 0x18, 0xd7, 0x2b, 0x3c, 0x1d, 0xde, + 0xe7, 0x1f, 0xe1, 0xc5, 0x79, 0x57, 0x60, 0x20, 0xfa, 0x99, 0xbd, 0x7b, 0xa2, 0x94, 0x0b, 0xa3, + 0xb4, 0xb3, 0x33, 0x4a, 0x2f, 0xd0, 0x17, 0x7, 0x2e, 0x70, 0x19, 0x84, 0x1f, 0x8e, 0xe9, 0x61, + 0xe5, 0x52, 0x3, 0x96, 0xea, 0xd8, 0xb6, 0x3, 0x9f, 0xc4, 0x3e, 0x23, 0x77, 0x17, 0x54, 0xfb, + 0x13, 0xf0, 0x3e, 0x9a, 0x27, 0x5d, 0x12, 0x99, 0x58, 0x8d, 0x41, 0x46, 0xd9, 0xc9, 0x29, 0xbd, + 0x40, 0xd1, 0x4f, 0xef, 0x63, 0x7b, 0x54, 0xe6, 0x59, 0x6d, 0xe2, 0x30, 0xe8, 0x2c, 0x2f, 0xf9, + 0x66, 0xa2, 0x12, 0xf5, 0x58, 0x61, 0xac, 0x43, 0xec, 0x7e, 0xf9, 0x2e, 0x27, 0x70, 0x35, 0x75, + 0xb4, 0x10, 0x29, 0xac, 0x0a, 0xab, 0x59, 0xb6, 0x68, 0x4c, 0x16, 0xaf, 0xf0, 0x4f, 0x21, 0xcd, + 0xcc, 0x48, 0x97, 0xe4, 0x21, 0x65, 0xa6, 0x55, 0xb8, 0xf3, 0xb2, 0x7b, 0x91, 0xd7, 0xca, 0xb9, + 0x17, 0x58, 0x31, 0x71, 0xc0, 0xc9, 0x69, 0x1e, 0xf0, 0x9e, 0x3f, 0xe2, 0x37, 0x4, 0x2d, 0xa8, + 0x55, 0x9, 0x6b, 0x9c, 0xc6, 0x37, 0xa9, 0x9b, 0xdf, 0x67, 0x73, 0x7b, 0x46, 0xf9, 0x63, 0x47, + 0xcb, 0xa0, 0x57, 0x2a, 0xed, 0x97, 0x2f, 0xfe, 0x92, 0xf2, 0x20, 0x2c, 0x7e, 0xee, 0x7d, 0x11, + 0x78, 0xe6, 0xb9, 0x9, 0xd1, 0x94, 0xce, 0xd1, 0x5b, 0xf4, 0x44, 0xa9, 0xcb, 0x26, 0x2, 0x36, + 0x57, 0x2c, 0xa2, 0xbe, 0x37, 0xde, 0x86, 0x46, 0x20, 0x27, 0x9d, 0xa0, 0x2f, 0x4, 0xc1, 0xcd, + 0xff, 0x81, 0xe5, 0xe6, 0x2c, 0x9e, 0x39, 0x82, 0x31, 0x54, 0x33, 0xf8, 0xe7, 0xa0, 0xe5, 0x96, + 0xa4, 0x40, 0xc4, 0x44, 0xfe, 0x93, 0x66, 0xe2, 0xda, 0xaa, 0xb8, 0xfb, 0x2f, 0x3b, 0x8c, 0xce, +}; + + + +char rsa_e_2048[] = { + 0xaf, 0xd4, 0xf6, 0x45, 0x63, 0x21, 0x8d, 0x98, 0xc4, 0xab, 0x18, 0xd7, 0x2b, 0x3c, 0x1d, 0xde, + 0xe7, 0x1f, 0xe1, 0xc5, 0x79, 0x57, 0x60, 0x20, 0xfa, 0x99, 0xbd, 0x7b, 0xa2, 0x94, 0x0b, 0xa3, + 0xb4, 0xb3, 0x33, 0x4a, 0x2f, 0xd0, 0x17, 0x7, 0x2e, 0x70, 0x19, 0x84, 0x1f, 0x8e, 0xe9, 0x61, + 0xe5, 0x52, 0x3, 0x96, 0xea, 0xd8, 0xb6, 0x3, 0x9f, 0xc4, 0x3e, 0x23, 0x77, 0x17, 0x54, 0xfb, + 0x13, 0xf0, 0x3e, 0x9a, 0x27, 0x5d, 0x12, 0x99, 0x58, 0x8d, 0x41, 0x46, 0xd9, 0xc9, 0x29, 0xbd, + 0x40, 0xd1, 0x4f, 0xef, 0x63, 0x7b, 0x54, 0xe6, 0x59, 0x6d, 0xe2, 0x30, 0xe8, 0x2c, 0x2f, 0xf9, + 0x66, 0xa2, 0x12, 0xf5, 0x58, 0x61, 0xac, 0x43, 0xec, 0x7e, 0xf9, 0x2e, 0x27, 0x70, 0x35, 0x75, + 0xb4, 0x10, 0x29, 0xac, 0x0a, 0xab, 0x59, 0xb6, 0x68, 0x4c, 0x16, 0xaf, 0xf0, 0x4f, 0x21, 0xcd, + 0xcc, 0x48, 0x97, 0xe4, 0x21, 0x65, 0xa6, 0x55, 0xb8, 0xf3, 0xb2, 0x7b, 0x91, 0xd7, 0xca, 0xb9, + 0x17, 0x58, 0x31, 0x71, 0xc0, 0xc9, 0x69, 0x1e, 0xf0, 0x9e, 0x3f, 0xe2, 0x37, 0x4, 0x2d, 0xa8, + 0x55, 0x09, 0x6b, 0x9c, 0xc6, 0x37, 0xa9, 0x9b, 0xdf, 0x67, 0x73, 0x7b, 0x46, 0xf9, 0x63, 0x47, + 0xcb, 0xa0, 0x57, 0x2a, 0xed, 0x97, 0x2f, 0xfe, 0x92, 0xf2, 0x20, 0x2c, 0x7e, 0xee, 0x7d, 0x11, + 0x78, 0xe6, 0xb9, 0x9, 0xd1, 0x94, 0xce, 0xd1, 0x5b, 0xf4, 0x44, 0xa9, 0xcb, 0x26, 0x2, 0x36, + 0x57, 0x2c, 0xa2, 0xbe, 0x37, 0xde, 0x86, 0x46, 0x20, 0x27, 0x9d, 0xa0, 0x2f, 0x4, 0xc1, 0xcd, + 0xff, 0x81, 0xe5, 0xe6, 0x2c, 0x9e, 0x39, 0x82, 0x31, 0x54, 0x33, 0xf8, 0xe7, 0xa0, 0xe5, 0x96, + 0xa4, 0x40, 0xc4, 0x44, 0xfe, 0x93, 0x66, 0xe2, 0xda, 0xaa, 0xb8, 0xfb, 0x2f, 0x3b, 0x8c, 0xce, +}; + +char rsa_p_2048[] = { + 0xce, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x09, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x04, 0xe8, 0x9a, 0xd2, 0x00, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x00, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x05, + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x07, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x03, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x01, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7 +}; + +char rsa_q_2048[] = { + 0x44, 0x58, 0xe8, 0x62, 0xc8, 0xd2, 0xb5, 0x45, 0x1f, 0xa5, 0xc3, 0xdb, 0x8e, 0x69, 0x42, 0xd2, + 0x21, 0x7e, 0x6b, 0x26, 0x69, 0x45, 0xf1, 0x33, 0xcf, 0xd7, 0xe6, 0x6e, 0x64, 0xc3, 0x29, 0xa5, + 0x68, 0x49, 0x3d, 0x13, 0x0b, 0x42, 0x36, 0xa6, 0xf4, 0xb1, 0xab, 0xa3, 0x8f, 0xe6, 0xcf, 0x46, + 0xe8, 0x85, 0xf3, 0xaa, 0xcb, 0x9, 0x84, 0x32, 0x34, 0xf7, 0x46, 0x0a, 0x65, 0xf9, 0xb5, 0x97, + 0xc2, 0x4a, 0x6f, 0x41, 0x40, 0xc9, 0x9e, 0x63, 0xe1, 0x0f, 0xd2, 0x12, 0x59, 0x35, 0xcc, 0x39, + 0x99, 0x4, 0xe8, 0x9a, 0xd2, 0x0, 0x7a, 0xce, 0x3c, 0x78, 0xfe, 0xea, 0x4b, 0x13, 0x53, 0xcd, + 0xc3, 0x60, 0x73, 0xa4, 0x3f, 0xbc, 0x8a, 0x8d, 0x61, 0x1c, 0xfa, 0xaf, 0xb7, 0xf8, 0x37, 0xa5, + 0xe2, 0x3a, 0xd2, 0x7a, 0xb6, 0x0, 0xf3, 0xd8, 0x3a, 0xa2, 0x46, 0xd2, 0x5c, 0x91, 0xc1, 0x5, + 0x6a, 0xf3, 0x2c, 0xd2, 0x2d, 0x55, 0xc1, 0x54, 0x40, 0x18, 0x71, 0x7, 0x96, 0xa9, 0x56, 0x6e, + 0x45, 0x58, 0x24, 0xce, 0x75, 0x80, 0x3, 0x68, 0x36, 0x96, 0x3, 0xb2, 0x9c, 0x25, 0xbc, 0x55, + 0x0d, 0xe8, 0xa1, 0x7d, 0xdd, 0x39, 0x87, 0x3c, 0xa1, 0x6a, 0xeb, 0x1b, 0x4f, 0x14, 0x72, 0x88, + 0x6c, 0x14, 0x6d, 0x24, 0xb7, 0xda, 0xf8, 0x97, 0xaa, 0xba, 0xb4, 0xdd, 0xc9, 0x5b, 0x28, 0x10, + 0x49, 0xfa, 0x93, 0xcc, 0x62, 0xc0, 0x70, 0xf8, 0xd6, 0xdc, 0xb2, 0x80, 0x35, 0x20, 0x84, 0xa4, + 0x99, 0xfc, 0x10, 0x7c, 0x9d, 0xc0, 0xc6, 0xd4, 0x8b, 0x0c, 0x57, 0xf1, 0x1, 0xf5, 0x1a, 0x4f, + 0x20, 0xfa, 0x8d, 0x66, 0x8b, 0x22, 0x3c, 0x96, 0xef, 0xd0, 0xde, 0xe5, 0x7e, 0x7f, 0x23, 0xdc, + 0x6d, 0x71, 0xdf, 0xc3, 0xe5, 0x1b, 0x39, 0xfe, 0xb7, 0x77, 0xe5, 0x72, 0x0d, 0x1c, 0x8d, 0xb7 +}; + +enum dh_test_item { + TEST_ITEM_INVALID, + SW_GENERATE_KEY, + SW_COMPUTE_KEY, + HW_GENERATE_KEY, + HW_COMPUTE_KEY, +}; + +struct hpre_dh_test_ctx_setup { + void *x; + void *p; + void *g; + void *except_pub_key; + void *cp_pub_key; + void *cp_share_key; + u32 x_size; + u32 p_size; + u32 g_size; + u32 cp_pub_key_size; + u32 cp_share_key_size; + u32 except_pub_key_size; + u32 op_type; + u32 generator; + u32 key_bits; + u32 key_from; //0 - Openssl 1 - Designed + void *pool; + void *q; + void *ctx; +}; + +struct hpre_dh_sw_opdata { + BIGNUM *except_pub_key; + unsigned char *pub_key; + u32 pub_key_size; + unsigned char *share_key; + u32 share_key_size; +}; + +struct hpre_dh_test_ctx { + void *priv; + void *opdata; + unsigned char *cp_share_key; + u32 cp_share_key_size; + unsigned char *cp_pub_key; + u32 cp_pub_key_size; + u32 op; + u32 key_size; + void *pool; +}; + +struct hpre_rsa_test_key_in { + void *e; + void *p; + void *q; + u32 e_size; + u32 p_size; + u32 q_size; + void *data[]; +}; + +static __thread struct hpre_rsa_test_key_in *rsa_key_in = NULL; + +/* OpenSSL RSA and BN APIs */ +BIGNUM *BN_new(void); +int BN_bn2bin(const BIGNUM *a, unsigned char *to); +BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret); +void BN_free(BIGNUM *a); +BIGNUM *BN_dup(const BIGNUM *a); +RSA *RSA_new(void); +void RSA_free(RSA *rsa); +int BN_set_word(BIGNUM *a, BN_ULONG w); +int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb); +void RSA_get0_key(const RSA *r, + const BIGNUM **n, const BIGNUM **e, const BIGNUM **d); +void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q); +void RSA_get0_crt_params(const RSA *r, + const BIGNUM **dmp1, const BIGNUM **dmq1, + const BIGNUM **iqmp); +int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, + BIGNUM *iqmp); +int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d); +int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q); +int RSA_public_encrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +int RSA_private_decrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +DH *DH_new(void); +void DH_free(DH *r); +int DH_generate_parameters_ex(DH *dh, int prime_len, int generator, + BN_GENCB *cb); +void DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, + const BIGNUM **g); +int DH_generate_key(DH *dh); +void DH_get0_key(const DH *dh, const BIGNUM **pub_key, + const BIGNUM **priv_key); +int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g); +int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key); +int DH_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh); +void *_hpre_sys_test_thread(void *data); + +#ifdef DEBUG +static void print_data(void *ptr, int size, const char *name) +{ + __u32 i = 0; + __u8* p = ptr; + + printf("\n%s:start_addr=%p, size %d\n", name, ptr, size); + for (i = 1; i <= size; i++) { + printf("%02x ", p[i - 1]); + if (i % 16 == 0) + printf("\n"); + } +} +#endif + +static int init_opdata_param(void *pool, + struct wcrypto_dh_op_data *opdata, + int key_size, enum dh_check_index step) +{ + unsigned char *ag_bin = NULL; + + memset(opdata, 0, sizeof(*opdata)); + if (step == DH_ALICE_PRIVKEY) { + ag_bin = wd_alloc_blk(pool); + if (!ag_bin) + return -ENOMEM; + memset(ag_bin, 0, 2 * key_size); + opdata->pv = ag_bin; + } + + opdata->x_p = wd_alloc_blk(pool); + if (!opdata->x_p) { + if (ag_bin) + wd_free_blk(pool, ag_bin); + return -ENOMEM; + } + memset(opdata->x_p, 0, 2 * key_size); + + opdata->pri = wd_alloc_blk(pool); + if (!opdata->pri) { + if (ag_bin) + wd_free_blk(pool, ag_bin); + wd_free_blk(pool, opdata->x_p); + return -ENOMEM; + } + memset(opdata->pri, 0, 2 * key_size); + + return 0; +} + + +void hpre_dh_del_test_ctx(struct hpre_dh_test_ctx *test_ctx) +{ + if (!test_ctx) + return; + + if (SW_GENERATE_KEY == test_ctx->op) { + DH_free(test_ctx->priv); + } else if (SW_COMPUTE_KEY == test_ctx->op) { + struct hpre_dh_sw_opdata *opdata = test_ctx->opdata; + + free(opdata->except_pub_key); + free(opdata->share_key); + free(opdata); + DH_free(test_ctx->priv); + } else if (HW_GENERATE_KEY == test_ctx->op) { + struct wcrypto_dh_op_data *opdata = test_ctx->opdata; + + wd_free_blk(test_ctx->pool, opdata->x_p); + wd_free_blk(test_ctx->pool, opdata->pri); + free(opdata); + free(test_ctx->cp_pub_key); + } else if (HW_COMPUTE_KEY == test_ctx->op) { + struct wcrypto_dh_op_data *opdata = test_ctx->opdata; + + wd_free_blk(test_ctx->pool, opdata->pv); + wd_free_blk(test_ctx->pool, opdata->x_p); + wd_free_blk(test_ctx->pool, opdata->pri); + free(opdata); + free(test_ctx->cp_share_key); + } else { + HPRE_TST_PRT("%s: no op %d\n", __func__, test_ctx->op); + } + + free(test_ctx); +} + +static struct hpre_dh_test_ctx *create_sw_gen_key_test_ctx(struct hpre_dh_test_ctx_setup setup) +{ + BIGNUM *p = NULL, *g = NULL, *x = NULL; + struct hpre_dh_test_ctx *test_ctx; + DH *dh = NULL; + + if (SW_GENERATE_KEY != setup.op_type) { + HPRE_TST_PRT("%s: err op type %d\n", __func__, setup.op_type); + return NULL; + } + + dh = DH_new(); + if (!dh) + return NULL; + + test_ctx = malloc(sizeof(struct hpre_dh_test_ctx)); + if (!test_ctx) { + DH_free(dh); + return NULL; + } + + if (setup.key_from) { + p = BN_bin2bn(setup.p, setup.p_size, NULL); + g = BN_bin2bn(setup.g, setup.g_size, NULL); + x = BN_bin2bn(setup.x, setup.x_size, NULL); + DH_set0_pqg(dh, p, NULL, g); + DH_set0_key(dh, NULL, x); + } else { + if (!DH_generate_parameters_ex(dh, setup.key_bits, setup.generator, NULL)) { + HPRE_TST_PRT("DH_generate_parameters_ex fail!\n"); + DH_free(dh); + free(test_ctx); + return NULL; + } + } + + test_ctx->op = SW_GENERATE_KEY; + test_ctx->priv = dh; + test_ctx->key_size = setup.key_bits >> 3; + +#ifdef DEBUG + //DHparams_print_fp(stdout, dh); +#endif + + return test_ctx; +} + +static struct hpre_dh_test_ctx *create_sw_compute_key_test_ctx(struct hpre_dh_test_ctx_setup setup) +{ + struct hpre_dh_sw_opdata *opdata; + struct hpre_dh_test_ctx *test_ctx; + DH *dh = NULL; + + if (!setup.except_pub_key || + !setup.except_pub_key_size || + setup.op_type !=SW_COMPUTE_KEY) { + HPRE_TST_PRT("%s: parm err!\n", __func__); + return NULL; + } + + dh = DH_new(); + if (!dh) + return NULL; + + opdata = malloc(sizeof(struct hpre_dh_sw_opdata)); + if (!opdata) { + DH_free(dh); + return NULL; + } + memset(opdata, 0, sizeof(struct hpre_dh_sw_opdata)); + + test_ctx = malloc(sizeof(struct hpre_dh_test_ctx)); + if (!test_ctx) { + DH_free(dh); + free(opdata); + return NULL; + } + memset(test_ctx, 0, sizeof(struct hpre_dh_test_ctx)); + + opdata->share_key = malloc(setup.key_bits >> 3); + if (!opdata->share_key) { + DH_free(dh); + free(opdata); + free(test_ctx); + return NULL; + } + + if (setup.key_from) { + BIGNUM *p = NULL, *g = NULL, *x = NULL; + p = BN_bin2bn(setup.p, setup.p_size, NULL); + g = BN_bin2bn(setup.g, setup.g_size, NULL); + x = BN_bin2bn(setup.x, setup.x_size, NULL); + DH_set0_pqg(dh, p, NULL, g); + DH_set0_key(dh, NULL, x); + + opdata->except_pub_key = BN_bin2bn(setup.except_pub_key, + setup.except_pub_key_size, NULL); + + } else { + opdata->except_pub_key = BN_bin2bn(setup.except_pub_key, + setup.except_pub_key_size, NULL); + + if (!DH_generate_parameters_ex(dh, setup.key_bits, setup.generator, NULL)) { + HPRE_TST_PRT("DH_generate_parameters_ex fail!\n"); + goto exit_free; + } + + if (!DH_generate_key(dh)) { + HPRE_TST_PRT("Alice DH_generate_key fail!\n"); + goto exit_free; + } + } +#ifdef DEBUG + //DHparams_print_fp(stdout, dh); +#endif + test_ctx->op = SW_COMPUTE_KEY; + test_ctx->priv = dh; + test_ctx->opdata = opdata; + test_ctx->key_size = setup.key_bits >> 3; + + return test_ctx; + +exit_free: + hpre_dh_del_test_ctx(test_ctx); + + return NULL; +} + +static struct hpre_dh_test_ctx *create_hw_gen_key_test_ctx(struct hpre_dh_test_ctx_setup setup) +{ + const BIGNUM *p = NULL, *g = NULL, *x = NULL; + const BIGNUM *pub_key = NULL; + struct wcrypto_dh_op_data *opdata; + struct hpre_dh_test_ctx *test_ctx; + struct wd_dtb ctx_g; + int ret; + u32 key_size = setup.key_bits >> 3; + DH *dh = NULL; + + if (!setup.q || !setup.pool || setup.op_type !=HW_GENERATE_KEY) { + HPRE_TST_PRT("%s: parm err!\n", __func__); + return NULL; + } + + opdata = malloc(sizeof(struct wcrypto_dh_op_data)); + if (!opdata) + return NULL; + memset(opdata, 0, sizeof(struct hpre_dh_sw_opdata)); + + dh = DH_new(); + if (!dh) { + free(opdata); + return NULL; + } + + test_ctx = malloc(sizeof(struct hpre_dh_test_ctx)); + if (!test_ctx) { + free(opdata); + DH_free(dh); + return NULL; + } + memset(test_ctx, 0, sizeof(struct hpre_dh_test_ctx)); + + ctx_g.data = malloc(key_size); + if (!ctx_g.data) { + free(test_ctx); + free(opdata); + DH_free(dh); + return NULL; + } + memset(ctx_g.data, 0, key_size); + + test_ctx->cp_pub_key = malloc(key_size); + if (!test_ctx->cp_pub_key) { + free(test_ctx); + free(opdata); + DH_free(dh); + free(ctx_g.data); + return NULL; + } + + ret = init_opdata_param(setup.pool, opdata, key_size, DH_ALICE_PUBKEY); + if (ret < 0) { + HPRE_TST_PRT("init_opdata_param failed\n"); + free(test_ctx); + free(opdata); + DH_free(dh); + free(ctx_g.data); + return NULL; + } + + if (setup.key_from) { + if (!setup.x || !setup.x_size || !setup.p || !setup.cp_pub_key || + !setup.p_size || !setup.g || !setup.g_size || !setup.cp_pub_key_size) { + HPRE_TST_PRT("%s: x/p/g parm err\n", __func__); + goto exit_free; + } + + memcpy(opdata->x_p, setup.x, setup.x_size); + memcpy(opdata->x_p + key_size, setup.p, setup.p_size); + memcpy(ctx_g.data, setup.g, setup.g_size); + memcpy(test_ctx->cp_pub_key, setup.cp_pub_key, setup.cp_pub_key_size); + opdata->pbytes = setup.p_size; + opdata->xbytes = setup.x_size; + ctx_g.dsize = setup.g_size; + ctx_g.bsize = key_size; + test_ctx->cp_pub_key_size = setup.cp_pub_key_size; + } else { + ret = DH_generate_parameters_ex(dh, setup.key_bits, setup.generator, NULL); + if (!ret) { + HPRE_TST_PRT("DH_generate_parameters_ex failed\n"); + goto exit_free; + } + + if (!DH_generate_key(dh)) { + HPRE_TST_PRT("DH_generate_key failed\n"); + goto exit_free; + } + + DH_get0_pqg(dh, &p, NULL, &g); + DH_get0_key(dh, &pub_key, &x); + + opdata->pbytes = BN_bn2bin(p, opdata->x_p + key_size); + opdata->xbytes = BN_bn2bin(x, opdata->x_p); + ctx_g.dsize = BN_bn2bin(g, (unsigned char*)ctx_g.data); + ctx_g.bsize = key_size; + test_ctx->cp_pub_key_size = BN_bn2bin(pub_key, test_ctx->cp_pub_key); + } + +#ifdef DEBUG + print_data(ctx_g.data, ctx_g.dsize, "g"); + print_data(opdata->x_p, opdata->xbytes, "x"); + print_data(opdata->x_p + key_size, opdata->pbytes, "p"); + print_data(test_ctx->cp_pub_key, test_ctx->cp_pub_key_size, "cp_pub_key"); +#endif + + opdata->op_type = WCRYPTO_DH_PHASE1; + test_ctx->opdata = opdata; + test_ctx->pool = setup.pool; + test_ctx->op = setup.op_type; + test_ctx->priv = setup.ctx; //init ctx + test_ctx->key_size = key_size; + + ret = wcrypto_set_dh_g(test_ctx->priv, &ctx_g); + if (ret) { + HPRE_TST_PRT("wcrypto_set_dh_g failed\n"); + goto exit_free; + } + + + DH_free(dh); + free(ctx_g.data); + + return test_ctx; +exit_free: + DH_free(dh); + free(ctx_g.data); + hpre_dh_del_test_ctx(test_ctx); + + return NULL; +} + +static struct hpre_dh_test_ctx *create_hw_compute_key_test_ctx(struct hpre_dh_test_ctx_setup setup) +{ + const BIGNUM *p = NULL, *g = NULL, *x = NULL; + struct wcrypto_dh_op_data *opdata; + struct hpre_dh_test_ctx *test_ctx; + int ret; + u32 key_size = setup.key_bits >> 3; + DH *dh = NULL; + DH *b = NULL; + + if (!setup.q || !setup.pool || setup.op_type !=HW_COMPUTE_KEY) { + HPRE_TST_PRT("%s: parm err!\n", __func__); + return NULL; + } + + opdata = malloc(sizeof(struct wcrypto_dh_op_data)); + if (!opdata) + return NULL; + memset(opdata, 0, sizeof(struct wcrypto_dh_op_data)); + + dh = DH_new(); + if (!dh) { + free(opdata); + return NULL; + } + + test_ctx = malloc(sizeof(struct hpre_dh_test_ctx)); + if (!test_ctx) { + free(opdata); + DH_free(dh); + return NULL; + } + memset(test_ctx, 0, sizeof(struct hpre_dh_test_ctx)); + + test_ctx->cp_share_key = malloc(key_size); + if (!test_ctx->cp_share_key) { + free(test_ctx); + free(opdata); + DH_free(dh); + return NULL; + } + + ret = init_opdata_param(setup.pool, opdata, key_size, DH_ALICE_PRIVKEY); + if (ret < 0) { + HPRE_TST_PRT("init_opdata_param failed\n"); + free(test_ctx); + free(opdata); + DH_free(dh); + return NULL; + } + + if (setup.key_from) { + memcpy(opdata->x_p, setup.x, setup.x_size); + memcpy(opdata->x_p + key_size, setup.p, setup.p_size); + memcpy(opdata->pv, setup.except_pub_key, setup.except_pub_key_size); + memcpy(test_ctx->cp_share_key, setup.cp_share_key, setup.cp_share_key_size); + opdata->pbytes = setup.p_size; + opdata->xbytes = setup.x_size; + opdata->pvbytes = setup.except_pub_key_size; + test_ctx->cp_share_key_size = setup.cp_share_key_size; + } else { + const BIGNUM *bp = NULL, *bg = NULL, + *bpub_key = NULL, *bpriv_key = NULL; + b = DH_new(); + + ret = DH_generate_parameters_ex(dh, setup.key_bits, setup.generator, NULL); + if (!ret) { + HPRE_TST_PRT("DH_generate_parameters_ex fail!\n"); + goto exit_free; + } + + if (!DH_generate_key(dh)) { + HPRE_TST_PRT("Alice DH_generate_key fail!\n"); + goto exit_free; + } + + DH_get0_pqg(dh, &p, NULL, &g); + DH_get0_key(dh, NULL, &x); + bp = BN_dup(p); + bg = BN_dup(g); + DH_set0_pqg(b, (BIGNUM *)bp, NULL, (BIGNUM *)bg); + if (!DH_generate_key(b)) { + HPRE_TST_PRT("a DH_generate_key fail!\n"); + ret = -1; + goto exit_free; + } + DH_get0_key(b, &bpub_key, &bpriv_key); + + test_ctx->cp_share_key_size = DH_compute_key(test_ctx->cp_share_key, bpub_key, dh); + if (!test_ctx->cp_share_key_size || test_ctx->cp_share_key_size == -1) { + HPRE_TST_PRT("DH_compute_key fail!\n"); + goto exit_free; + } + + opdata->pbytes = BN_bn2bin(p, opdata->x_p + key_size); + opdata->xbytes = BN_bn2bin(x, opdata->x_p); + opdata->pvbytes = setup.except_pub_key_size; + opdata->pvbytes = BN_bn2bin(bpub_key, opdata->pv); + } + + opdata->op_type = WCRYPTO_DH_PHASE2; + test_ctx->priv = setup.ctx; //init ctx + test_ctx->opdata = opdata; + test_ctx->pool = setup.pool; + test_ctx->op = setup.op_type; + test_ctx->key_size = key_size; + +#ifdef DEBUG + print_data(opdata->pv, opdata->pvbytes, "pv"); + print_data(opdata->x_p, opdata->xbytes, "x"); + print_data(opdata->x_p + key_size, opdata->pbytes, "p"); + print_data(test_ctx->cp_share_key, test_ctx->cp_share_key_size, "cp_share_key"); +#endif + + DH_free(dh); + if (b) + DH_free(b); + + return test_ctx; +exit_free: + DH_free(dh); + if (b) + DH_free(b); + hpre_dh_del_test_ctx(test_ctx); + + return NULL; +} + + +struct hpre_dh_test_ctx *hpre_dh_create_test_ctx(struct hpre_dh_test_ctx_setup setup) +{ + struct hpre_dh_test_ctx *test_ctx = NULL; + + switch (setup.op_type) { + case SW_GENERATE_KEY: + { + test_ctx = create_sw_gen_key_test_ctx(setup); + } + break; + case HW_GENERATE_KEY: + { + test_ctx = create_hw_gen_key_test_ctx(setup); + } + break; + case SW_COMPUTE_KEY: + { + test_ctx = create_sw_compute_key_test_ctx(setup); + } + break; + case HW_COMPUTE_KEY: + { + test_ctx = create_hw_compute_key_test_ctx(setup); + } + break; + default: + break; + } + + return test_ctx; +} + +int dh_generate_key(void *test_ctx, void *tag) +{ + struct hpre_dh_test_ctx *t_c = test_ctx; + int ret = 0; + + if (t_c->op == SW_GENERATE_KEY) { + DH *dh = t_c->priv; + + if (!DH_generate_key(dh)) { + HPRE_TST_PRT("DH_generate_key fail!\n"); + return -1; + } + +#ifdef DEBUG + //DHparams_print_fp(stdout, dh); +#endif + + } else { + struct wcrypto_dh_op_data *opdata = t_c->opdata; + void* ctx = t_c->priv; +try_again: + ret = wcrypto_do_dh(ctx, opdata, tag); + if (ret == -WD_EBUSY) { + usleep(100); + goto try_again; + } else if (ret) { + HPRE_TST_PRT("wcrypto_do_dh fail!\n"); + return -1; + } + } + + return 0; +} + +int dh_compute_key(void *test_ctx, void *tag) +{ + struct hpre_dh_test_ctx *t_c = test_ctx; + int ret = 0; + + if (t_c->op == SW_COMPUTE_KEY) { + struct hpre_dh_sw_opdata *opdata = t_c->opdata; + DH *dh = t_c->priv; + + ret = DH_compute_key(opdata->share_key, opdata->except_pub_key, dh); + if (ret <= 0) { + HPRE_TST_PRT("DH_compute_key fail!\n"); + return -1; + } + opdata->share_key_size = ret; + +#ifdef DEBUG + //DHparams_print_fp(stdout, dh); + //print_data(opdata->share_key, ret, "openssl share key"); + +#endif + } else { + struct wcrypto_dh_op_data *opdata = t_c->opdata; + void* ctx = t_c->priv; +try_again: + + ret = wcrypto_do_dh(ctx, opdata, tag); + if (ret == -WD_EBUSY) { + usleep(100); + goto try_again; + } else if (ret) { + HPRE_TST_PRT("wcrypto_do_dh fail!\n"); + return -1; + } +#ifdef DEBUG + //print_data(opdata->pri, opdata->pri_bytes,"hpre share key"); +#endif + } + + return 0; +} + +static bool is_exit(struct test_hpre_pthread_dt *pdata) +{ + struct timeval cur_tval; + float time_used; + + //if (!performance_test) + // return false; + + gettimeofday(&cur_tval, NULL); + time_used = (float)((cur_tval.tv_sec -pdata->start_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - pdata->start_tval.tv_usec); + + if (t_seconds) + return time_used >= t_seconds * 1000000; + else if (t_times) + return pdata->send_task_num >= t_times; + + return false; +} + +static int dh_result_check(struct hpre_dh_test_ctx *test_ctx) +{ + struct wcrypto_dh_op_data *opdata = test_ctx->opdata; + unsigned char *cp_key; + u32 cp_size; + + if (test_ctx->op == HW_GENERATE_KEY) { + cp_key = test_ctx->cp_pub_key; + cp_size = test_ctx->cp_pub_key_size; + + } else { + cp_key = test_ctx->cp_share_key; + cp_size = test_ctx->cp_share_key_size; + } + + if (opdata->pri_bytes != cp_size || memcmp(cp_key, opdata->pri, cp_size)) { + HPRE_TST_PRT("dh op %d mismatch!\n", test_ctx->op); + +#ifdef DEBUG + print_data(opdata->pri, opdata->pri_bytes, "hpre out"); + print_data(cp_key, cp_size, "openssl out"); +#endif + + return -1; + } + + return 0; + +} + +static bool is_allow_print(int cnt, enum alg_op_type opType, int thread_num) +{ + int intval_index = 0; + unsigned int log_intval_adjust = 0; + int log_intval[LOG_INTVL_NUM] = {0x1, 0xff, 0x3ff, 0x7ff, 0xfff, 0x1fff}; + + if (!with_log) + return false; + + if (only_soft) + return true; + + switch (opType) { + case RSA_ASYNC_GEN: + case RSA_ASYNC_EN: + case RSA_ASYNC_DE: + case DH_ASYNC_COMPUTE: + case DH_ASYNC_GEN: + case RSA_KEY_GEN: + { + intval_index = 0x04; + } + break; + case DH_COMPUTE: + case DH_GEN: + { + intval_index = 0x00; + } + break; + default: + { + intval_index = 0x01; + } + break; + } + + if (!thread_num) + return false; + log_intval_adjust = log_intval[intval_index] * ((thread_num - 1) / 16 + 1); + + if (!(cnt % log_intval_adjust)) + return true; + else + return false; +} + +static void _dh_perf_cb(const void *message, void *tag) +{ + //const struct wcrypto_dh_msg *msg = message; + struct dh_user_tag_info* pTag = (struct dh_user_tag_info*)tag; + struct test_hpre_pthread_dt *thread_data = pTag->thread_data; + + thread_data->recv_task_num++; + hpre_dh_del_test_ctx(pTag->test_ctx); + free(pTag); +} + +static void _dh_cb(const void *message, void *tag) +{ + const struct wcrypto_dh_msg *msg = message; + struct dh_user_tag_info* pSwData = (struct dh_user_tag_info*)tag; + struct timeval start_tval, end_tval; + int pid, threadId; + float time, speed; + int ret; + static int failTimes = 0; + struct hpre_dh_test_ctx *test_ctx = pSwData->test_ctx; + struct wcrypto_dh_op_data *opdata = test_ctx->opdata; + struct test_hpre_pthread_dt *thread_data = pSwData->thread_data; + + start_tval = thread_data->start_tval; + pid = pSwData->pid; + threadId = pSwData->thread_id; + + if (opdata->status != WD_SUCCESS) { + HPRE_TST_PRT("Proc-%d, %d-TD dh %dtimes fail!, status 0x%02x\n", + pid, threadId, thread_data->send_task_num, opdata->status); + goto err; + } + + if (openssl_check) { + opdata->pri_bytes = msg->out_bytes; + ret = dh_result_check(test_ctx); + if (ret) { + failTimes++; + HPRE_TST_PRT("TD-%d:dh %d result mismatching!\n", + threadId, test_ctx->op); + } + } + + gettimeofday(&end_tval, NULL); + if (is_allow_print(thread_data->send_task_num, DH_ASYNC_GEN, 1)) { + time = (end_tval.tv_sec - start_tval.tv_sec) * 1000000 + + (end_tval.tv_usec - start_tval.tv_usec); + speed = 1 / (time / thread_data->send_task_num) * 1000 * 1000; + HPRE_TST_PRT("Proc-%d, %d-TD dh %dtimes,%f us, %0.3fps, fail %dtimes(all TD)\n", + pid, threadId, thread_data->send_task_num, time, speed, failTimes); + } + +err: + if (is_allow_print(thread_data->send_task_num, DH_ASYNC_GEN, 1)) + HPRE_TST_PRT("thread %d do DH %dth time success!\n", threadId, thread_data->send_task_num); + hpre_dh_del_test_ctx(test_ctx); + if (pSwData) + free(pSwData); +} + + +int dh_init_test_ctx_setup(struct hpre_dh_test_ctx_setup *setup) +{ + if (!setup) + return -1; + + if (!strcmp(g_mode, "-g2")) + setup->generator = DH_GENERATOR_2; + else + setup->generator = DH_GENERATOR_5; + + if (performance_test) + setup->key_from = 1; //0 - Openssl 1 - Designed + else + setup->key_from = 0; //0 - Openssl 1 - Designed + + setup->key_bits = key_bits; + + if (key_bits == 768) { + setup->x = dh_xa_768; + setup->p = dh_p_768; + setup->except_pub_key = dh_except_b_pubkey_768; + setup->cp_pub_key = dh_except_a_pubkey_768; + setup->cp_share_key = dh_share_key_768; + setup->x_size = sizeof(dh_xa_768); + setup->p_size = sizeof(dh_p_768); + setup->except_pub_key_size = sizeof(dh_except_b_pubkey_768); + setup->cp_pub_key_size = sizeof(dh_except_a_pubkey_768); + setup->cp_share_key_size = sizeof(dh_share_key_768); + } else if (key_bits == 1024) { + setup->x = dh_xa_1024; + setup->p = dh_p_1024; + setup->except_pub_key = dh_except_b_pubkey_1024; + setup->cp_pub_key = dh_except_a_pubkey_1024; + setup->cp_share_key = dh_share_key_1024; + setup->x_size = sizeof(dh_xa_1024); + setup->p_size = sizeof(dh_p_1024); + setup->except_pub_key_size = sizeof(dh_except_b_pubkey_1024); + setup->cp_pub_key_size = sizeof(dh_except_a_pubkey_1024); + setup->cp_share_key_size = sizeof(dh_share_key_1024); + } else if (key_bits == 1536) { + setup->x = dh_xa_1536; + setup->p = dh_p_1536; + setup->except_pub_key = dh_except_b_pubkey_1536; + setup->cp_pub_key = dh_except_a_pubkey_1536; + setup->cp_share_key = dh_share_key_1536; + setup->x_size = sizeof(dh_xa_1536); + setup->p_size = sizeof(dh_p_1536); + setup->except_pub_key_size = sizeof(dh_except_b_pubkey_1536); + setup->cp_pub_key_size = sizeof(dh_except_a_pubkey_1536); + setup->cp_share_key_size = sizeof(dh_share_key_1536); + } else if (key_bits == 2048) { + setup->x = dh_xa_2048; + setup->p = dh_p_2048; + setup->except_pub_key = dh_except_b_pubkey_2048; + setup->cp_pub_key = dh_except_a_pubkey_2048; + setup->cp_share_key = dh_share_key_2048; + setup->x_size = sizeof(dh_xa_2048); + setup->p_size = sizeof(dh_p_2048); + setup->except_pub_key_size = sizeof(dh_except_b_pubkey_2048); + setup->cp_pub_key_size = sizeof(dh_except_a_pubkey_2048); + setup->cp_share_key_size = sizeof(dh_share_key_2048); + } else if (key_bits == 3072) { + setup->x = dh_xa_3072; + setup->p = dh_p_3072; + setup->except_pub_key = dh_except_b_pubkey_3072; + setup->cp_pub_key = dh_except_a_pubkey_3072; + setup->cp_share_key = dh_share_key_3072; + setup->x_size = sizeof(dh_xa_3072); + setup->p_size = sizeof(dh_p_3072); + setup->except_pub_key_size = sizeof(dh_except_b_pubkey_3072); + setup->cp_pub_key_size = sizeof(dh_except_a_pubkey_3072); + setup->cp_share_key_size = sizeof(dh_share_key_3072); + } else if (key_bits == 4096) { + setup->x = dh_xa_4096; + setup->p = dh_p_4096; + setup->except_pub_key = dh_except_b_pubkey_4096; + setup->cp_pub_key = dh_except_a_pubkey_4096; + setup->cp_share_key = dh_share_key_4096; + setup->x_size = sizeof(dh_xa_4096); + setup->p_size = sizeof(dh_p_4096); + setup->except_pub_key_size = sizeof(dh_except_b_pubkey_4096); + setup->cp_pub_key_size = sizeof(dh_except_a_pubkey_4096); + setup->cp_share_key_size = sizeof(dh_share_key_4096); + } else { + HPRE_TST_PRT("not find this keybits %d\n", key_bits); + return -1; + } + + if (!strcmp(g_mode, "-g2")) { + setup->g = dh_g_2; + } else { + setup->g = dh_g_5; + } + setup->g_size = 1; + + return 0; +} + +static void *_hpre_dh_sys_test_thread(void *data) +{ + struct test_hpre_pthread_dt *pdata = data; + struct dh_user_tag_info *pTag = NULL; + struct hpre_dh_test_ctx *test_ctx; + struct hpre_dh_test_ctx_setup setup; + struct timeval cur_tval; + enum alg_op_type opType; + float time_used, speed; + int thread_num; + cpu_set_t mask; + int pid = getpid(); + int thread_id = (int)syscall(__NR_gettid); + int ret, cpuid, opstr_idx = 0; + struct wd_queue *q = NULL; + void *pool = NULL; + void *ctx = NULL; + struct wcrypto_dh_ctx_setup dh_setup; + + CPU_ZERO(&mask); + cpuid = pdata->cpu_id; + q = (struct wd_queue *)pdata->q; + pool = pdata->pool; + opType = pdata->op_type; + thread_num = pdata->thread_num; + + if (performance_test && (!t_times && !t_seconds)) { + HPRE_TST_PRT("t_times or t_seconds err\n"); + return NULL; + } + + if (!q || !pool) { + HPRE_TST_PRT("q or pool null!\n"); + return NULL; + } + + CPU_SET(cpuid, &mask); + if (cpuid) { + ret = pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask); + if (ret < 0) { + HPRE_TST_PRT("Proc-%d, thrd-%d:set affinity fail!\n", + pid, thread_id); + return NULL; + } + HPRE_TST_PRT("Proc-%d, thrd-%d bind to cpu-%d!\n", + pid, thread_id, cpuid); + } + + if (!only_soft) { + memset(&dh_setup, 0, sizeof(dh_setup)); + dh_setup.key_bits = key_bits; + if (performance_test) + dh_setup.cb = _dh_perf_cb; + else + dh_setup.cb = _dh_cb; + dh_setup.br.alloc = (void *)wd_alloc_blk; + dh_setup.br.free = (void *)wd_free_blk; + dh_setup.br.iova_map = (void *)wd_blk_iova_map; + dh_setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + dh_setup.br.usr = pool; + if (!strcmp(g_mode, "-g2")) + dh_setup.is_g2 = true; + else + dh_setup.is_g2 = false; + + ctx = wcrypto_create_dh_ctx(q, &dh_setup); + if (!ctx) { + HPRE_TST_PRT("wcrypto_create_dh_ctx failed\n"); + return NULL; + } + } + + if (dh_init_test_ctx_setup(&setup)) { + wcrypto_del_dh_ctx(ctx); + return NULL; + } + + setup.pool = pool; + setup.q = q; + setup.ctx = ctx; + + if (opType == DH_ASYNC_GEN || opType == DH_GEN) + setup.op_type = (only_soft) ? SW_GENERATE_KEY: HW_GENERATE_KEY; + else + setup.op_type = (only_soft) ? SW_COMPUTE_KEY: HW_COMPUTE_KEY; + +new_test_again: + test_ctx = hpre_dh_create_test_ctx(setup); + if (!test_ctx) { + HPRE_TST_PRT("hpre_dh_create_test_ctx failed\n"); + return NULL; + } + + do { + if (opType == DH_ASYNC_GEN || + opType == DH_ASYNC_COMPUTE) { + + pTag = malloc(sizeof(struct dh_user_tag_info)); + if (!pTag) { + HPRE_TST_PRT("malloc pTag fail!\n"); + goto fail_release; + } + + pTag->test_ctx = test_ctx; + pTag->thread_data = pdata; + pTag->pid = pid; + pTag->thread_id = thread_id; + } + + if (opType == DH_ASYNC_GEN || opType == DH_GEN) { + if (dh_generate_key(test_ctx, pTag)) { + goto fail_release; + } + opstr_idx = 0; + } else { + if (dh_compute_key(test_ctx, pTag)) { + goto fail_release; + } + opstr_idx = 1; + } + + pdata->send_task_num++; + if (opType == DH_GEN ||opType == DH_COMPUTE) { + if (!performance_test && !only_soft) { + if (dh_result_check(test_ctx)) + goto fail_release; + + if (is_allow_print(pdata->send_task_num, opType, thread_num)) { + HPRE_TST_PRT("Proc-%d, %d-TD dh %s succ!\n", + getpid(), (int)syscall(__NR_gettid), dh_op_str[opstr_idx]); + } + + hpre_dh_del_test_ctx(test_ctx); + if (thread_num > 1 && pdata->send_task_num == t_times) { + HPRE_TST_PRT("opType:%d run %d times or %d seconds will return!\n", opType, t_times, t_seconds); + return NULL; + } + goto new_test_again; + } + } else { + if (is_exit(pdata)) + break; + goto new_test_again; + } + + }while(!is_exit(pdata)); + + if (!performance_test) { + HPRE_TST_PRT("opType:%d run %d times or %d seconds, success!\n", opType, t_times, t_seconds); + return NULL; + } + + if (opType == DH_GEN || opType == DH_COMPUTE) + pdata->recv_task_num = pdata->send_task_num; + + if (performance_test) { + gettimeofday(&cur_tval, NULL); + time_used = (float)((cur_tval.tv_sec -pdata->start_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - pdata->start_tval.tv_usec); + + if (t_seconds){ + speed = pdata->send_task_num / time_used * 1000000; + HPRE_TST_PRT("Proc-%d, %d-TD: dh do %s send %u task, recv %u task, run %0.1f s at %0.3f ops\n", + pid, thread_id, dh_op_str[opstr_idx], + pdata->send_task_num, pdata->recv_task_num, + time_used / 1000000, speed); + } else if (t_times) { + speed = 1 / (time_used / t_times) * 1000; + HPRE_TST_PRT("\r\nPID(%d)-thread-%d:%s g2 mode %dbits kgen %s time %0.0f us, pkt len =" + " %d bytes, %0.3f Kops\n", getpid(), (int)syscall(__NR_gettid), "dh", + key_bits, dh_op_str[opstr_idx],time_used, key_bits / 8, speed); + } + } + + /* wait for recv finish */ + while (pdata->send_task_num != pdata->recv_task_num) + usleep(1000); + +fail_release: + if (opType == DH_ASYNC_GEN || + opType == DH_ASYNC_COMPUTE) { + return NULL; + } + if (test_ctx->op == HW_COMPUTE_KEY || test_ctx->op == HW_GENERATE_KEY) + wcrypto_del_dh_ctx(test_ctx->priv); + + if (opType == DH_GEN || opType == DH_COMPUTE) + hpre_dh_del_test_ctx(test_ctx); + + return NULL; +} + +static inline int _get_cpu_id(int thr, __u64 core_mask) +{ + __u64 i; + int cnt = 0; + + + for (i = 1; i < 64; i++) { + if (core_mask & (0x1ull << i)) { + if (thr == cnt) + return i; + cnt++; + } + } + + return 0; +} + +static inline int _get_one_bits(__u64 val) +{ + int count = 0; + + while (val) { + if (val % 2 == 1) + count++; + val = val / 2; + } + + return count; +} + +int hpre_test_get_file_size(char *in_file) +{ + int fd = -1, ret; + struct stat file_info; + + if (!in_file) { + HPRE_TST_PRT("para err while try to %s!\n", __func__); + return -EINVAL; + } + fd = open(in_file, O_RDONLY, S_IRUSR) ; + if (fd < 0) { + HPRE_TST_PRT("Get %s file fail!\n", in_file); + return fd; + } + ret = fstat(fd, &file_info); + if (ret < 0) { + close(fd); + HPRE_TST_PRT("fstat file %s fail!\n", in_file); + return -ret; + } + close(fd); + return (int)file_info.st_size; +} + +int hpre_test_read_from_file(__u8 *out, char *in_file, int size) +{ + int fd = -1, bytes_rd; + + if (!out || !size || !in_file) { + HPRE_TST_PRT("para err while try to write file!\n"); + return -EINVAL; + } + + fd = open(in_file, O_RDONLY, S_IRUSR) ; + if (fd < 0) { + HPRE_TST_PRT("Get %s file fail!\n", in_file); + return fd; + } + + bytes_rd = read(fd, out, size); + if (bytes_rd < 0) { + close(fd); + HPRE_TST_PRT("write data to %s file fail!\n", in_file); + return -ENOMEM; + } + close(fd); + + /* to be fixed */ + return bytes_rd; +} + +int hpre_test_write_to_file(__u8 *out, int size, char *out_file, + int handle, int try_close) +{ + int fd = -1, bytes_write; + + if (!out || !size || !out_file) { + HPRE_TST_PRT("para err while try to write file!\n"); + return -EINVAL; + } + + if (handle < 0) { + fd = open(out_file, O_WRONLY | O_CREAT, + S_IRUSR | S_IWUSR); + if (fd < 0) { + HPRE_TST_PRT("create %s file fail!\n", out_file); + return fd; + } + } else + fd = handle; + + bytes_write = write(fd, out, size); + if (bytes_write < 0 || bytes_write < size) { + if (try_close) + close(fd); + HPRE_TST_PRT("write data to %s file fail!\n", out_file); + return -ENOMEM; + } + if (try_close) + close(fd); + + /* to be fixed */ + return fd; +} + +static int test_rsa_key_gen(void *ctx, char *pubkey_file, + char *privkey_file, + char *crt_privkey_file, int is_file) +{ + int ret, bits; + RSA *test_rsa; + BIGNUM *p, *q, *e_value, *n, *e, *d, *dmp1, *dmq1, *iqmp; + //struct wd_dtb *wd_e, *wd_d, *wd_n, *wd_dq, *wd_dp, *wd_qinv, *wd_q, *wd_p; + struct wd_dtb wd_e, wd_d, wd_n, wd_dq, wd_dp, wd_qinv, wd_q, wd_p; + //struct wcrypto_rsa_pubkey *pubkey; + //struct wcrypto_rsa_prikey *prikey; + u32 key_size = key_bits >> 3; + + memset(&wd_e, 0, sizeof(wd_e)); + memset(&wd_d, 0, sizeof(wd_d)); + memset(&wd_n, 0, sizeof(wd_n)); + memset(&wd_dq, 0, sizeof(wd_dq)); + memset(&wd_dp, 0, sizeof(wd_dp)); + memset(&wd_qinv, 0, sizeof(wd_qinv)); + memset(&wd_q, 0, sizeof(wd_q)); + memset(&wd_p, 0, sizeof(wd_p)); + + bits = wcrypto_rsa_key_bits(ctx); + test_rsa = RSA_new(); + if (!test_rsa || !bits) { + HPRE_TST_PRT("RSA new fail!\n"); + return -ENOMEM; + } + e_value = BN_new(); + if (!e_value) { + RSA_free(test_rsa); + HPRE_TST_PRT("BN new e fail!\n"); + ret = -ENOMEM; + return ret; + } + ret = BN_set_word(e_value, 65537); + if (ret != 1) { + HPRE_TST_PRT("BN_set_word fail!\n"); + ret = -1; + goto gen_fail; + } + + ret = RSA_generate_key_ex(test_rsa, key_bits, e_value, NULL); + if (ret != 1) { + HPRE_TST_PRT("RSA_generate_key_ex fail!\n"); + ret = -1; + goto gen_fail; + } + RSA_get0_key((const RSA *)test_rsa, (const BIGNUM **)&n, + (const BIGNUM **)&e, (const BIGNUM **)&d); + RSA_get0_factors((const RSA *)test_rsa, (const BIGNUM **)&p, + (const BIGNUM **)&q); + RSA_get0_crt_params((const RSA *)test_rsa, (const BIGNUM **)&dmp1, + (const BIGNUM **)&dmq1, (const BIGNUM **)&iqmp); + + //wcrypto_get_rsa_pubkey(ctx, &pubkey); + //wcrypto_get_rsa_pubkey_params(pubkey, &wd_e, &wd_n); + wd_e.bsize = key_size; + wd_e.data = malloc(GEN_PARAMS_SZ(key_size)); + wd_n.bsize = wd_e.bsize; + wd_n.data = wd_e.data + wd_e.bsize; + + wd_e.dsize = BN_bn2bin(e, (unsigned char *)wd_e.data); + if (wd_e.dsize > wd_e.bsize) { + HPRE_TST_PRT("e bn to bin overflow!\n"); + goto gen_fail; + } + wd_n.dsize = BN_bn2bin(n, (unsigned char *)wd_n.data); + if (wd_n.dsize > wd_n.bsize) { + HPRE_TST_PRT("n bn to bin overflow!\n"); + goto gen_fail; + } + + if (wcrypto_set_rsa_pubkey_params(ctx, &wd_e, &wd_n)) + { + HPRE_TST_PRT("set rsa pubkey failed %d!\n", ret); + goto gen_fail; + } + + if (pubkey_file && is_file) { + ret = hpre_test_write_to_file((unsigned char *)wd_e.data, key_bits >> 2, + pubkey_file, -1, 1); + if (ret < 0) + goto gen_fail; + HPRE_TST_PRT("RSA public key was written to %s!\n", + privkey_file); + } + + if (rsa_key_in) { + memset(rsa_key_in->e, 0, key_size); + memset(rsa_key_in->p, 0, key_size >> 1); + memset(rsa_key_in->q, 0, key_size >> 1); + rsa_key_in->e_size = BN_bn2bin(e, (unsigned char *)rsa_key_in->e); + rsa_key_in->p_size = BN_bn2bin(p, (unsigned char *)rsa_key_in->p); + rsa_key_in->q_size = BN_bn2bin(q, (unsigned char *)rsa_key_in->q); + } + + //wcrypto_get_rsa_prikey(ctx, &prikey); + if (wcrypto_rsa_is_crt(ctx)) { + //wcrypto_get_rsa_crt_prikey_params(prikey, &wd_dq, &wd_dp, &wd_qinv, &wd_q, &wd_p); + wd_dq.bsize = CRT_PARAM_SZ(key_size); + wd_dq.data = malloc(CRT_PARAMS_SZ(key_size)); + wd_dp.bsize = CRT_PARAM_SZ(key_size); + wd_dp.data = wd_dq.data + wd_dq.bsize; + wd_q.bsize = CRT_PARAM_SZ(key_size); + wd_q.data = wd_dp.data + wd_dp.bsize; + wd_p.bsize = CRT_PARAM_SZ(key_size); + wd_p.data = wd_q.data + wd_q.bsize; + wd_qinv.bsize = CRT_PARAM_SZ(key_size); + wd_qinv.data = wd_p.data + wd_p.bsize; + + /* CRT mode private key */ + wd_dq.dsize = BN_bn2bin(dmq1, (unsigned char *)wd_dq.data); + if (wd_dq.dsize > wd_dq.bsize) { + HPRE_TST_PRT("dq bn to bin overflow!\n"); + goto gen_fail; + } + + wd_dp.dsize = BN_bn2bin(dmp1, (unsigned char *)wd_dp.data); + if (wd_dp.dsize > wd_dp.bsize) { + HPRE_TST_PRT("dp bn to bin overflow!\n"); + goto gen_fail; + } + + wd_q.dsize = BN_bn2bin(q, (unsigned char *)wd_q.data); + if (wd_q.dsize > wd_q.bsize) { + HPRE_TST_PRT("q bn to bin overflow!\n"); + goto gen_fail; + } + + wd_p.dsize = BN_bn2bin(p, (unsigned char *)wd_p.data); + if (wd_p.dsize > wd_p.bsize) { + HPRE_TST_PRT("p bn to bin overflow!\n"); + goto gen_fail; + } + + wd_qinv.dsize = BN_bn2bin(iqmp, (unsigned char *)wd_qinv.data); + if (wd_qinv.dsize > wd_qinv.bsize) { + HPRE_TST_PRT("qinv bn to bin overflow!\n"); + goto gen_fail; + } + + if (wcrypto_set_rsa_crt_prikey_params(ctx, &wd_dq, + &wd_dp, &wd_qinv, + &wd_q, &wd_p)) + { + HPRE_TST_PRT("set rsa crt prikey failed %d!\n", ret); + goto gen_fail; + } + + if (crt_privkey_file && is_file) { + ret = hpre_test_write_to_file((unsigned char *)wd_dq.data, + (key_bits >> 4) * 5, crt_privkey_file, -1, 0); + if (ret < 0) + goto gen_fail; + ret = hpre_test_write_to_file((unsigned char *)wd_e.data, + (key_bits >> 2), crt_privkey_file, ret, 1); + if (ret < 0) + goto gen_fail; + HPRE_TST_PRT("RSA CRT private key was written to %s!\n", + crt_privkey_file); + } else if (crt_privkey_file && !is_file) { + memcpy(crt_privkey_file, wd_dq.data, (key_bits >> 4) * 5); + memcpy(crt_privkey_file + (key_bits >> 4) * 5, + wd_e.data, (key_bits >> 2)); + } + + } else { + //wcrypto_get_rsa_prikey_params(prikey, &wd_d, &wd_n); + wd_d.bsize = key_size; + wd_d.data = malloc(GEN_PARAMS_SZ(key_size)); + wd_n.bsize =key_size; + wd_n.data = wd_d.data + wd_d.bsize; + + /* common mode private key */ + wd_d.dsize = BN_bn2bin(d, (unsigned char *)wd_d.data); + wd_n.dsize = BN_bn2bin(n, (unsigned char *)wd_n.data); + + if (wcrypto_set_rsa_prikey_params(ctx, &wd_d, &wd_n)) + { + HPRE_TST_PRT("set rsa prikey failed %d!\n", ret); + goto gen_fail; + } + + if (privkey_file && is_file) { + ret = hpre_test_write_to_file((unsigned char *)wd_d.data, + (key_size), + privkey_file, -1, 0); + if (ret < 0) + goto gen_fail; + ret = hpre_test_write_to_file((unsigned char *)wd_n.data, + (key_size), + privkey_file, ret, 1); + if (ret < 0) + goto gen_fail; + + ret = hpre_test_write_to_file((unsigned char *)wd_e.data, + (key_size), privkey_file, ret, 1); + if (ret < 0) + goto gen_fail; + HPRE_TST_PRT("RSA common private key was written to %s!\n", + privkey_file); + } else if (privkey_file && !is_file) { + memcpy(privkey_file, wd_d.data, key_size); + memcpy(privkey_file + key_size, wd_n.data, key_size); + memcpy(privkey_file + 2 * key_size, wd_e.data, key_size); + } + } + + RSA_free(test_rsa); + BN_free(e_value); + + if (wd_e.data) + free(wd_e.data); + + if (wcrypto_rsa_is_crt(ctx)) { + if (wd_dq.data) + free(wd_dq.data); + } else { + if (wd_d.data) + free(wd_d.data); + } + + return 0; +gen_fail: + RSA_free(test_rsa); + BN_free(e_value); + + if (wd_e.data) + free(wd_e.data); + + if (wcrypto_rsa_is_crt(ctx)) { + if (wd_dq.data) + free(wd_dq.data); + } else { + if (wd_d.data) + free(wd_d.data); + } + + return ret; +} + +int hpre_test_fill_keygen_opdata(void *ctx, struct wcrypto_rsa_op_data *opdata) +{ + struct wd_dtb *e, *p, *q; + struct wcrypto_rsa_pubkey *pubkey; + struct wcrypto_rsa_prikey *prikey; + struct wd_dtb t_e, t_p, t_q; + + wcrypto_get_rsa_pubkey(ctx, &pubkey); + wcrypto_get_rsa_pubkey_params(pubkey, &e, NULL); + wcrypto_get_rsa_prikey(ctx, &prikey); + + if (wcrypto_rsa_is_crt(ctx)) { + wcrypto_get_rsa_crt_prikey_params(prikey, NULL , NULL, NULL, &q, &p); + } else { + e = &t_e; + p = &t_p; + q = &t_q; + e->data = rsa_key_in->e; + e->dsize = rsa_key_in->e_size; + p->data = rsa_key_in->p; + p->dsize = rsa_key_in->p_size; + q->data = rsa_key_in->q; + q->dsize = rsa_key_in->q_size; + } + + opdata->in = wcrypto_new_kg_in(ctx, e, p, q); + if (!opdata->in) { + HPRE_TST_PRT("create rsa kgen in fail!\n"); + return -ENOMEM; + } + opdata->out = wcrypto_new_kg_out(ctx); + if (!opdata->out) { + HPRE_TST_PRT("create rsa kgen out fail!\n"); + return -ENOMEM; + } + return 0; +} + +static int hpre_test_get_bin_size(__u8 *bin, int csize) +{ + int i = csize - 1; + int cut = 0; + + while (!(*(__u8 *)(bin + i)) && i >= 0) { + i--; + cut++; + } + + return csize - cut; +} + +static BIGNUM *hpre_bin_to_bn(void *bin, int raw_size) +{ + int bin_size; + + if (!bin || !raw_size) + return NULL; + bin_size = hpre_test_get_bin_size((__u8 *)bin, raw_size); + return BN_bin2bn((const unsigned char *)bin, bin_size, NULL); +} + +int hpre_test_result_check(void *ctx, struct wcrypto_rsa_op_data *opdata, void *key) +{ + struct wcrypto_rsa_kg_out *out = (void *)opdata->out; + struct wcrypto_rsa_prikey *prikey; + int ret, keybits, key_size; + void *ssl_out; + BIGNUM *nn; + BIGNUM *e; + + if (!hpre_test_rsa) { + hpre_test_rsa = RSA_new(); + if (!hpre_test_rsa) { + HPRE_TST_PRT("%s:RSA new fail!\n", __func__); + return -ENOMEM; + } + } + wcrypto_get_rsa_prikey(ctx, &prikey); + keybits = wcrypto_rsa_key_bits(ctx); + key_size = keybits >> 3; + if (opdata->op_type == WCRYPTO_RSA_GENKEY) { + if (wcrypto_rsa_is_crt(ctx)) { + struct wd_dtb qinv, dq, dp; + struct wd_dtb *s_qinv, *s_dq, *s_dp; + + wcrypto_get_rsa_crt_prikey_params(prikey, &s_dq, &s_dp, + &s_qinv, NULL, NULL); + wcrypto_get_rsa_kg_out_crt_params(out, &qinv, &dq, &dp); + + if (memcmp(s_qinv->data, qinv.data, s_qinv->dsize)) { + HPRE_TST_PRT("keygen qinv mismatch!\n"); + return -EINVAL; + } + if (memcmp(s_dq->data, dq.data, s_dq->dsize)) { + HPRE_TST_PRT("keygen dq mismatch!\n"); + return -EINVAL; + } + if (memcmp(s_dp->data, dp.data, s_dp->dsize)) { + HPRE_TST_PRT("keygen dp mismatch!\n"); + return -EINVAL; + } + } else { + struct wd_dtb d, n; + struct wd_dtb *s_d, *s_n; + + wcrypto_get_rsa_kg_out_params(out, &d, &n); + + wcrypto_get_rsa_prikey_params(prikey, &s_d, &s_n); + + /* check D */ + if (memcmp(s_n->data, n.data, s_n->dsize)) { + HPRE_TST_PRT("key generate N result mismatching!\n"); + return -EINVAL; + } + if (memcmp(s_d->data, d.data, s_d->dsize)) { + HPRE_TST_PRT("key generate D result mismatching!\n"); + return -EINVAL; + } + } + } else if (opdata->op_type == WCRYPTO_RSA_VERIFY) { + ssl_out = malloc(key_size); + if (!ssl_out) { + HPRE_TST_PRT("malloc ssl out fail!\n"); + return -ENOMEM; + } + if (key) { + nn = hpre_bin_to_bn(key + key_size, + key_size); + if (!nn) { + HPRE_TST_PRT("n bin2bn err!\n"); + return -EINVAL; + } + e = hpre_bin_to_bn(key, key_size); + if (!e) { + HPRE_TST_PRT("e bin2bn err!\n"); + return -EINVAL; + } + ret = RSA_set0_key(hpre_test_rsa, nn, e, NULL); + if (ret <= 0) { + HPRE_TST_PRT("e set0_key err!\n"); + return -EINVAL; + } + } + ret = RSA_public_encrypt(opdata->in_bytes, opdata->in, ssl_out, + hpre_test_rsa, RSA_NO_PADDING); + if (ret != (int)opdata->in_bytes) { + HPRE_TST_PRT("openssl pub encrypto fail!ret=%d\n", ret); + return -ENOMEM; + } + if (!only_soft && memcmp(ssl_out, opdata->out, key_size)) { + HPRE_TST_PRT("pub encrypto result mismatch!\n"); + return -EINVAL; + } + free(ssl_out); + } else { + + ssl_out = malloc(key_size); + if (!ssl_out) { + HPRE_TST_PRT("malloc ssl out fail!\n"); + return -ENOMEM; + } + + if (key && wcrypto_rsa_is_crt(ctx)) { + BIGNUM *dp, *dq, *iqmp, *p, *q; + int size = key_size / 2; + + dq = hpre_bin_to_bn(key, size); + if (!dq) { + HPRE_TST_PRT("dq bin2bn err!\n"); + return -EINVAL; + } + dp = hpre_bin_to_bn(key + size, size); + if (!dp) { + HPRE_TST_PRT("dp bin2bn err!\n"); + return -EINVAL; + } + q = hpre_bin_to_bn(key + 2 * size, size); + if (!q) { + HPRE_TST_PRT("q bin2bn err!\n"); + return -EINVAL; + } + p = hpre_bin_to_bn(key + 3 * size, size); + if (!p) { + HPRE_TST_PRT("p bin2bn err!\n"); + return -EINVAL; + } + iqmp = hpre_bin_to_bn(key + 4 * size, size); + if (!iqmp) { + HPRE_TST_PRT("iqmp bin2bn err!\n"); + return -EINVAL; + } + ret = RSA_set0_crt_params(hpre_test_rsa, dp, dq, iqmp); + if (ret <= 0) { + HPRE_TST_PRT("set0_crt_params err!\n"); + return -EINVAL; + } + ret = RSA_set0_factors(hpre_test_rsa, p, q); + if (ret <= 0) { + HPRE_TST_PRT("set0_factors err!\n"); + return -EINVAL; + } + nn = hpre_bin_to_bn(key + 7 * size, key_size); + if (!nn) { + HPRE_TST_PRT("n bin2bn err!\n"); + return -EINVAL; + } + e = hpre_bin_to_bn(key + 5 * size, key_size); + if (!e) { + HPRE_TST_PRT("e bin2bn err!\n"); + return -EINVAL; + } + ret = RSA_set0_key(hpre_test_rsa, nn, e, NULL); + if (ret <= 0) { + HPRE_TST_PRT("rsa set0_key crt err!\n"); + return -EINVAL; + } + + } else if (key && !wcrypto_rsa_is_crt(ctx)) { + BIGNUM *d; + + nn = hpre_bin_to_bn(key + key_size, key_size); + if (!nn) { + HPRE_TST_PRT("n bin2bn err!\n"); + return -EINVAL; + } + d = hpre_bin_to_bn(key, key_size); + if (!d) { + HPRE_TST_PRT("d bin2bn err!\n"); + return -EINVAL; + } + e = hpre_bin_to_bn(key + 2 * key_size, key_size); + if (!e) { + HPRE_TST_PRT("e bin2bn err!\n"); + return -EINVAL; + } + ret = RSA_set0_key(hpre_test_rsa, nn, e, d); + if (ret <= 0) { + HPRE_TST_PRT("d set0_key err!\n"); + return -EINVAL; + } + } + + ret = RSA_private_decrypt(opdata->in_bytes, opdata->in, ssl_out, + hpre_test_rsa, RSA_NO_PADDING); + if (ret != (int)opdata->in_bytes) { + HPRE_TST_PRT("openssl priv decrypto fail!ret=%d\n", ret); + return -ENOMEM; + } +#ifdef DEBUG + print_data(opdata->out, 16, "out"); + print_data(opdata->in, 16, "in"); + print_data(ssl_out, 16, "ssl_out"); +#endif + + if (!only_soft && memcmp(ssl_out, opdata->out, ret)) { + HPRE_TST_PRT("prv decrypto result mismatch!\n"); + return -EINVAL; + } + free(ssl_out); + + } + + return 0; +} + +int hpre_dh_test(void *c, struct hpre_queue_mempool *pool) +{ + DH *a = NULL, *b = NULL; + int ret, generator = DH_GENERATOR_5; + struct wcrypto_dh_op_data opdata_a; + struct wcrypto_dh_op_data opdata_b; + const BIGNUM *ap = NULL, *ag = NULL, + *apub_key = NULL, *apriv_key = NULL; + const BIGNUM *bp = NULL, *bg = NULL, + *bpub_key = NULL, *bpriv_key = NULL; + unsigned char *ap_bin = NULL, *ag_bin = NULL, + *apub_key_bin = NULL, *apriv_key_bin = NULL; + unsigned char *bp_bin = NULL, *bg_bin = NULL, + *bpub_key_bin = NULL, *bpriv_key_bin = NULL; + unsigned char *abuf = NULL; + struct wd_dtb g; + + __u32 gbytes; + void *tag = NULL; + int key_size, key_bits, bin_size = 0; + + if (!pool) { + HPRE_TST_PRT("pool null!\n"); + return -1; + } + + a = DH_new(); + b = DH_new(); + if (!a || !b) { + HPRE_TST_PRT("New DH fail!\n"); + return -1; + } + if (wcrypto_dh_is_g2(c)) + generator = DH_GENERATOR_2; + + key_bits = wcrypto_dh_key_bits(c); + key_size = key_bits >> 3; + + /* Alice generates DH parameters */ + ret = DH_generate_parameters_ex(a, key_bits, generator, NULL); + if (!ret) { + HPRE_TST_PRT("DH_generate_parameters_ex fail!\n"); + goto dh_err; + } + DH_get0_pqg(a, &ap, NULL, &ag); + bp = BN_dup(ap); + bg = BN_dup(ag); + if (!bp || !bg) { + HPRE_TST_PRT("bn dump fail!\n"); + ret = -1; + goto dh_err; + } + + /* Set the same parameters on Bob as Alice :) */ + DH_set0_pqg(b, (BIGNUM *)bp, NULL, (BIGNUM *)bg); + if (!DH_generate_key(a)) { + HPRE_TST_PRT("a DH_generate_key fail!\n"); + ret = -1; + goto dh_err; + } + DH_get0_key(a, &apub_key, &apriv_key); + ag_bin = wd_alloc_blk(pool); + if (!ag_bin) { + HPRE_TST_PRT("pool alloc ag_bin fail!\n"); + goto dh_err; + } + memset(ag_bin, 0, key_size * 2); + apriv_key_bin = wd_alloc_blk(pool); + if (!apriv_key_bin) { + HPRE_TST_PRT("pool alloc apriv_key_bin fail!\n"); + goto dh_err; + } + memset(apriv_key_bin, 0, key_size * 2); + + /* The hpre_UM tells us key_addr contains xa and p, + * their addr should be together + */ + ap_bin= apriv_key_bin + key_size; + + gbytes = BN_bn2bin(ag, ag_bin); + g.data = (char*)ag_bin; + g.bsize = key_size; + g.dsize = gbytes; + opdata_a.pbytes = BN_bn2bin(ap, ap_bin); + opdata_a.xbytes = BN_bn2bin(apriv_key, apriv_key_bin); + ret = wcrypto_set_dh_g(c, &g); + if (ret) { + HPRE_TST_PRT("Alice wcrypto_set_dh_g fail!\n"); + goto dh_err; + } + opdata_a.x_p = apriv_key_bin; + opdata_a.pri = wd_alloc_blk(pool); + if (!opdata_a.pri) { + HPRE_TST_PRT("pool alloc opdata_a.pri fail!\n"); + goto dh_err; + } + memset(opdata_a.pri, 0, key_size * 2); + + opdata_a.op_type = WCRYPTO_DH_PHASE1; + + /* Alice computes public key */ + ret = wcrypto_do_dh(c, &opdata_a, tag); + if (ret) { + HPRE_TST_PRT("a wcrypto_do_dh fail!\n"); + goto dh_err; + } + + if (openssl_check) { + apub_key_bin = malloc(key_size); + if (!apub_key_bin) { + HPRE_TST_PRT("malloc apub_key_bin fail!\n"); + ret = -ENOMEM; + goto dh_err; + } + ret = BN_bn2bin(apub_key, apub_key_bin); + if (!ret) { + HPRE_TST_PRT("apub_key bn 2 bin fail!\n"); + ret = -1; + goto dh_err; + } + bin_size = ret; + + if (memcmp(apub_key_bin, opdata_a.pri, bin_size)) { + HPRE_TST_PRT("Alice HPRE DH key gen pub mismatch, dsize %d!\n", bin_size); + ret = -EINVAL; +#ifdef DEBUG + print_data(apub_key_bin, key_size, "SOFT"); + print_data(opdata_a.pri, key_size, "HARDWATE"); +#endif + goto dh_err; + } + } + if (!DH_generate_key(b)) { + HPRE_TST_PRT("b DH_generate_key fail!\n"); + ret = -1; + goto dh_err; + } + DH_get0_key(b, &bpub_key, &bpriv_key); + bg_bin = wd_alloc_blk(pool); + if (!bg_bin) { + HPRE_TST_PRT("pool alloc bg_bin fail!\n"); + ret = -1; + goto dh_err; + } + memset(bg_bin, 0, key_size * 2); + + bpriv_key_bin= wd_alloc_blk(pool); + if (!bpriv_key_bin) { + HPRE_TST_PRT("pool alloc bpriv_key_bin fail!\n"); + ret = -1; + goto dh_err; + } + memset(bpriv_key_bin, 0, key_size * 2); + bp_bin = bpriv_key_bin + key_size; + gbytes = BN_bn2bin(bg, bg_bin); + g.data = (char*)bg_bin; + g.bsize = gbytes; + g.dsize = key_size; + ret = wcrypto_set_dh_g(c, &g); + if (ret) { + HPRE_TST_PRT("bob wcrypto_set_dh_g fail!\n"); + goto dh_err; + } + opdata_b.pbytes = BN_bn2bin(bp, bp_bin); + opdata_b.xbytes = BN_bn2bin(bpriv_key, bpriv_key_bin); + opdata_b.x_p = bpriv_key_bin; + opdata_b.pri = wd_alloc_blk(pool); + if (!opdata_b.pri) { + HPRE_TST_PRT("pool alloc opdata_b.pri fail!\n"); + ret = -1; + goto dh_err; + } + memset(opdata_b.pri, 0, key_size * 2); + opdata_b.op_type = WCRYPTO_DH_PHASE1; + + /* Bob computes public key */ + ret = wcrypto_do_dh(c, &opdata_b, tag); + if (ret) { + HPRE_TST_PRT("b wcrypto_do_dh fail!\n"); + goto dh_err; + } + if (openssl_check) { + bpub_key_bin = malloc(key_size); + if (!bpub_key_bin) { + HPRE_TST_PRT("malloc bpub_key_bin fail!\n"); + ret = -1; + goto dh_err; + } + ret = BN_bn2bin(bpub_key, bpub_key_bin); + if (!ret) { + HPRE_TST_PRT("bpub_key bn 2 bin fail!\n"); + goto dh_err; + } + bin_size = ret; + + if (memcmp(bpub_key_bin, opdata_b.pri, bin_size)) { + HPRE_TST_PRT("Bob HPRE DH key gen pub mismatch, dsize %d!\n", bin_size); + ret = -EINVAL; +#ifdef DEBUG + print_data(bpub_key_bin, key_size, "SOFT"); + print_data(opdata_b.pri, key_size, "HARDWATE"); +#endif + goto dh_err; + } + } + /* Alice computes private key with OpenSSL */ + abuf = malloc(key_size); + if (!abuf) { + HPRE_TST_PRT("malloc abuf fail!\n"); + ret = -ENOMEM; + goto dh_err; + } + + memset(abuf, 0, key_size); + if (openssl_check) { + ret = DH_compute_key(abuf, bpub_key, a); + if (!ret) { + HPRE_TST_PRT("DH_compute_key fail!\n"); + ret = -1; + goto dh_err; + } + bin_size = ret; + } + + /* Alice computes private key with HW accelerator */ + memset(ag_bin, 0, key_size * 2); + memset(apriv_key_bin, 0, key_size * 2); + ap_bin = apriv_key_bin + key_size; + memset(opdata_a.pri, 0, key_size * 2); + + opdata_a.pvbytes = BN_bn2bin(bpub_key, ag_bin); + opdata_a.pv = ag_bin;/* bob's public key here */ + opdata_a.pbytes = BN_bn2bin(ap, ap_bin); + opdata_a.xbytes = BN_bn2bin(apriv_key, apriv_key_bin); + opdata_a.x_p = apriv_key_bin; + opdata_a.pri = wd_alloc_blk(pool); + if (!opdata_a.pri) { + HPRE_TST_PRT("pool alloc opdata_a.pri fail!\n"); + ret = -1; + goto dh_err; + } + memset(opdata_a.pri, 0, key_size * 2); + opdata_a.op_type = WCRYPTO_DH_PHASE2; + + /* Alice computes private key with HPRE */ + ret = wcrypto_do_dh(c, &opdata_a, tag); + if (ret) { + HPRE_TST_PRT("a wcrypto_do_dh fail!\n"); + goto dh_err; + } + if (openssl_check) { + if (memcmp(abuf, opdata_a.pri, bin_size)) { + HPRE_TST_PRT("Alice HPRE DH gen privkey mismatch!\n"); + ret = -EINVAL; +#ifdef DEBUG + print_data(abuf, key_size, "SOFT"); + print_data(opdata_a.pri, key_size, "HARDWATE"); +#endif + goto dh_err; + } + } + + ret = 0; + HPRE_TST_PRT("HPRE DH generate key sucessfully!\n"); + dh_err: + DH_free(a); + DH_free(b); + if (ag_bin) + wd_free_blk(pool, ag_bin); + if (apriv_key_bin) + wd_free_blk(pool, apriv_key_bin); + if (opdata_a.pri) + wd_free_blk(pool, opdata_a.pri); + + if (bg_bin) + wd_free_blk(pool, bg_bin); + if (bpriv_key_bin) + wd_free_blk(pool, bpriv_key_bin); + if (opdata_b.pri) + wd_free_blk(pool, opdata_b.pri); + + if (apub_key_bin) + free(apub_key_bin); + if (bpub_key_bin) + free(bpub_key_bin); + if (abuf) + free(abuf); + return ret; +} + +#ifdef RSA_OP_DEBUG +int hpre_test_rsa_op(enum alg_op_type op_type, void *c, __u8 *in, + int in_size, __u8 *out, __u8 *key) +{ + struct wcrypto_rsa_op_data opdata; + int ret, move; + void *tag; + int key_bits, key_size; + + key_bits = wcrypto_dh_key_bits(c); + key_size = key_bits >> 3; + if (op_type == RSA_KEY_GEN) { + /* use openSSL generate key and store them to files at first */ + ret = test_rsa_key_gen(c, (char *)in, + (char *)out, (char *)key, 1); + if (ret < 0) + return ret; + } else { + struct wcrypto_rsa_pubkey pubkey; + struct wcrypto_rsa_prikey prvkey; + + if (!key) + goto try_format_input; + memset(&pubkey, 0, sizeof(pubkey)); + memset(&prvkey, 0, sizeof(prvkey)); + if (op_type == RSA_PUB_EN) { + pubkey.e = key; + pubkey.n = key + (key_bits >> 3); + ret = wd_set_rsa_pubkey(c, &pubkey); + if (ret) { + HPRE_TST_PRT("wd_set_rsa_pubkey fail!\n"); + return ret; + } + } + if (op_type == RSA_PRV_DE && wcrypto_rsa_is_crt(c)) { + prvkey.pkey2.dq = key; + prvkey.pkey2.dp = key + (key_bits >> 4); + prvkey.pkey2.q = key + (key_bits >> 3); + prvkey.pkey2.p = key + (key_bits >> 4) * 3; + prvkey.pkey2.qinv = key + (key_bits >> 2); + ret = wd_set_rsa_prikey(c, &prvkey); + if (ret) { + HPRE_TST_PRT("wd_set_rsa_prikey crt fail!\n"); + return ret; + } + } else if (op_type == RSA_PRV_DE && !wcrypto_rsa_is_crt(c)) { + prvkey.pkey1.d = key; + prvkey.pkey1.n = key + (key_bits >> 3); + ret = wd_set_rsa_prikey(c, &prvkey); + if (ret) { + HPRE_TST_PRT("wd_set_rsa_prikey fail!\n"); + return ret; + } + } +try_format_input: + /* Padding zero in this sample */ + if (in_size < key_size && op_type == RSA_PUB_EN) { + move = key_size - in_size; + memmove(in + move, in, in_size); + memset(in, 0, move); + } + } + + /* always key size bytes input */ + opdata.in_bytes = key_size; + if (op_type == RSA_PRV_DE) { + opdata.op_type = WCRYPTO_RSA_SIGN; + } else if (op_type == RSA_PUB_EN) { + opdata.op_type = WCRYPTO_RSA_VERIFY; + } else if (op_type == RSA_KEY_GEN) { + opdata.op_type = WCRYPTO_RSA_GENKEY; + } else { + ret = -EINVAL; + goto type_err; + } + if (op_type == RSA_KEY_GEN) { + ret = hpre_test_fill_keygen_opdata(c, &opdata); + if (ret) + goto type_err; + } else { + opdata.in = in; + opdata.out = out; + } + tag = NULL; + ret = wcrypto_do_rsa(c, &opdata, tag); + if (ret) + goto type_err; + if (openssl_check) { + ret = hpre_test_result_check(c, &opdata, key); + if (ret) + goto type_err; + else if (opdata->op_type == WCRYPTO_RSA_GENKEY) + HPRE_TST_PRT("HPRE hardware key generate successfully!\n"); + } else if (!openssl_check && op_type == RSA_KEY_GEN) { + HPRE_TST_PRT("HPRE hardware key generate finished!\n"); + } + if (op_type == RSA_PRV_DE) { + __u8 *tmp = opdata.out; + + move = 0; + while (!tmp[move]) + move++; + opdata.out_bytes -= move; + memmove(out, out + move, opdata.out_bytes); + } + return (int)opdata.out_bytes; +type_err: + return ret; +} +#endif + +int hpre_sys_qmng_test(int thread_num) +{ + int pid = getpid(), i = 0, ret; + int thread_id = (int)syscall(__NR_gettid); + struct wd_queue q; + + memset((void *)&q, 0, sizeof(q)); + q.capa.alg = "rsa"; + + while (1) { + ret = wd_request_queue(&q); + if (ret) { + HPRE_TST_PRT("Proc-%d, thrd-%d:request queue t-%d fail!\n", + pid, thread_id, i); + return ret; + } + i++; + if (is_allow_print(i, HPRE_ALG_INVLD_TYPE, thread_num)) + HPRE_TST_PRT("Proc-%d, %d-TD request %dQs at %dnode\n", + pid, thread_id, i, wd_get_node_id(&q)); + usleep(1); + wd_release_queue(&q); + } + return 0; +} + +int hpre_sys_func_test(struct test_hpre_pthread_dt * pdata) +{ + int pid = getpid(), ret = 0, i = 0; + int thread_id = (int)syscall(__NR_gettid); + struct wcrypto_rsa_ctx_setup setup; + struct wcrypto_rsa_op_data opdata; + void *ctx = NULL; + void *tag = NULL; + struct wd_queue *q = pdata->q; + void *key_info = NULL; + struct timeval cur_tval; + float time, speed; + int key_size = key_bits >> 3; + + if (performance_test && (!t_times && !t_seconds)) { + HPRE_TST_PRT("t_times or t_seconds err\n"); + return -1; + } + +new_test_again: + + memset(&setup, 0, sizeof(setup)); + memset(&opdata, 0, sizeof(opdata)); + setup.key_bits = key_bits; + setup.br.alloc = (void *)wd_alloc_blk; + setup.br.free = (void *)wd_free_blk; + setup.br.iova_map = (void *)wd_blk_iova_map; + setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + setup.br.usr = pdata->pool; + + if (!strcmp(g_mode, "-crt")) + setup.is_crt = true; + else + setup.is_crt = false; + + ctx = wcrypto_create_rsa_ctx(q, &setup); + if (!ctx) { + HPRE_TST_PRT("Proc-%d, %d-TD:create %s ctx fail!\n", + pid, thread_id, q->capa.alg); + ret = -EINVAL; + goto fail_release; + } + + /* Just make sure memory size is enough */ + key_info = malloc(key_size * 16); + if (!key_info) { + HPRE_TST_PRT("thrd-%d:malloc key!\n", thread_id); + goto fail_release; + } + + rsa_key_in = malloc(2 * key_size + sizeof(struct hpre_rsa_test_key_in)); + if (!rsa_key_in) { + HPRE_TST_PRT("thrd-%d:malloc err!\n", thread_id); + goto fail_release; + } + + rsa_key_in->e = rsa_key_in + 1; + rsa_key_in->p = rsa_key_in->e + key_size; + rsa_key_in->q = rsa_key_in->p + (key_size >> 1); + + memset(key_info, 0, key_size * 16); + ret = test_rsa_key_gen(ctx, NULL, key_info, key_info, 0); + if (ret) { + HPRE_TST_PRT("thrd-%d:Openssl key gen fail!\n", thread_id); + goto fail_release; + } + + /* always key size bytes input */ + opdata.in_bytes = key_size; + if (pdata->op_type == RSA_KEY_GEN) { + opdata.op_type = WCRYPTO_RSA_GENKEY; + } else if (pdata->op_type == RSA_PUB_EN) { + opdata.op_type = WCRYPTO_RSA_VERIFY; + } else if (pdata->op_type == RSA_PRV_DE) { + opdata.op_type = WCRYPTO_RSA_SIGN; + } else { + HPRE_TST_PRT("thrd-%d:optype=%d err!\n", + thread_id, pdata->op_type); + goto fail_release; + } + + if (opdata.op_type == WCRYPTO_RSA_GENKEY) { + ret = hpre_test_fill_keygen_opdata(ctx, &opdata); + if (ret){ + HPRE_TST_PRT("fill key gen opdata fail!\n"); + goto fail_release; + } + } else { + opdata.in = wd_alloc_blk(pdata->pool); + if (!opdata.in) { + HPRE_TST_PRT("alloc in buffer fail!\n"); + goto fail_release; + } + memset(opdata.in, 0, opdata.in_bytes); + opdata.out = wd_alloc_blk(pdata->pool); + if (!opdata.out) { + HPRE_TST_PRT("alloc out buffer fail!\n"); + goto fail_release; + } + } + + do { + if (!only_soft) { + ret = wcrypto_do_rsa(ctx, &opdata, tag); + if (ret || opdata.status) { + HPRE_TST_PRT("Proc-%d, T-%d:hpre %s %dth status=%d fail!\n", + pid, thread_id, + rsa_op_str[opdata.op_type], i, opdata.status); + goto fail_release; + } + } + + pdata->send_task_num++; + i++; + if (openssl_check) { + void *check_key; + + if (opdata.op_type == WCRYPTO_RSA_SIGN) + check_key = key_info; + if (opdata.op_type == WCRYPTO_RSA_VERIFY) + if (wcrypto_rsa_is_crt(ctx)) + check_key = key_info + 5 * (key_bits >> 4); + else + check_key = key_info; + else + check_key = key_info; + ret = hpre_test_result_check(ctx, &opdata, check_key); + if (ret) { + HPRE_TST_PRT("P-%d,T-%d:hpre %s %dth mismth\n", + pid, thread_id, + rsa_op_str[opdata.op_type], i); + goto fail_release; + } + else { + if (opdata.op_type == WCRYPTO_RSA_GENKEY) { + if (is_allow_print(i, WCRYPTO_RSA_GENKEY, pdata->thread_num)) + HPRE_TST_PRT("HPRE hardware key generate successfully!\n"); + } + } + } + + /* clean output buffer remainings in the last time operation */ + if (opdata.op_type == WCRYPTO_RSA_GENKEY) { + char *data; + int len; + + len = wcrypto_rsa_kg_out_data((void *)opdata.out, &data); + if (len < 0) { + HPRE_TST_PRT("wd rsa get key gen out data fail!\n"); + goto fail_release; + } + memset(data, 0, len); + } else { +#ifdef DEBUG + print_data(opdata.out, 16, "out"); +#endif + } + if (is_allow_print(i, pdata->op_type, pdata->thread_num)) { + gettimeofday(&cur_tval, NULL); + time = (float)((cur_tval.tv_sec - pdata->start_tval.tv_sec) * 1000000 + + (cur_tval.tv_usec - pdata->start_tval.tv_usec)); + speed = 1 / (time / i) * 1000; + HPRE_TST_PRT("Proc-%d, %d-TD %s %dtimes,%0.0fus, %0.3fkops\n", + pid, thread_id, rsa_op_str[opdata.op_type], + i, time, speed); + } + + if (!performance_test && !only_soft) { + if (opdata.op_type == WCRYPTO_RSA_GENKEY) { + if (opdata.in) + wcrypto_del_kg_in(ctx, opdata.in); + if (opdata.out) + wcrypto_del_kg_out(ctx, opdata.out); + } else { + if (opdata.in) + wd_free_blk(pdata->pool, opdata.in); + if (opdata.out) + wd_free_blk(pdata->pool, opdata.out); + } + + if (ctx) + wcrypto_del_rsa_ctx(ctx); + + if (rsa_key_in) + free(rsa_key_in); + + if (key_info) + free(key_info); + if (pdata->send_task_num == t_times) { + HPRE_TST_PRT("opType:%d run %d times or %d seconds will return!\n", pdata->op_type, t_times, t_seconds); + return 0; + } + goto new_test_again; + } + }while(!is_exit(pdata)); + + if (!performance_test) { + HPRE_TST_PRT("opType:%d run %d times or %d seconds will return!\n", pdata->op_type, t_times, t_seconds); + return 0; + } + + pdata->recv_task_num = pdata->send_task_num; + + if (performance_test) { + gettimeofday(&cur_tval, NULL); + time = (float)((cur_tval.tv_sec -pdata->start_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - pdata->start_tval.tv_usec); + + if (t_seconds) { + speed = pdata->send_task_num / time * 1000000; + HPRE_TST_PRT("Proc-%d, %d-TD: dh do %s send %u task, recv %u task, run %0.1f s at %0.3f ops\n", + pid, thread_id, rsa_op_str_perf[opdata.op_type], + pdata->send_task_num, pdata->recv_task_num, + time / 1000000, speed); + } else if (t_times) { + speed = 1 / (time / t_times) * 1000; + HPRE_TST_PRT("\r\nPID(%d)-thread-%d:%s CRT mode %dbits %s time %0.0f us, pkt len =" + " %d bytes, %0.3f Kops\n", getpid(), (int)syscall(__NR_gettid), "rsa", + key_bits, rsa_op_str_perf[opdata.op_type], time, key_bits / 8, speed); + } + } + +fail_release: + if (opdata.op_type == WCRYPTO_RSA_GENKEY) { + if (opdata.in) + wcrypto_del_kg_in(ctx, opdata.in); + if (opdata.out) + wcrypto_del_kg_out(ctx, opdata.out); + } else { + if (opdata.in) + wd_free_blk(pdata->pool, opdata.in); + if (opdata.out) + wd_free_blk(pdata->pool, opdata.out); + } + if (ctx) + wcrypto_del_rsa_ctx(ctx); + if (key_info) + free(key_info); + if (rsa_key_in) + free(rsa_key_in); + + + return ret; +} + +void *_hpre_rsa_sys_test_thread(void *data) +{ + int ret, cpuid; + struct test_hpre_pthread_dt *pdata = data; + cpu_set_t mask; + enum alg_op_type op_type; + int thread_num; + int pid = getpid(); + int thread_id = (int)syscall(__NR_gettid); + + CPU_ZERO(&mask); + cpuid = pdata->cpu_id; + op_type = pdata->op_type; + thread_num = pdata->thread_num; + CPU_SET(cpuid, &mask); + if (cpuid) { + ret = pthread_setaffinity_np(pthread_self(), + sizeof(mask), &mask); + if (ret < 0) { + HPRE_TST_PRT("Proc-%d, thrd-%d:set affinity fail!\n", + pid, thread_id); + return NULL; + } + HPRE_TST_PRT("Proc-%d, thrd-%d bind to cpu-%d!\n", + pid, thread_id, cpuid); + } + if (op_type == HPRE_ALG_INVLD_TYPE) { + ret = hpre_sys_qmng_test(thread_num); + if (ret) + return NULL; + } else { + ret = hpre_sys_func_test(pdata); + if (ret) + return NULL; + } + return NULL; +} + +static int hpre_sys_test(int thread_num, __u64 lcore_mask, + __u64 hcore_mask, enum alg_op_type op_type, + char *dev_path, unsigned int node_msk) +{ + void **pool; + struct wd_blkpool_setup setup; + int i, ret, cnt = 0, j; + int block_num = 512; + struct wd_queue *q; + int h_cpuid, qidx; + + q = malloc(q_num * sizeof(struct wd_queue)); + if (!q) { + HPRE_TST_PRT("malloc q memory fail!\n"); + return -ENOMEM; + } + memset(q, 0, q_num * sizeof(struct wd_queue)); + + /* create pool for every queue */ + pool = malloc(q_num * sizeof(pool)); + if (!pool) { + HPRE_TST_PRT("malloc pool memory fail!\n"); + return -ENOMEM; + } + + memset(pool, 0, q_num * sizeof(pool)); + + if (op_type != HPRE_ALG_INVLD_TYPE) { + for (j = 0; j < q_num; j++) { + if (op_type > MAX_RSA_ASYNC_TYPE && op_type < MAX_DH_TYPE) + q[j].capa.alg = "dh"; + else + q[j].capa.alg = "rsa"; + + if (dev_path) + strcpy(q[j].dev_path, dev_path); + q[j].node_mask = node_msk; + ret = wd_request_queue(&q[j]); + if (ret) { + HPRE_TST_PRT("request queue %d fail!\n", j); + return ret; + } + memset(&setup, 0, sizeof(setup)); + if (!strncmp(q[j].capa.alg, "dh", 2)) + setup.block_size = key_bits >> 2; + else if (!strncmp(q[j].capa.alg, "rsa", 3)) + setup.block_size = (key_bits >> 4) * 20; + setup.block_num = block_num; + setup.align_size = 64; + + pool[j] = wd_blkpool_create(&q[j], &setup); + if (!pool[j]) { + HPRE_TST_PRT("%s(): create %dth pool fail!\n", __func__, j); + return -ENOMEM; + } + } + } + if (_get_one_bits(lcore_mask) > 0) + cnt = _get_one_bits(lcore_mask); + else if (_get_one_bits(lcore_mask) == 0 && + _get_one_bits(hcore_mask) == 0) + cnt = thread_num; + for (i = 0; i < cnt; i++) { + qidx = i / ctx_num_per_q; + test_thrds_data[i].pool = pool[qidx]; + test_thrds_data[i].q = &q[qidx]; + test_thrds_data[i].thread_num = thread_num; + test_thrds_data[i].op_type = op_type; + test_thrds_data[i].cpu_id = _get_cpu_id(i, lcore_mask); + gettimeofday(&test_thrds_data[i].start_tval, NULL); + ret = pthread_create(&system_test_thrds[i], NULL, + _hpre_sys_test_thread, &test_thrds_data[i]); + if (ret) { + HPRE_TST_PRT("Create %dth thread fail!\n", i); + return ret; + } + } + for (i = 0; i < thread_num - cnt; i++) { + h_cpuid = _get_cpu_id(i, hcore_mask); + if (h_cpuid > 0) + h_cpuid += 64; + + qidx = (i + cnt) / ctx_num_per_q; + test_thrds_data[i + cnt].pool = pool[qidx]; + test_thrds_data[i + cnt].q = &q[qidx]; + test_thrds_data[i + cnt].thread_num = thread_num; + test_thrds_data[i + cnt].op_type = op_type; + test_thrds_data[i + cnt].cpu_id = h_cpuid; + gettimeofday(&test_thrds_data[i + cnt].start_tval, NULL); + ret = pthread_create(&system_test_thrds[i + cnt], NULL, + _hpre_sys_test_thread, &test_thrds_data[i + cnt]); + if (ret) { + HPRE_TST_PRT("Create %dth thread fail!\n", i); + return ret; + } + } + for (i = 0; i < thread_num; i++) { + ret = pthread_join(system_test_thrds[i], NULL); + if (ret) { + HPRE_TST_PRT("Join %dth thread fail!\n", i); + return ret; + } + } + + if (op_type != HPRE_ALG_INVLD_TYPE) { + for (j = 0; j < q_num; j++) { + wd_release_queue(&q[j]); + } + } + + return 0; +} + +static void *_rsa_async_poll_test_thread(void *data) +{ + struct test_hpre_pthread_dt *pdata = data; + struct wd_queue *q = pdata->q; + int ret; + + while (1) { + ret = wcrypto_rsa_poll(q, 1); + if (ret < 0) { + break; + } + + if (asyn_thread_exit) + break; + } + + return NULL; +} + +static void _rsa_cb(void *message, void *rsa_tag) +{ + int keybits, key_size; + struct rsa_async_tag *tag = rsa_tag; + void *ctx = tag->ctx; + int thread_id = tag->thread_id; + int cnt = tag->cnt; + struct wcrypto_rsa_msg *msg = message; + void *out = msg->out; + enum wcrypto_rsa_op_type op_type = msg->op_type; + struct wcrypto_rsa_prikey *prikey; + struct test_hpre_pthread_dt *thread_info = tag->thread_info; + + wcrypto_get_rsa_prikey(ctx, &prikey); + keybits = wcrypto_rsa_key_bits(ctx); + key_size = keybits >> 3; + + if (op_type == WCRYPTO_RSA_GENKEY) { + struct wcrypto_rsa_kg_out *kout = out; + + if (wcrypto_rsa_is_crt(ctx)) { + struct wd_dtb qinv, dq, dp; + struct wd_dtb *s_qinv, *s_dq, *s_dp; + + wcrypto_get_rsa_crt_prikey_params(prikey, &s_dq, &s_dp, + &s_qinv, NULL, NULL); + wcrypto_get_rsa_kg_out_crt_params(kout, &qinv, &dq, &dp); + if (memcmp(s_qinv->data, qinv.data, s_qinv->bsize)) { + HPRE_TST_PRT("keygen qinv mismatch!\n"); + return; + } + if (memcmp(s_dq->data, dq.data, s_dq->bsize)) { + HPRE_TST_PRT("keygen dq mismatch!\n"); + return; + } + if (memcmp(s_dp->data, dp.data, s_dp->bsize)) { + HPRE_TST_PRT("keygen dp mismatch!\n"); + return; + } + + } else { + struct wd_dtb d, n; + struct wd_dtb *s_d, *s_n; + + wcrypto_get_rsa_prikey_params(prikey, &s_d, &s_n); + wcrypto_get_rsa_kg_out_params(kout, &d, &n); + + /* check D */ + if (memcmp(s_d->data, d.data, s_d->bsize)) { + HPRE_TST_PRT("key generate D result mismatching!\n"); + return; + } + if (memcmp(s_n->data, n.data, s_n->bsize)) { + HPRE_TST_PRT("key generate N result mismatching!\n"); + return; + } + } + if (is_allow_print(cnt, DH_ASYNC_GEN, 1)) + HPRE_TST_PRT("HPRE hardware key generate successfully!\n"); + } else if (op_type == WCRYPTO_RSA_VERIFY) { + if (!only_soft && memcmp(ssl_params.ssl_verify_result, out, key_size)) { + HPRE_TST_PRT("pub encrypto result mismatch!\n"); + return; + } + } else { + if (wcrypto_rsa_is_crt(ctx)) + if (!only_soft && memcmp(ssl_params.ssl_sign_result, out, key_size)) { + HPRE_TST_PRT("prv decrypto result mismatch!\n"); + return; + } + } + + thread_info->recv_task_num++; + + if (is_allow_print(cnt, op_type, 1)) + HPRE_TST_PRT("thread %d do RSA %dth time success!\n", thread_id, cnt); + if (op_type == WCRYPTO_RSA_GENKEY && out) { + wcrypto_del_kg_out(ctx, out); + } + free(rsa_tag); +} + +void *_rsa_async_op_test_thread(void *data) +{ + int ret = 0, i = 0, cpuid; + struct test_hpre_pthread_dt *pdata = data; + cpu_set_t mask; + enum alg_op_type op_type; + int pid = getpid(); + int thread_id = (int)syscall(__NR_gettid); + void *pool; + struct wcrypto_rsa_ctx_setup setup; + struct wcrypto_rsa_op_data opdata; + void *ctx = NULL; + struct wd_queue *q; + void *key_info = NULL; + struct wcrypto_rsa_prikey *prikey; + struct wcrypto_rsa_pubkey *pubkey; + struct rsa_async_tag *tag; + struct wd_dtb *wd_e, *wd_d, *wd_n, *wd_dq, *wd_dp, *wd_qinv, *wd_q, *wd_p; + struct wd_dtb t_e, t_p, t_q; + u32 key_size = key_bits >> 3; + + if (performance_test && (!t_times && !t_seconds)) { + HPRE_TST_PRT("t_times or t_seconds err\n"); + return NULL; + } + + CPU_ZERO(&mask); + cpuid = pdata->cpu_id; + op_type = pdata->op_type; + q = pdata->q; + pool = pdata->pool; + CPU_SET(cpuid, &mask); + if (cpuid) { + ret = pthread_setaffinity_np(pthread_self(), + sizeof(mask), &mask); + if (ret < 0) { + HPRE_TST_PRT("Proc-%d, thrd-%d:set affinity fail!\n", + pid, thread_id); + return NULL; + } + HPRE_TST_PRT("Proc-%d, thrd-%d bind to cpu-%d!\n", + pid, thread_id, cpuid); + } + memset(&setup, 0, sizeof(setup)); + memset(&opdata, 0, sizeof(opdata)); + setup.key_bits = key_bits; + setup.cb = (void *)_rsa_cb; + setup.br.alloc = (void *)wd_alloc_blk; + setup.br.free = (void *)wd_free_blk; + setup.br.iova_map = (void *)wd_blk_iova_map; + setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + setup.br.usr = pool; + if (!strcmp(g_mode, "-crt")) + setup.is_crt = true; + else + setup.is_crt = false; + + ctx = wcrypto_create_rsa_ctx(q, &setup); + if (!ctx) { + HPRE_TST_PRT("Proc-%d, %d-TD:create %s ctx fail!\n", + pid, thread_id, q->capa.alg); + goto fail_release; + } + + rsa_key_in = malloc(2 * key_size + sizeof(struct hpre_rsa_test_key_in)); + if (!rsa_key_in) { + HPRE_TST_PRT("thrd-%d:malloc err!\n", thread_id); + goto fail_release; + } + + rsa_key_in->e = rsa_key_in + 1; + rsa_key_in->p = rsa_key_in->e + key_size; + rsa_key_in->q = rsa_key_in->p + (key_size >> 1); + + wcrypto_get_rsa_pubkey(ctx, &pubkey); + wcrypto_get_rsa_pubkey_params(pubkey, &wd_e, &wd_n); + wd_e->dsize = BN_bn2bin(ssl_params.e, (unsigned char *)wd_e->data); + if (wd_e->dsize > wd_e->bsize) { + HPRE_TST_PRT("e bn to bin overflow!\n"); + goto fail_release; + } + wd_n->dsize = BN_bn2bin(ssl_params.n, (unsigned char *)wd_n->data); + if (wd_n->dsize > wd_n->bsize) { + HPRE_TST_PRT("n bn to bin overflow!\n"); + goto fail_release; + } + + wcrypto_get_rsa_prikey(ctx, &prikey); + if (wcrypto_rsa_is_crt(ctx)) { + wcrypto_get_rsa_crt_prikey_params(prikey, &wd_dq, &wd_dp, &wd_qinv, &wd_q, &wd_p); + /* CRT mode private key */ + wd_dq->dsize = BN_bn2bin(ssl_params.dq, (unsigned char *)wd_dq->data); + if (wd_dq->dsize > wd_dq->bsize) { + HPRE_TST_PRT("dq bn to bin overflow!\n"); + goto fail_release; + } + wd_dp->dsize = BN_bn2bin(ssl_params.dp, (unsigned char *)wd_dp->data); + if (wd_dp->dsize > wd_dp->bsize) { + HPRE_TST_PRT("dp bn to bin overflow!\n"); + goto fail_release; + } + wd_qinv->dsize = BN_bn2bin(ssl_params.qinv, (unsigned char *)wd_qinv->data); + if (wd_qinv->dsize > wd_qinv->bsize) { + HPRE_TST_PRT("qinv bn to bin overflow!\n"); + goto fail_release; + } + wd_q->dsize = BN_bn2bin(ssl_params.q, (unsigned char *)wd_q->data); + if (wd_q->dsize > wd_q->bsize) { + HPRE_TST_PRT("q bn to bin overflow!\n"); + goto fail_release; + } + wd_p->dsize = BN_bn2bin(ssl_params.p, (unsigned char *)wd_p->data); + if (wd_p->dsize > wd_p->bsize) { + HPRE_TST_PRT("p bn to bin overflow!\n"); + goto fail_release; + } + + } else { + wcrypto_get_rsa_prikey_params(prikey, &wd_d, &wd_n); + + wd_d->dsize = BN_bn2bin(ssl_params.d, (unsigned char *)wd_d->data); + wd_n->dsize = BN_bn2bin(ssl_params.n, (unsigned char *)wd_n->data); + wd_e = &t_e; + wd_p = &t_p; + wd_q = &t_q; + memset(rsa_key_in->e, 0, key_size); + memset(rsa_key_in->p, 0, key_size >> 1); + memset(rsa_key_in->q, 0, key_size >> 1); + rsa_key_in->e_size = BN_bn2bin(ssl_params.e, (unsigned char *)rsa_key_in->e); + rsa_key_in->p_size = BN_bn2bin(ssl_params.p, (unsigned char *)rsa_key_in->p); + rsa_key_in->q_size = BN_bn2bin(ssl_params.q, (unsigned char *)rsa_key_in->q); + wd_e->data = rsa_key_in->e; + wd_e->dsize = rsa_key_in->e_size; + wd_p->data = rsa_key_in->p; + wd_p->dsize = rsa_key_in->p_size; + wd_q->data = rsa_key_in->q; + wd_q->dsize = rsa_key_in->q_size; + } + + /* always key size bytes input */ + opdata.in_bytes = key_size; + if (op_type == RSA_KEY_GEN || op_type == RSA_ASYNC_GEN) { + opdata.op_type = WCRYPTO_RSA_GENKEY; + } else if (op_type == RSA_PUB_EN || op_type == RSA_ASYNC_EN) { + opdata.op_type = WCRYPTO_RSA_VERIFY; + } else if (op_type == RSA_PRV_DE || op_type == RSA_ASYNC_DE) { + opdata.op_type = WCRYPTO_RSA_SIGN; + } else { + HPRE_TST_PRT("thrd-%d:optype=%d err!\n", + thread_id, op_type); + goto fail_release; + } + + if (opdata.op_type == WCRYPTO_RSA_GENKEY) { + opdata.in = (__u8 *)wcrypto_new_kg_in(ctx, wd_e, wd_p, wd_q); + if (!opdata.in) { + HPRE_TST_PRT("thrd-%d:fill key gen opdata fail!\n", + thread_id); + goto fail_release; + } + //opdata.out = wcrypto_new_kg_out(ctx); + //if (!opdata.out) { + // HPRE_TST_PRT("create rsa kgen out fail!\n"); + // goto fail_release; + //} + } else { + opdata.in = wd_alloc_blk(pool); + if (!opdata.in) { + HPRE_TST_PRT("alloc in buffer fail!\n"); + goto fail_release; + } + memset(opdata.in, 0, opdata.in_bytes); + opdata.out = wd_alloc_blk(pool); + if (!opdata.out) { + HPRE_TST_PRT("alloc out buffer fail!\n"); + goto fail_release; + } + memset(opdata.out, 0, opdata.in_bytes); + } + + do { + if (opdata.op_type == WCRYPTO_RSA_GENKEY) { + opdata.out = wcrypto_new_kg_out(ctx); + if (!opdata.out) { + HPRE_TST_PRT("create rsa kgen out fail!\n"); + goto fail_release; + } + } + /* set the user tag */ + tag = malloc(sizeof(*tag)); + if (!tag) + goto fail_release; + tag->ctx = ctx; + tag->thread_id = thread_id; + tag->cnt = i; + tag->thread_info = pdata; +try_do_again: + ret = wcrypto_do_rsa(ctx, &opdata, tag); + if (ret == -WD_EBUSY) { + usleep(100); + goto try_do_again; + } else if (ret) { + HPRE_TST_PRT("Proc-%d, T-%d:hpre %s %dth fail!\n", + pid, thread_id, + rsa_op_str[opdata.op_type], i); + goto fail_release; + } + //usleep(100); + i++; + pdata->send_task_num++; + }while (!is_exit(pdata)); + + if (!performance_test) { + HPRE_TST_PRT("opType:%d run %d times or %d seconds will return!\n", op_type, t_times, t_seconds); + return NULL; + } + + if (performance_test) { + struct timeval cur_tval; + float speed = 0.0, time_used = 0.0; + gettimeofday(&cur_tval, NULL); + time_used = (float)((cur_tval.tv_sec -pdata->start_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - pdata->start_tval.tv_usec); + + if (t_seconds) { + speed = pdata->recv_task_num / time_used * 1000000; + HPRE_TST_PRT("Proc-%d, %d-TD: rsa do %s send %u task, recv %u task, run %0.1f s at %0.3f ops\n", + pid, thread_id, rsa_op_str[opdata.op_type], + pdata->send_task_num, pdata->recv_task_num, + time_used / 1000000, speed); + } else if (t_times) { + speed = 1 / (time_used / t_times) * 1000; + HPRE_TST_PRT("\r\nPID(%d)-thread-%d:%s CRT mode %dbits %s time %0.0f us, pkt len =" + " %d bytes, %0.3f Kops\n", getpid(), (int)syscall(__NR_gettid), "rsa", + key_bits, rsa_op_str_perf[opdata.op_type], time_used, key_bits / 8, speed); + } + } + + /* wait for recv finish */ + while (pdata->send_task_num != pdata->recv_task_num) + usleep(1000); + + +fail_release: + if (opdata.op_type == WCRYPTO_RSA_GENKEY) { + if (opdata.in) + wcrypto_del_kg_in(ctx, opdata.in); + //if (opdata.out) + // wcrypto_del_kg_out(ctx, opdata.out); + } else { + if (opdata.in) + wd_free_blk(pool, opdata.in); + if (opdata.out) + wd_free_blk(pool, opdata.out); + } + if (ctx) + wcrypto_del_rsa_ctx(ctx); + if (key_info) + free(key_info); + if (rsa_key_in) + free(rsa_key_in); + return NULL; +} + +static int set_ssl_plantext(void) +{ + ssl_params.size = key_bits >> 3; + ssl_params.plantext = malloc(ssl_params.size); + if (!ssl_params.plantext) + return -ENOMEM; + memset(ssl_params.plantext, 0, ssl_params.size); + return 0; +} + +static int rsa_openssl_key_gen_for_async_test(void) +{ + int ret; + + ssl_params.rsa = RSA_new(); + if (!ssl_params.rsa) { + HPRE_TST_PRT("RSA new fail!\n"); + return -ENOMEM; + } + ssl_params.e = BN_new(); + if (!ssl_params.e) { + RSA_free(ssl_params.rsa); + ssl_params.rsa = NULL; + HPRE_TST_PRT("BN new e fail!\n"); + ret = -ENOMEM; + goto gen_fail; + } + ret = BN_set_word(ssl_params.e, 65537); + if (ret != 1) { + HPRE_TST_PRT("BN_set_word fail!\n"); + ret = -1; + goto gen_fail; + } + + /* Generate OpenSSL SW rsa parameters */ + ret = RSA_generate_key_ex(ssl_params.rsa, key_bits, ssl_params.e, NULL); + if (ret != 1) { + HPRE_TST_PRT("RSA_generate_key_ex fail!\n"); + ret = -1; + goto gen_fail; + } + RSA_get0_key((const RSA *)ssl_params.rsa, (const BIGNUM **)&ssl_params.n, + (const BIGNUM **)&ssl_params.e, (const BIGNUM **)&ssl_params.d); + RSA_get0_factors((const RSA *)ssl_params.rsa, (const BIGNUM **)&ssl_params.p, + (const BIGNUM **)&ssl_params.q); + RSA_get0_crt_params((const RSA *)ssl_params.rsa, (const BIGNUM **)&ssl_params.dp, + (const BIGNUM **)&ssl_params.dq, (const BIGNUM **)&ssl_params.qinv); + + /* Generate OpenSSL SW rsa verify and sign standard result + * for check in the next tests + */ + ret = set_ssl_plantext(); + if (ret) { + HPRE_TST_PRT("set ssl plantext fail!!\n"); + ret = -1; + goto gen_fail; + } + ssl_params.ssl_verify_result = malloc(ssl_params.size); + if (!ssl_params.ssl_verify_result) { + HPRE_TST_PRT("malloc verify result buffer fail!!\n"); + ret = -1; + goto gen_fail; + } + ret = RSA_public_encrypt(ssl_params.size, ssl_params.plantext, + ssl_params.ssl_verify_result, + ssl_params.rsa, RSA_NO_PADDING); + if (ret != ssl_params.size) { + HPRE_TST_PRT("openssl pub encrypto fail!ret=%d\n", ret); + ret = -1; + return ret; + } + ssl_params.ssl_sign_result = malloc(ssl_params.size); + if (!ssl_params.ssl_sign_result) { + HPRE_TST_PRT("malloc sign result buffer fail!!\n"); + ret = -1; + goto gen_fail; + } + ret = RSA_private_decrypt(ssl_params.size, ssl_params.plantext, + ssl_params.ssl_sign_result, + ssl_params.rsa, RSA_NO_PADDING); + if (ret != ssl_params.size) { + HPRE_TST_PRT("openssl priv decrypto fail!ret=%d\n", ret); + ret = -1; + goto gen_fail; + } + + return 0; +gen_fail: + RSA_free(ssl_params.rsa); + BN_free(ssl_params.e); + if (ssl_params.plantext) + free(ssl_params.plantext); + if (ssl_params.ssl_verify_result) + free(ssl_params.ssl_verify_result); + if (ssl_params.ssl_sign_result) + free(ssl_params.ssl_sign_result); + return ret; +} + +static int rsa_async_test(int thread_num, __u64 lcore_mask, + __u64 hcore_mask, enum alg_op_type op_type) +{ + unsigned int block_num = 2048; + void *pool; + struct wd_blkpool_setup setup; + struct wd_queue q; + int ret = 0, cnt = 0, i; + int h_cpuid; + + memset(&q, 0, sizeof(q)); + q.capa.alg = "rsa"; + ret = wd_request_queue(&q); + if (ret) { + HPRE_TST_PRT("%s:request queue fail!\n", __func__); + return ret; + } + memset(&setup, 0, sizeof(setup)); + setup.block_size = (key_bits >> 4) * 20; + setup.block_num = block_num; + setup.align_size = 64; + + pool = wd_blkpool_create(&q, &setup); + if (!pool) { + HPRE_TST_PRT("%s(): create pool fail!\n", __func__); + return -ENOMEM; + } + + /* Create poll thread at first */ + test_thrds_data[0].pool = pool; + test_thrds_data[0].q = &q; + test_thrds_data[0].thread_num = 1; + test_thrds_data[0].op_type = op_type; + test_thrds_data[0].cpu_id = 0; + ret = pthread_create(&system_test_thrds[0], NULL, + _rsa_async_poll_test_thread, &test_thrds_data[0]); + if (ret) { + HPRE_TST_PRT("Create poll thread fail!\n"); + return ret; + } + + ret = rsa_openssl_key_gen_for_async_test(); + if(ret) { + HPRE_TST_PRT("openssl genkey for async thread test fail!"); + return 0; + } + + if (_get_one_bits(lcore_mask) > 0) + cnt = _get_one_bits(lcore_mask); + else if (_get_one_bits(lcore_mask) == 0 && + _get_one_bits(hcore_mask) == 0) + cnt = thread_num; + for (i = 1; i <= cnt; i++) { + test_thrds_data[i].pool = pool; + test_thrds_data[i].q = &q; + test_thrds_data[i].thread_num = thread_num; + test_thrds_data[i].op_type = op_type; + test_thrds_data[i].cpu_id = _get_cpu_id(i - 1, lcore_mask); + gettimeofday(&test_thrds_data[i].start_tval, NULL); + ret = pthread_create(&system_test_thrds[i], NULL, + _rsa_async_op_test_thread, &test_thrds_data[i]); + if (ret) { + HPRE_TST_PRT("Create %dth thread fail!\n", i); + return ret; + } + } + for (i = 1; i <= thread_num - cnt; i++) { + h_cpuid = _get_cpu_id(i - 1, hcore_mask); + if (h_cpuid > 0) + h_cpuid += 64; + test_thrds_data[i + cnt].pool = pool; + test_thrds_data[i + cnt].q = &q; + test_thrds_data[i + cnt].thread_num = thread_num; + test_thrds_data[i + cnt].op_type = op_type; + test_thrds_data[i + cnt].cpu_id = h_cpuid; + gettimeofday(&test_thrds_data[i + cnt].start_tval, NULL); + ret = pthread_create(&system_test_thrds[i + cnt], NULL, + _rsa_async_op_test_thread, &test_thrds_data[i + cnt]); + if (ret) { + HPRE_TST_PRT("Create %dth thread fail!\n", i); + return ret; + } + } + for (i = 1; i <= thread_num; i++) { + ret = pthread_join(system_test_thrds[i], NULL); + if (ret) { + HPRE_TST_PRT("Join %dth thread fail!\n", i); + return ret; + } + } + + asyn_thread_exit = 1; + + ret = pthread_join(system_test_thrds[0], NULL); + if (ret) { + HPRE_TST_PRT("Join %dth thread fail!\n", i); + return ret; + } + + wd_release_queue(&q); + wd_blkpool_destroy(pool); + return 0; +} + +static void *_dh_async_poll_test_thread(void *data) +{ + struct test_hpre_pthread_dt *pdata = data; + struct wd_queue *q = pdata->q; + int ret, cpuid; + int pid = getpid(); + cpu_set_t mask; + int thread_id = (int)syscall(__NR_gettid); + + CPU_ZERO(&mask); + cpuid = pdata->cpu_id; + CPU_SET(cpuid, &mask); + if (cpuid) { + ret = pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask); + if (ret < 0) { + HPRE_TST_PRT("Proc-%d, thrd-%d:set affinity fail!\n", + pid, thread_id); + return NULL; + } + HPRE_TST_PRT("Proc-%d, poll thrd-%d bind to cpu-%d!\n", + pid, thread_id, cpuid); + } + + while (1) { + ret = wcrypto_dh_poll(q, 1); + if (ret < 0) { + break; + } + + if (asyn_thread_exit) + break; + } + + HPRE_TST_PRT("%s exit!\n", __func__); + return NULL; +} + +static int dh_async_test(int thread_num, __u64 lcore_mask, + __u64 hcore_mask, enum alg_op_type op_type) +{ + void *bufPool; + struct wd_blkpool_setup setup; + int i, ret, cnt = 0; + int block_num = 1024*16; + struct wd_queue *q; + int h_cpuid; + + q = malloc(sizeof(struct wd_queue)); + if (!q) { + HPRE_TST_PRT("malloc q memory fail!\n"); + return -ENOMEM; + } + memset(q, 0, sizeof(struct wd_queue)); + + q->capa.alg = "dh"; + ret = wd_request_queue(q); + if (ret) { + HPRE_TST_PRT("request queue fail!\n"); + return ret; + } + memset(&setup, 0, sizeof(setup)); + setup.block_size = key_bits >> 2; // block_size; + setup.block_num = block_num; + setup.align_size = 64; + + bufPool = wd_blkpool_create(q, &setup); + if (!bufPool) { + HPRE_TST_PRT("%s(): create pool fail!\n", __func__); + return -ENOMEM; + } + + if (_get_one_bits(lcore_mask) > 0) + cnt = _get_one_bits(lcore_mask); + else if (_get_one_bits(lcore_mask) == 0 && + _get_one_bits(hcore_mask) == 0) + cnt = thread_num; + + /* Create poll thread at first */ + test_thrds_data[0].pool = bufPool; + test_thrds_data[0].q = q; + test_thrds_data[0].thread_num = 1; + test_thrds_data[0].op_type = op_type; + test_thrds_data[0].cpu_id = 0; + ret = pthread_create(&system_test_thrds[0], NULL, + _dh_async_poll_test_thread, &test_thrds_data[0]); + if (ret) { + HPRE_TST_PRT("Create poll thread fail!\n"); + return ret; + } + + for (i = 1; i <= cnt; i++) { + test_thrds_data[i].pool = bufPool; + test_thrds_data[i].q = q; + test_thrds_data[i].thread_num = thread_num; + test_thrds_data[i].op_type = op_type; + test_thrds_data[i].cpu_id = _get_cpu_id(i - 1, lcore_mask); + gettimeofday(&test_thrds_data[i].start_tval, NULL); + ret = pthread_create(&system_test_thrds[i], NULL, + _hpre_dh_sys_test_thread, &test_thrds_data[i]); + if (ret) { + HPRE_TST_PRT("Create %dth thread fail!\n", i); + return ret; + } + } + + for (i = 1; i <= thread_num - cnt; i++) { + h_cpuid = _get_cpu_id(i - 1, hcore_mask); + if (h_cpuid > 0) + h_cpuid += 64; + + test_thrds_data[i + cnt].pool = bufPool; + test_thrds_data[i + cnt].q = q; + test_thrds_data[i + cnt].thread_num = thread_num; + test_thrds_data[i + cnt].op_type = op_type; + test_thrds_data[i + cnt].cpu_id = h_cpuid; + gettimeofday(&test_thrds_data[i + cnt].start_tval, NULL); + ret = pthread_create(&system_test_thrds[i + cnt], NULL, + _hpre_dh_sys_test_thread, &test_thrds_data[i + cnt]); + if (ret) { + HPRE_TST_PRT("Create %dth thread fail!\n", i); + return ret; + } + } + + for (i = 1; i <= thread_num; i++) { + ret = pthread_join(system_test_thrds[i], NULL); + if (ret) { + HPRE_TST_PRT("Join %dth thread fail!\n", i); + return ret; + } + } + + asyn_thread_exit = 1; + + ret = pthread_join(system_test_thrds[0], NULL); + if (ret) { + HPRE_TST_PRT("Join %dth thread fail!\n", i); + return ret; + } + + return 0; +} + +void *_hpre_sys_test_thread(void *data) +{ + enum alg_op_type op_type; + struct test_hpre_pthread_dt *pdata = data; + + op_type = pdata->op_type; + if (op_type > MAX_RSA_ASYNC_TYPE && op_type < MAX_DH_TYPE ) { + return _hpre_dh_sys_test_thread(data); + } else { + return _hpre_rsa_sys_test_thread(data); + } +} +void normal_register(const char *format, ...) +{ + printf("wd log:%s", format); + return; +} + +void redirect_log_2_file(const char *format, ...) +{ + FILE *fp; + fp = fopen("file.txt", "a+"); + fprintf(fp,format,__FILE__, __LINE__, __func__); + fclose(fp); + return; +} + +void segmant_fault_register(const char *format, ...) +{ + int *ptr = NULL; + *ptr = 0; + return; +} +int main(int argc, char *argv[]) +{ + void *pool = NULL; + enum alg_op_type alg_op_type = HPRE_ALG_INVLD_TYPE; + enum alg_op_mode mode; + __u8 *in = NULL, *tp_in, *temp_in = NULL; + __u8 *out = NULL; + __u8 *key = NULL; + char *in_file = NULL; + char *out_file = NULL; + char *key_file = NULL; + int ret = 0, in_size = 0, op_size; + int priv_key_size, pub_key_size, key_info_size; + int read_size, out_fd = -1, try_close = 1; + int block_num = 1024; + struct wd_queue q; + struct wcrypto_rsa_ctx_setup setup; + struct wcrypto_dh_ctx_setup dh_setup; + void *ctx = NULL; + int thread_num, bits; + __u64 core_mask[2]; + u32 value = 0; + char dev_path[PATH_STR_SIZE] = {0}; + unsigned int node_msk = 0; + + if (!argv[1] || !argv[6]) { + HPRE_TST_PRT("pls use ./test_hisi_hpre -help get details!\n"); + return -EINVAL; + } + + if (argv[7] && !strcmp(argv[7], "-check")) + openssl_check = 1; + if (argv[7] && !strcmp(argv[7], "-soft")) + only_soft = 1; + + if (!strcmp(argv[argc-1], "-registerlog-0")){ + ret = wd_register_log(NULL); + if (!ret){ + printf("illegel to register null log interface"); + return -EINVAL; + } + return 0; + } + if (!strcmp(argv[argc-1], "-registerlog-1")){ + ret = wd_register_log(redirect_log_2_file); + if (ret){ + printf("fail to register log interface"); + return -EINVAL; + } + if (argc == 2){ + char *error_info = "q, info or dev_info NULL!"; + struct wd_queue *q = NULL; + char content[1024]; + wd_get_node_id(q); + FILE *fp = NULL; + fp = fopen("file.txt", "r"); + if (fgets(content,1024,fp) == NULL) + return -EIO; + if (strstr(content,error_info) == NULL){ + return -EINVAL; + } + return 0; + } + } + if (!strcmp(argv[argc-1], "-registerlog-2")){ + ret = wd_register_log(normal_register); + if (ret){ + printf("fail to register log interface"); + return -EINVAL; + } + if (!wd_register_log(normal_register)){ + printf("illegel to register dumplicate log interface"); + return -EINVAL; + } + return 0; + } + if (!strcmp(argv[argc-1], "-registerlog-3")){ + ret = wd_register_log(segmant_fault_register); + if (ret){ + printf("fail to register log interface"); + return -EINVAL; + } + WD_ERR("segment fault"); + return 0; + } + if (!strcmp(argv[1], "-system-qt")) { + is_system_test = 1; + HPRE_TST_PRT("Now doing system queue mng test!\n"); + } else if (!strcmp(argv[1], "-system-gen")) { + alg_op_type = RSA_KEY_GEN; + is_system_test = 1; + HPRE_TST_PRT("Now doing system key gen test!\n"); + } else if (!strcmp(argv[1], "-system-vrf")) { + alg_op_type = RSA_PUB_EN; + is_system_test = 1; + HPRE_TST_PRT("Now doing system verify test!\n"); + } else if (!strcmp(argv[1], "-system-sgn")) { + alg_op_type = RSA_PRV_DE; + is_system_test = 1; + HPRE_TST_PRT("Now doing system sign test!\n"); + } else if (!strcmp(argv[1], "-system-asgn")) { + alg_op_type = RSA_ASYNC_DE; + is_system_test = 1; + HPRE_TST_PRT("Now doing system rsa async sign test!\n"); + } else if (!strcmp(argv[1], "-system-avrf")) { + alg_op_type = RSA_ASYNC_EN; + is_system_test = 1; + HPRE_TST_PRT("Now doing system rsa async verify test!\n"); + } else if (!strcmp(argv[1], "-system-agen")) { + alg_op_type = RSA_ASYNC_GEN; + is_system_test = 1; + HPRE_TST_PRT("Now doing system rsa async kgerate test!\n"); + } else if (!strcmp(argv[1], "-system-gen1")) { + HPRE_TST_PRT("DH key generation\n"); + alg_op_type = DH_GEN; + is_system_test = 1; + } else if (!strcmp(argv[1], "-system-agen1")) { + HPRE_TST_PRT("DH gen async\n"); + alg_op_type = DH_ASYNC_GEN; + is_system_test = 1; + } else if (!strcmp(argv[1], "-system-gen2")) { + HPRE_TST_PRT("DH key generation\n"); + alg_op_type = DH_COMPUTE; + is_system_test = 1; + } else if (!strcmp(argv[1], "-system-agen2")) { + HPRE_TST_PRT("DH gen async\n"); + alg_op_type = DH_ASYNC_COMPUTE; + is_system_test = 1; + } else { + goto basic_function_test; + } + + if (argv[8]) { + key_bits = strtoul(argv[8], NULL, 10); + } else { + key_bits = 2048; + } + + /* Do sys test for performance and mult threads/process scenarioes */ + if (is_system_test) { + if (!strcmp(argv[2], "-t")) { + thread_num = strtoul((char *)argv[3], NULL, 10); + if (thread_num <= 0 || thread_num > TEST_MAX_THRD) { + HPRE_TST_PRT("Invalid threads num:%d!\n", + thread_num); + HPRE_TST_PRT("Now set threads num as 2\n"); + thread_num = 2; + } + } else { + HPRE_TST_PRT("./test_hisi_hpre --help get details\n"); + return -EINVAL; + } + if (strcmp(argv[4], "-c")) { + HPRE_TST_PRT("./test_hisi_hpre --help get details\n"); + return -EINVAL; + } + + if (argv[5][0] != '0' || argv[5][1] != 'x') { + HPRE_TST_PRT("Err:coremask should be hex!\n"); + return -EINVAL; + } + if (strlen(argv[5]) > 34) { + HPRE_TST_PRT("Warning: coremask is cut!\n"); + argv[5][34] = 0; + } + if (strlen(argv[5]) <= 18) { + core_mask[0] = strtoull(argv[5], NULL, 16); + if (core_mask[0] & 0x1) { + HPRE_TST_PRT("Warn:cannot bind to core 0,\n"); + HPRE_TST_PRT("now run without binding\n"); + core_mask[0] = 0x0; /* no binding */ + } + core_mask[1] = 0; + } else { + int offset = 0; + char *temp; + + offset = strlen(argv[5]) - 16; + core_mask[0] = strtoull(&argv[5][offset], NULL, 16); + if (core_mask[0] & 0x1) { + HPRE_TST_PRT("Warn:cannot bind to core 0,\n"); + HPRE_TST_PRT("now run without binding\n"); + core_mask[0] = 0x0; /* no binding */ + } + temp = malloc(64); + strcpy(temp, argv[5]); + temp[offset] = 0; + core_mask[1] = strtoull(temp, NULL, 16); + } + bits = _get_one_bits(core_mask[0]); + bits += _get_one_bits(core_mask[1]); + if (thread_num > bits) { + HPRE_TST_PRT("Coremask not covers all thrds,\n"); + HPRE_TST_PRT("Bind first %d thrds!\n", bits); + } else if (thread_num < bits) { + HPRE_TST_PRT("Coremask overflow,\n"); + HPRE_TST_PRT("Just try to bind all thrds!\n"); + } + if (!strcmp(argv[6], "-log")) { + with_log = 1; + performance_test = 0; + } else if (!strcmp(argv[6], "-performance")) { + with_log = 0; + openssl_check = 0; + performance_test = 1; + } else { + with_log = 0; + performance_test = 0; + } + + if (argv[9]) { + ctx_num_per_q = strtoul(argv[9], NULL, 10); + if (ctx_num_per_q <= 0) { + HPRE_TST_PRT("Invalid ctx num per queue:%s!\n", + argv[9]); + HPRE_TST_PRT("Now ctx num per queue is set as 1!\n"); + ctx_num_per_q = 1; + } + } else { + HPRE_TST_PRT("Now ctx num per queue is set as 1!\n"); + ctx_num_per_q = 1; + } + + q_num = (thread_num - 1) / ctx_num_per_q + 1; + + if (argc == 13) { + if (!strcmp(argv[10], "-g2")) { + g_mode = "-g2"; + } else if (!strcmp(argv[10], "-com")) { + g_mode = "-com"; + } else if (!strcmp(argv[10], "-crt")) { + g_mode = "-crt"; + } else { + HPRE_TST_PRT("pls use ./test_hisi_hpre -help get details!\n"); + return -EINVAL; + } + + if (!strcmp(argv[11], "-seconds") || + !strcmp(argv[11], "-cycles")) { + value = strtoul(argv[12], NULL, 10); + if (!strcmp(argv[11], "-seconds")) { + t_seconds = value; + } else if (!strcmp(argv[11], "-cycles")) { + t_times = value; + } else { + HPRE_TST_PRT("pls use ./test_hisi_hpre -help get details!\n"); + return -EINVAL; + } + } else if (!strcmp(argv[11], "-dev")) { + strcpy(dev_path, argv[12]); + } else if (!strcmp(argv[11], "-node")) { + node_msk = strtoul(argv[12], NULL, 16); + } else { + HPRE_TST_PRT("pls use ./test_hisi_hpre -help get details!\n"); + return -EINVAL; + } + } + + if (argc == 12) { + if (!strcmp(argv[10], "-seconds") || + !strcmp(argv[10], "-cycles")) { + value = strtoul(argv[11], NULL, 10); + if (!strcmp(argv[10], "-seconds")) { + t_seconds = value; + HPRE_TST_PRT("set t_seconds:%d\n", t_seconds); + } else if (!strcmp(argv[11], "-cycles")) { + t_times = value; + HPRE_TST_PRT("set t_times:%d\n", t_times); + } else { + HPRE_TST_PRT("pls use ./test_hisi_hpre -help get details!\n"); + return -EINVAL; + } + } else if (!strcmp(argv[10], "-dev")) { + strcpy(dev_path, argv[11]); + } else if (!strcmp(argv[10], "-node")) { + node_msk = strtoul(argv[11], NULL, 16); + } else { + HPRE_TST_PRT("pls use ./test_hisi_hpre -help get details!\n"); + return -EINVAL; + } + } + + if (argc == 11) { + if (!strcmp(argv[10], "-g2")) { + g_mode = "-g2"; + } else if (!strcmp(argv[10], "-com")) { + g_mode = "-com"; + } else if (!strcmp(argv[10], "-crt")) { + g_mode = "-crt"; + } else { + HPRE_TST_PRT("pls use ./test_hisi_hpre -help get details!\n"); + return -EINVAL; + } + } + + HPRE_TST_PRT("Proc-%d: starts %d threads bind to %s\n", + getpid(), thread_num, argv[5]); + HPRE_TST_PRT(" lcoremask=0x%llx, hcoremask=0x%llx\n", + core_mask[0], core_mask[1]); + if (alg_op_type < MAX_RSA_SYNC_TYPE || alg_op_type == DH_GEN || alg_op_type == DH_COMPUTE) + return hpre_sys_test(thread_num, core_mask[0], + core_mask[1], alg_op_type, dev_path, node_msk); + else if (alg_op_type > MAX_RSA_SYNC_TYPE && alg_op_type < MAX_RSA_ASYNC_TYPE) + return rsa_async_test(thread_num, core_mask[0], + core_mask[1], alg_op_type); + else if (alg_op_type == DH_ASYNC_GEN || alg_op_type == DH_ASYNC_COMPUTE) + return dh_async_test(thread_num, core_mask[0], + core_mask[1], alg_op_type); + else + return -1; /* to extend other test samples */ + } +basic_function_test: + if (!strcmp(argv[1], "-en")) { + alg_op_type = RSA_PUB_EN; + HPRE_TST_PRT("RSA public key encrypto\n"); + } else if (!strcmp(argv[1], "-de")) { + alg_op_type = RSA_PRV_DE; + HPRE_TST_PRT("RSA private key decrypto\n"); + } else if (!strcmp(argv[1], "-gen")) { + HPRE_TST_PRT("RSA key generation\n"); + alg_op_type = RSA_KEY_GEN; + } else if (!strcmp(argv[1], "-gen1")) { + HPRE_TST_PRT("DH key generation\n"); + alg_op_type = DH_GEN; + } else if (!strcmp(argv[1], "-rsa-num")) { + printf("num %d\n", wd_get_available_dev_num("rsa")); + return 0; + } else if (!strcmp(argv[1], "-dh-num")) { + printf("num %d\n", wd_get_available_dev_num("dh")); + return 0; + } else if (!strcmp(argv[1], "-zip-num")) { + printf("num %d\n", wd_get_available_dev_num("zip")); + return 0; + } else if (!strcmp(argv[1], "-xx-num")) { + printf("num %d\n", wd_get_available_dev_num("xx")); + return 0; + } else if (!strcmp(argv[1], "--help")) { + HPRE_TST_PRT("[version]:1.0\n"); + HPRE_TST_PRT("NAME\n"); + HPRE_TST_PRT(" test_hisi_hpre: test wd hpre function,etc\n"); + HPRE_TST_PRT(" example 1: test_hisi_hpre_rsa -system-asgn -t 1 -c 0x2 -performance -nocheck 2048 2\n"); + HPRE_TST_PRT(" example 2: test_hisi_hpre -gen1 256 -g2 public private crt_private -check hisi_hpre-0\n"); + HPRE_TST_PRT("SYNOPSIS\n"); + HPRE_TST_PRT(" test_hisi_hpre [op_type] -t [thread_num] -c [core_mask] [log] [openssl_check] [key_bits]...[ctx_num_per_q] [mode] [others]\n"); + HPRE_TST_PRT(" test_hisi_hpre [op_type] [key_bits] [mode] [in] [out] [key_file] [openssl_check] [dev_path]...[others]\n"); + HPRE_TST_PRT("DESCRIPTION\n"); + HPRE_TST_PRT(" [op_type]:\n"); + HPRE_TST_PRT(" -system-qt = queue request and release test\n"); + HPRE_TST_PRT(" -system-gen = RSA key generate synchronize test\n"); + HPRE_TST_PRT(" -system-agen = RSA key generate c test\n"); + HPRE_TST_PRT(" -system-sgn = RSA signature synchronize test\n"); + HPRE_TST_PRT(" -system-asgn = RSA signature asynchronize test\n"); + HPRE_TST_PRT(" -system-vrf = RSA verification synchronize test\n"); + HPRE_TST_PRT(" -system-avrf = RSA verification asynchronize test\n"); + HPRE_TST_PRT(" -system-gen1 = DH phase 1 key generate synchronize test\n"); + HPRE_TST_PRT(" -system-agen1 = DH phase 1 key generate asynchronize test\n"); + HPRE_TST_PRT(" -system-gen2 = DH phase 2 key generate synchronize test\n"); + HPRE_TST_PRT(" -system-agen2 = DH phase 2 key generate asynchronize test\n"); + HPRE_TST_PRT(" -gen1 = DH share key generate test\n"); + HPRE_TST_PRT(" -registerlog-0 = register null log interface\n"); + HPRE_TST_PRT(" -registerlog-1 = register normal log interface\n"); + HPRE_TST_PRT(" -registerlog-2 = register dumplicate log interface\n"); + HPRE_TST_PRT(" -registerlog-3 = register unnormal log interface\n"); + HPRE_TST_PRT(" [thread_num]: start thread total\n"); + HPRE_TST_PRT(" [core_mask]: mask for bind cpu core, as 0x3 bind to cpu-1 and cpu-2\n"); + HPRE_TST_PRT(" [log]:\n"); + HPRE_TST_PRT(" -log\n"); + HPRE_TST_PRT(" -nolog\n"); + HPRE_TST_PRT(" -performance: use test DH and RSA perf\n"); + HPRE_TST_PRT(" [openssl_check]:\n"); + HPRE_TST_PRT(" 1: check result compared with openssl\n"); + HPRE_TST_PRT(" 0: no check\n"); + HPRE_TST_PRT(" [key_bits]:key size (bits)\n"); + HPRE_TST_PRT(" [ctx_num_per_q]:run ctx number per queue\n"); + HPRE_TST_PRT(" [mode]:\n"); + HPRE_TST_PRT(" -g2 = DH G2 mode\n"); + HPRE_TST_PRT(" -com = common mode\n"); + HPRE_TST_PRT(" -crt = RSA CRT mode\n"); + HPRE_TST_PRT(" [dev_path]: designed dev path\n"); + HPRE_TST_PRT(" [others]:\n"); + HPRE_TST_PRT(" -seconds [10] = test time set (s), for 10s\n"); + HPRE_TST_PRT(" -cycles [10] = test cycle set (times), for 10 times\n"); + HPRE_TST_PRT(" [--help] = usage\n"); + return 0; + } else { + HPRE_TST_PRT("Unknown option\n"); + HPRE_TST_PRT("<>\n"); + return -EINVAL; + } + if (argv[2]) { + key_bits = strtoul(argv[2], NULL, 10); + if (key_bits != 1024 && key_bits != 2048 && + key_bits != 3072 && key_bits != 4096) { + key_bits = 2048; + } + } else { + key_bits = 2048; + } + HPRE_TST_PRT("RSA/DH key size=%d bits\n", key_bits); + if (!strcmp(argv[3], "-crt")) { + HPRE_TST_PRT("RSA CRT mode\n"); + mode = RSA_CRT_MD; + } else if (!strcmp(argv[3], "-com") && alg_op_type < MAX_RSA_ASYNC_TYPE) { + HPRE_TST_PRT("RSA Common mode\n"); + mode = RSA_COM_MD; + } else if (!strcmp(argv[3], "-com") && alg_op_type > MAX_RSA_ASYNC_TYPE) { + HPRE_TST_PRT("DH Common mode\n"); + mode = DH_COM_MD; + } else if (!strcmp(argv[3], "-g2")) { + HPRE_TST_PRT("DH g2 mode\n"); + mode = DH_G2; + } else { + HPRE_TST_PRT("please input a mode:<-crt> <-com>for rsa!\n"); + HPRE_TST_PRT("and:<-g2> <-com>for dh!\n"); + return -EINVAL; + } + in_file = argv[4]; + out_file = argv[5]; + key_file = argv[6]; + memset((void *)&q, 0, sizeof(q)); + if (argc >= 9) { + strcpy(q.dev_path, argv[8]); + HPRE_TST_PRT("denote dev path:%s\n", argv[8]); + } + + if (argc >= 10) { + q.node_mask = strtoul(argv[9], NULL, 16); + HPRE_TST_PRT("denote node_id %d\n", q.node_mask); + } + + if (alg_op_type < MAX_RSA_ASYNC_TYPE && alg_op_type > HPRE_ALG_INVLD_TYPE) { + q.capa.alg = "rsa"; + } else if (alg_op_type < MAX_DH_TYPE && + alg_op_type > MAX_RSA_ASYNC_TYPE) { + q.capa.alg = "dh"; + } else { + HPRE_TST_PRT("op type err!\n"); + return -EINVAL; + } + ret = wd_request_queue(&q); + if (ret) { + HPRE_TST_PRT("request queue fail!\n"); + return ret; + } + HPRE_TST_PRT("Get a WD HPRE queue of %s successfully!\n", q.capa.alg); + memset(&dh_setup, 0, sizeof(dh_setup)); + memset(&setup, 0, sizeof(setup)); + if (alg_op_type < MAX_RSA_ASYNC_TYPE && mode == RSA_CRT_MD) { + setup.is_crt = 1; + } else if (alg_op_type < MAX_RSA_ASYNC_TYPE && mode == RSA_COM_MD) { + setup.is_crt = 0; + } else if (alg_op_type > MAX_RSA_ASYNC_TYPE && + alg_op_type < HPRE_MAX_OP_TYPE && mode == DH_COM_MD) { + dh_setup.is_g2 = 0; + } else if (alg_op_type > MAX_RSA_ASYNC_TYPE && + alg_op_type < HPRE_MAX_OP_TYPE && mode == DH_G2) { + dh_setup.is_g2 = 1; + } else { + HPRE_TST_PRT("op type or mode err!\n"); + ret = -ENOMEM; + goto release_q; + } + + struct wd_blkpool_setup wsetup; + memset(&wsetup, 0, sizeof(wsetup)); + if (!strncmp(q.capa.alg, "rsa", 3)) + wsetup.block_size = (key_bits >> 4) * 7; + else if (!strncmp(q.capa.alg, "dh", 2)) + wsetup.block_size = key_bits >> 2; + wsetup.block_num = block_num; + wsetup.align_size = 64; + + pool = wd_blkpool_create(&q, &wsetup); + if (!pool) { + HPRE_TST_PRT("%s(): create ctx pool fail!\n", __func__); + return -EINVAL; + } + + if (!strncmp(q.capa.alg, "rsa", 3)) { + setup.key_bits = key_bits; + + setup.br.alloc = (void *)wd_alloc_blk; + setup.br.free = (void *)wd_free_blk; + setup.br.iova_map = (void *)wd_blk_iova_map; + setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + setup.br.usr = pool; + ctx = wcrypto_create_rsa_ctx(&q, &setup); + if (!ctx) { + ret = -ENOMEM; + HPRE_TST_PRT("create rsa ctx fail!\n"); + goto release_q; + } + } else if (!strncmp(q.capa.alg, "dh", 2)) { + dh_setup.key_bits = key_bits; + + dh_setup.br.alloc = (void *)wd_alloc_blk; + dh_setup.br.free = (void *)wd_free_blk; + dh_setup.br.iova_map = (void *)wd_blk_iova_map; + dh_setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + dh_setup.br.usr = pool; + ctx = wcrypto_create_dh_ctx(&q, &dh_setup); + if (!ctx) { + ret = -ENOMEM; + HPRE_TST_PRT("create dh ctx fail!\n"); + goto release_q; + } + } + if (alg_op_type == RSA_KEY_GEN) { + /* As generate key, we take in_file for storing public key + * and out_file for storing private key. + */ +#ifdef RSA_OP_DEBUG + return hpre_test_rsa_op(alg_op_type, ctx, (__u8 *)in_file, + key_bits >> 3, (__u8 *)out_file, (__u8 *)key_file); +#else + HPRE_TST_PRT("hpre_test_rsa_op not supported currently!\n"); + return 0; +#endif + } else if (alg_op_type == DH_GEN) { + ret = hpre_dh_test(ctx, pool); + wcrypto_del_dh_ctx(ctx); + return ret; + } else if (alg_op_type == RSA_PUB_EN && (mode == RSA_CRT_MD || + mode == RSA_COM_MD)) { + read_size = pub_key_size = key_bits >> 2; + } else if (alg_op_type == RSA_PRV_DE && mode == RSA_CRT_MD) { + read_size = priv_key_size = (key_bits >> 4) * 5; + } else if (alg_op_type == RSA_PRV_DE && mode == RSA_COM_MD) { + read_size = priv_key_size = key_bits >> 2; + } else { + HPRE_TST_PRT("op=%d mode=%d CMD err!\n", alg_op_type, mode); + ret = -EINVAL; + goto release_q; + } + if (openssl_check && alg_op_type != RSA_PUB_EN) + key_info_size = read_size + (key_bits >> 2); + else + key_info_size = read_size; + + /* while we check the hw result, we need more info such as n and e */ + key = malloc(key_info_size); + if (!key) { + HPRE_TST_PRT("malloc key fail!\n"); + ret = -ENOMEM; + goto release_q; + } + ret = hpre_test_read_from_file(key, key_file, key_info_size); + if (ret < 0 || key_info_size != ret) { + HPRE_TST_PRT("Fail to get key from %s!\n", key_file); + HPRE_TST_PRT("Please input right RSA key!\n"); + goto release_q; + } + + /* Try to get the input file size */ + read_size = hpre_test_get_file_size(in_file); + if (read_size <= 0) { + HPRE_TST_PRT("%s file is not valid!\n", in_file); + goto release_q; + } + + in = malloc(read_size + (key_bits >> 3)); + if (!in) { + HPRE_TST_PRT("Fail to malloc mem for %s!\n", in_file); + goto release_q; + } + memset(in, 0, read_size + (key_bits >> 3)); + ret = hpre_test_read_from_file(in, in_file, read_size); + if (ret != read_size) { + HPRE_TST_PRT("Fail to get data from %s!\n", in_file); + goto release_q; + } + out = malloc(key_bits >> 3); + if (!out) { + HPRE_TST_PRT("Fail to malloc mem for output!\n"); + goto release_q; + } + memset(out, 0, key_bits >> 3); + + /* Initiated input Size */ + if (alg_op_type == RSA_PRV_DE) { + in_size = key_bits >> 3; + } else { + in_size = (key_bits >> 3) - HPRE_PADDING_SZ; + temp_in = malloc(key_bits >> 3); + if (!temp_in) { + HPRE_TST_PRT("Fail to malloc mem for temp in!\n"); + goto release_q; + } + memset(temp_in, 0, key_bits >> 3); + } + tp_in = in; + do { + /* While read_size is small the key size, it is finished */ + if (read_size - in_size > 0) { + op_size = in_size; + try_close = 0; + } else { + op_size = read_size; + try_close = 1; + } +#ifdef RSA_OP_DEBUG + if (alg_op_type == RSA_PUB_EN) { + memcpy(temp_in, tp_in, op_size); + ret = hpre_test_rsa_op(alg_op_type, ctx, temp_in, op_size, out, key); + } else { + ret = hpre_test_rsa_op(alg_op_type, ctx, tp_in, op_size, out, key); + } +#endif + if (ret < 0) { + HPRE_TST_PRT("HPRE operates failing!\n"); + goto release_q; + } + + ret = hpre_test_write_to_file(out, ret, out_file, + out_fd, try_close); + if (ret < 0) { + HPRE_TST_PRT("Fail to write output buffer to %s!\n", + out_file); + goto release_q; + } + if (key) { + free(key); + key = NULL; + } + if (try_close && openssl_check) { + if (alg_op_type == RSA_PUB_EN) + HPRE_TST_PRT("HPRE pub encrypt"\ + " %s to %s success!\n", in_file, out_file); + else + HPRE_TST_PRT("HPRE priv decrypt"\ + " %s to %s success!\n", in_file, out_file); + } else if (try_close) { + if (alg_op_type == RSA_PUB_EN) + HPRE_TST_PRT("HPRE pub encrypt"\ + " %s to %s finished!\n", in_file, out_file); + else + HPRE_TST_PRT("HPRE priv decrypt"\ + " %s to %s finished!\n", in_file, out_file); + } + out_fd = ret; + tp_in += op_size; + read_size -= op_size; + } while (!try_close); +release_q: + if (in) + free(in); + if (out) + free(out); + if (key) + free(key); + if (temp_in) + free(temp_in); + if (hpre_test_rsa) + RSA_free(hpre_test_rsa); + wcrypto_del_rsa_ctx(ctx); + wd_blkpool_destroy(pool); + wd_release_queue(&q); + + return ret; +} diff --git a/uadk/v1/test/hisi_sec_test/Makefile.am b/uadk/v1/test/hisi_sec_test/Makefile.am new file mode 100644 index 0000000..713fb0b --- /dev/null +++ b/uadk/v1/test/hisi_sec_test/Makefile.am @@ -0,0 +1,14 @@ +AM_CFLAGS=-Wall -O0 -fno-strict-aliasing -I$(top_srcdir) -I$(top_srcdir)/include -I$(srcdir) -pthread + +if WITH_OPENSSL_DIR +bin_PROGRAMS=test_hisi_sec + +test_hisi_sec_SOURCES=test_hisi_sec.c test_hisi_sec.h + +if WD_STATIC_DRV +test_hisi_sec_LDADD=../../../.libs/libwd.la $(with_openssl_dir)/libcrypto_wd.so +else +test_hisi_sec_LDADD=../../../.libs/libwd.so $(with_openssl_dir)/libcrypto_wd.so +endif + +endif diff --git a/uadk/v1/test/hisi_sec_test/test_hisi_sec.c b/uadk/v1/test/hisi_sec_test/test_hisi_sec.c new file mode 100644 index 0000000..be4ee9d --- /dev/null +++ b/uadk/v1/test/hisi_sec_test/test_hisi_sec.c @@ -0,0 +1,2372 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#include +#include +#include +#define __USE_GNU +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "test_hisi_sec.h" +#include "../../wd.h" +#include "../../wd_cipher.h" +#include "../../wd_aead.h" +#include "../../wd_digest.h" +#include "../../wd_bmm.h" +#include "../../wd_util.h" + +#define SEC_TST_PRT printf +#define TEST_MAX_THRD 128 +#define SQE_SIZE 128 +#define MAX_BLOCK_SZ 1024 * 8 +#define MAX_BLOCK_NM 128 +#define MAX_ALGO_PER_TYPE 13 + +typedef unsigned char u8; +typedef unsigned int u32; + +static int q_num = 1; +static int ctx_num_per_q = 1; +static long long g_total_perf = 0; +static long long total_recv_task; +enum alg_class g_algclass = CIPHER_CLASS; +enum cipher_op_type alg_op_type; + +pthread_mutex_t perf_mutex; + +struct test_sec_pthread_dt { + int cpu_id; + enum cipher_op_type op_type; + int thread_num; + void *pool; + void *q; + struct timeval start_tval; + u32 send_task_num; + u32 recv_task_num; +}; + +struct cipher_async_tag { + void *ctx; + int thread_id; + int cnt; + struct test_sec_pthread_dt *thread_info; +}; + +struct digest_async_tag { + void *ctx; + int thread_id; + int cnt; + struct test_sec_pthread_dt *thread_info; +}; + +/** + * struct test_sec_option - Define the test sec app option list. + * @algclass: 0:cipher 1:digest + * @algtype: The sub alg type, reference func get_cipher_resource. + * @syncmode: 0:sync mode 1:async mode + */ +struct test_sec_option { + u32 algclass; + u32 algtype; + u32 t; + u32 optype; + u32 pktlen; + u32 keylen; + u32 ivlen; + u32 timeclass; + u32 times; + u32 syncmode; + u32 dump; +}; + +/* OpenSSL Skcipher APIS */ +static long long t_times = 1000; +static int t_seconds = 0; +static int pktlen = 1024; +static int g_testalg = 0; +static int g_thread_num = 0; +static int g_dump = 0; + +static pthread_t system_test_thrds[TEST_MAX_THRD]; +static struct test_sec_pthread_dt test_thrds_data[TEST_MAX_THRD]; +static volatile int asyn_thread_exit = 0; +static u32 g_keylen = 16; +static u32 g_ivlen = 16; + +char *skcipher_names[MAX_ALGO_PER_TYPE] = + {"ecb(aes)", "cbc(aes)", "xts(aes)", "ofb(aes)", "cfb(aes)", "ecb(des3_ede)", + "cbc(des3_ede)", "cbc(sm4)", "xts(sm4)", "ofb(sm4)", "cfb(sm4)", "ecb(sm4)", NULL,}; +static inline int _get_cpu_id(int thr, __u64 core_mask) +{ + __u64 i; + int cnt = 0; + + for (i = 1; i < 64; i++) { + if (core_mask & (0x1ull << i)) { + if (thr == cnt) + return i; + cnt++; + } + } + + return 0; +} + +static inline int _get_one_bits(__u64 val) +{ + int count = 0; + + while (val) { + if (val % 2 == 1) + count++; + val = val / 2; + } + + return count; +} + +static bool is_exit(struct test_sec_pthread_dt *pdata) +{ + struct timeval cur_tval; + float time_used; + + gettimeofday(&cur_tval, NULL); + time_used = (float)((cur_tval.tv_sec - pdata->start_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - pdata->start_tval.tv_usec); + if (t_seconds) + return time_used >= t_seconds * 1000000; + else if (t_times) + return pdata->send_task_num >= t_times; + + return false; +} + +void hexdump(char *buf, int num) +{ + int i; + + if (g_dump) { + for (i = 0; i < num; i++) { + printf("\\%02X", buf[i]); + if ((i + 1) % 8 == 0) + printf("\n"); + } + printf("\n"); + } + + return; +} + +int get_resource(struct cipher_testvec **alg_tv, int* alg, int* mode) +{ + struct cipher_testvec *tv; + int alg_type; + int mode_type; + + switch (g_testalg) { + case 0: + alg_type = WCRYPTO_CIPHER_AES; + mode_type = WCRYPTO_CIPHER_ECB; + SEC_TST_PRT("test alg: %s\n", "ecb(aes)"); + switch (g_keylen) { + case AES_KEYSIZE_128: + tv = &aes_ecb_tv_template_128[0]; + break; + case AES_KEYSIZE_192: + tv = &aes_ecb_tv_template_192[0]; + break; + case AES_KEYSIZE_256: + tv = &aes_ecb_tv_template_256[0]; + break; + default: + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + break; + case 1: + alg_type = WCRYPTO_CIPHER_AES; + mode_type = WCRYPTO_CIPHER_CBC; + SEC_TST_PRT("test alg: %s\n", "cbc(aes)"); + switch (g_keylen) { + case AES_KEYSIZE_128: + tv = &aes_cbc_tv_template_128[0]; + break; + case AES_KEYSIZE_192: + tv = &aes_cbc_tv_template_192[0]; + break; + case AES_KEYSIZE_256: + tv = &aes_cbc_tv_template_256[0]; + break; + default: + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + break; + case 2: + alg_type = WCRYPTO_CIPHER_AES; + mode_type = WCRYPTO_CIPHER_XTS; + SEC_TST_PRT("test alg: %s\n", "xts(aes)"); + switch (g_keylen / 2) { + case AES_KEYSIZE_128: + tv = &aes_xts_tv_template_256[0]; + break; + case AES_KEYSIZE_256: + tv = &aes_xts_tv_template_512[0]; + break; + default: + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + break; + case 3: + alg_type = WCRYPTO_CIPHER_AES; + mode_type = WCRYPTO_CIPHER_OFB; + SEC_TST_PRT("test alg: %s\n", "ofb(aes)"); + switch (g_keylen) { + case AES_KEYSIZE_128: + tv = &aes_ofb_tv_template_128[0]; + break; + case AES_KEYSIZE_192: + tv = &aes_ofb_tv_template_192[0]; + break; + case AES_KEYSIZE_256: + tv = &aes_ofb_tv_template_256[0]; + break; + default: + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + break; + case 4: + alg_type = WCRYPTO_CIPHER_AES; + mode_type = WCRYPTO_CIPHER_CFB; + SEC_TST_PRT("test alg: %s\n", "cfb(aes)"); + switch (g_keylen) { + case AES_KEYSIZE_128: + tv = &aes_cfb_tv_template_128[0]; + break; + case AES_KEYSIZE_192: + tv = &aes_cfb_tv_template_192[0]; + break; + case AES_KEYSIZE_256: + tv = &aes_cfb_tv_template_256[0]; + break; + default: + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + break; + case 5: + alg_type = WCRYPTO_CIPHER_AES; + mode_type = WCRYPTO_CIPHER_CTR; + SEC_TST_PRT("test alg: %s\n", "ctr(aes)"); + switch (g_keylen) { + case AES_KEYSIZE_128: + tv = &aes_ctr_tv_template_128[0]; + break; + case AES_KEYSIZE_192: + tv = &aes_ctr_tv_template_192[0]; + break; + case AES_KEYSIZE_256: + tv = &aes_ctr_tv_template_256[0]; + break; + default: + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + break; + case 6: + alg_type = WCRYPTO_CIPHER_3DES; + mode_type = WCRYPTO_CIPHER_ECB; + SEC_TST_PRT("test alg: %s\n", "ecb(des3)"); + if (g_keylen == 16) + tv = &des3_ecb_tv_template_128[0]; + else if (g_keylen == 24) + tv = &des3_ecb_tv_template_192[0]; + else { + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + break; + case 7: + alg_type = WCRYPTO_CIPHER_3DES; + mode_type = WCRYPTO_CIPHER_CBC; + SEC_TST_PRT("test alg: %s\n", "cbc(des3)"); + if (g_keylen == 16) + tv = &des3_cbc_tv_template_128[0]; + else if (g_keylen == 24) + tv = &des3_cbc_tv_template_192[0]; + else { + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + break; + case 8: + alg_type = WCRYPTO_CIPHER_SM4; + mode_type = WCRYPTO_CIPHER_CBC; + SEC_TST_PRT("test alg: %s\n", "cbc(sm4)"); + if (g_keylen != 16) { + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + tv = &sm4_cbc_tv_template[0]; + break; + case 9: + alg_type = WCRYPTO_CIPHER_SM4; + mode_type = WCRYPTO_CIPHER_XTS; + SEC_TST_PRT("test alg: %s\n", "xts(sm4)"); + if (g_keylen != 32) { + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + tv = &sm4_xts_tv_template[0]; + break; + case 10: + alg_type = WCRYPTO_CIPHER_SM4; + mode_type = WCRYPTO_CIPHER_OFB; + SEC_TST_PRT("test alg: %s\n", "ofb(sm4)"); + if (g_keylen != 16) { + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + tv = &sm4_ofb_tv_template_128[0]; + break; + case 11: + alg_type = WCRYPTO_CIPHER_SM4; + mode_type = WCRYPTO_CIPHER_CFB; + SEC_TST_PRT("test alg: %s\n", "cfb(sm4)"); + if (g_keylen != 16) { + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + tv = &sm4_cfb_tv_template_128[0]; + break; + case 12: + alg_type = WCRYPTO_CIPHER_SM4; + mode_type = WCRYPTO_CIPHER_CTR; + SEC_TST_PRT("test alg: %s\n", "ctr(sm4)"); + if (g_keylen != 16) { + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + tv = &sm4_ctr_tv_template_128[0]; + break; + case 13: + alg_type = WCRYPTO_CIPHER_SM4; + mode_type = WCRYPTO_CIPHER_ECB; + SEC_TST_PRT("test alg: %s\n", "ecb(sm4)"); + if (g_keylen != 16) { + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + tv = &sm4_ecb_tv_template_128[0]; + break; + default: + SEC_TST_PRT("keylenth error, default test alg: %s\n", "ecb(aes)"); + return -EINVAL; + } + *alg = alg_type; + *mode = mode_type; + *alg_tv = tv; + + return 0; +} + +int get_aead_resource(struct aead_testvec **alg_tv, + int* alg, int* mode, int* dalg, int* dmode) +{ + struct aead_testvec *tv; + int alg_type = 0; + int mode_type = 0; + int dalg_type = 0; + int dmode_type = 0; + + switch (g_testalg) { + case 0: + alg_type = WCRYPTO_CIPHER_AES; + mode_type = WCRYPTO_CIPHER_CCM; + SEC_TST_PRT("test alg: %s\n", "ccm(aes)"); + switch (g_keylen) { + case AES_KEYSIZE_128: + tv = &aes_ccm_tv_template_128[0]; + break; + case AES_KEYSIZE_192: + tv = &aes_ccm_tv_template_192[0]; + break; + case AES_KEYSIZE_256: + tv = &aes_ccm_tv_template_256[0]; + break; + default: + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + break; + case 1: + alg_type = WCRYPTO_CIPHER_AES; + mode_type = WCRYPTO_CIPHER_GCM; + SEC_TST_PRT("test alg: %s\n", "gcm(aes)"); + switch (g_keylen) { + case AES_KEYSIZE_128: + tv = &aes_gcm_tv_template_128[0]; + break; + case AES_KEYSIZE_192: + tv = &aes_gcm_tv_template_192[0]; + break; + case AES_KEYSIZE_256: + tv = &aes_gcm_tv_template_256[0]; + break; + default: + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + break; + case 2: + alg_type = WCRYPTO_CIPHER_AES; + mode_type = WCRYPTO_CIPHER_CBC; + dalg_type = WCRYPTO_SHA256; + dmode_type = WCRYPTO_DIGEST_HMAC; + SEC_TST_PRT("test alg: %s\n", "hmac(sha256),cbc(aes)"); + tv = &hmac_sha256_aes_cbc_tv_temp[0]; + break; + case 3: + alg_type = WCRYPTO_CIPHER_SM4; + mode_type = WCRYPTO_CIPHER_CCM; + SEC_TST_PRT("test alg: %s\n", "ccm(sm4)"); + if (g_keylen != 16) { + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + tv = &sm4_ccm_tv_template_128[0]; + break; + case 4: + alg_type = WCRYPTO_CIPHER_SM4; + mode_type = WCRYPTO_CIPHER_GCM; + SEC_TST_PRT("test alg: %s\n", "gcm(sm4)"); + if (g_keylen != 16) { + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + tv = &sm4_gcm_tv_template_128[0]; + break; + default: + SEC_TST_PRT("keylenth error, default test alg: %s\n", "ccm(aes)"); + return -EINVAL; + } + *alg = alg_type; + *mode = mode_type; + *dalg = dalg_type; + *dmode = dmode_type; + *alg_tv = tv; + + return 0; +} + +int sec_sync_test_set_iv(struct test_sec_pthread_dt *pdata, + struct wcrypto_cipher_op_data *opdata, struct cipher_testvec *tv) +{ + int ivlen; + + if (!tv->iv) + return -1; + + ivlen = strlen(tv->iv); + if (ivlen != AES_KEYSIZE_128 && ivlen != (AES_KEYSIZE_128 >> 1)) + ivlen = AES_KEYSIZE_128; + + tv->ivlen = ivlen; + + memset(opdata->iv, 0, tv->ivlen); + memcpy(opdata->iv, tv->iv, tv->ivlen); + + opdata->iv_bytes = tv->ivlen; + SEC_TST_PRT("dump set input IV! IV lenght:%d\n", ivlen); + hexdump(opdata->iv, opdata->iv_bytes); + + return 0; +} + +int sec_sync_func_test(struct test_sec_pthread_dt *pdata) +{ + int thread_id = (int)syscall(__NR_gettid); + struct wcrypto_cipher_ctx_setup setup; + struct wcrypto_cipher_op_data *opdata = malloc(sizeof(struct wcrypto_cipher_op_data)); + struct wd_queue *q = pdata->q; + struct timeval cur_tval; + struct cipher_testvec *tv; + float time_used, speed; + unsigned long Perf = 0; + int pid = getpid(); + void *ctx = NULL; + void *tag = NULL; + int ret; + + memset(&setup, 0, sizeof(setup)); + memset(opdata, 0, sizeof(struct wcrypto_cipher_op_data)); + + setup.alg = WCRYPTO_CIPHER_AES; + setup.mode = WCRYPTO_CIPHER_CBC; + setup.br.alloc = (void *)wd_alloc_blk; + setup.br.free = (void *)wd_free_blk; + setup.br.iova_map = (void *)wd_blk_iova_map; + setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + setup.br.get_bufsize = (void *)wd_blksize; + setup.br.usr = pdata->pool; + + ret = get_resource(&tv, (int *)&setup.alg, (int *)&setup.mode); + if (ret) + return -EINVAL; + + ctx = wcrypto_create_cipher_ctx(q, &setup); + if (!ctx) { + SEC_TST_PRT("Proc-%d, %d-TD:create %s ctx fail!\n", + pid, thread_id, q->capa.alg); + ret = -EINVAL; + return ret; + } + + hexdump(tv->key, tv->klen); + + ret = wcrypto_set_cipher_key(ctx, (__u8*)tv->key, (__u16)tv->klen); + if (ret) { + SEC_TST_PRT("set key fail!\n"); + goto fail_release; + } + + if (q->capa.priv.direction == 0) { + opdata->op_type = WCRYPTO_CIPHER_ENCRYPTION; + } else { + opdata->op_type = WCRYPTO_CIPHER_DECRYPTION; + } + opdata->in = wd_alloc_blk(pdata->pool); + if (!opdata->in) { + SEC_TST_PRT("alloc in buffer fail!\n"); + goto fail_release; + } + + memset(opdata->in, 0, tv->len); + if (q->capa.priv.direction == 0) { + memcpy(opdata->in, tv->ptext, tv->len); + if (strlen(tv->ptext) > pktlen) { + opdata->in_bytes = tv->len; + } else { + opdata->in_bytes = pktlen; + } + } else { + memcpy(opdata->in, tv->ctext, tv->len); + if (strlen(tv->ctext) > pktlen) { + opdata->in_bytes = tv->len; + } else { + opdata->in_bytes = pktlen; + } + } + + SEC_TST_PRT("cipher len:%d\n", opdata->in_bytes); + + hexdump(opdata->in, opdata->in_bytes); + + opdata->priv = NULL; + opdata->out = wd_alloc_blk(pdata->pool); + if (!opdata->out) { + SEC_TST_PRT("alloc out buffer fail!\n"); + goto fail_release; + } + opdata->out_bytes = opdata->in_bytes; + //set iv + opdata->iv = wd_alloc_blk(pdata->pool); + if (!opdata->iv) { + SEC_TST_PRT("alloc iv buffer fail!\n"); + goto fail_release; + } + + sec_sync_test_set_iv(pdata, opdata, tv); + do { + ret = wcrypto_do_cipher(ctx, opdata, tag); + pdata->send_task_num++; +#ifdef DEBUG + if (pdata->send_task_num == 1) { + SEC_TST_PRT("dump output!\n"); + hexdump(opdata->out, opdata->out_bytes); + } +#endif + } while(!is_exit(pdata)); + + gettimeofday(&cur_tval, NULL); + time_used = (float)((cur_tval.tv_sec - pdata->start_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - pdata->start_tval.tv_usec); + SEC_TST_PRT("time_used:%0.0f us, send task num:%d\n", time_used, pdata->send_task_num++); + if (t_seconds) { + speed = pdata->send_task_num / time_used * 1000000; + Perf = speed * pktlen / 1024; //B->KB + pthread_mutex_lock(&perf_mutex); + g_total_perf += Perf; + pthread_mutex_unlock(&perf_mutex); + SEC_TST_PRT("Pro-%d, thread_id-%d, speed:%0.3f ops, Perf: %ld KB/s\n", pid, + thread_id, speed, Perf); + } else if (t_times) { + speed = 1 / (time_used / t_times) * 1000000; + Perf = speed * pktlen / 1024; //B->KB + pthread_mutex_lock(&perf_mutex); + g_total_perf += Perf; + pthread_mutex_unlock(&perf_mutex); + SEC_TST_PRT("Pro-%d, thread_id-%d, speed:%0.3f ops, Perf: %ld KB/s\n", pid, + thread_id, speed, Perf); + } + +fail_release: + if (opdata->in) + wd_free_blk(pdata->pool, opdata->in); + if (opdata->iv) + wd_free_blk(pdata->pool, opdata->iv); + if (opdata->out) + wd_free_blk(pdata->pool, opdata->out); + if (ctx) + wcrypto_del_cipher_ctx(ctx); + free(opdata); + + return ret; +} + +int get_digest_resource(struct hash_testvec **alg_tv, int* alg, int* mode) +{ + struct hash_testvec *tmp_tv; + struct hash_testvec *tv = NULL; + int alg_type; + int mode_type; + + switch (g_testalg) { + case 0: + switch (alg_op_type) { + case 0: + mode_type = WCRYPTO_DIGEST_NORMAL; + SEC_TST_PRT("test alg: %s\n", "normal(sm3)"); + tv = &sm3_tv_template[0]; + break; + case 1: + mode_type = WCRYPTO_DIGEST_HMAC; + SEC_TST_PRT("test alg: %s\n", "hmac(sm3)"); + tv = &hmac_sm3_tv_template[0]; + break; + } + tv->dsize = 32; + alg_type = WCRYPTO_SM3; + break; + case 1: + switch (alg_op_type) { + case 0: + mode_type = WCRYPTO_DIGEST_NORMAL; + SEC_TST_PRT("test alg: %s\n", "normal(md5)"); + tv = &md5_tv_template[0]; + break; + case 1: + mode_type = WCRYPTO_DIGEST_HMAC; + SEC_TST_PRT("test alg: %s\n", "hmac(md5)"); + tv = &hmac_md5_tv_template[0]; + break; + } + tv->dsize = 16; + alg_type = WCRYPTO_MD5; + break; + case 2: + switch (alg_op_type) { + case 0: + mode_type = WCRYPTO_DIGEST_NORMAL; + SEC_TST_PRT("test alg: %s\n", "normal(sha1)"); + tv = &sha1_tv_template[0]; + break; + case 1: + mode_type = WCRYPTO_DIGEST_HMAC; + SEC_TST_PRT("test alg: %s\n", "hmac(sha1)"); + tv = &hmac_sha1_tv_template[0]; + break; + } + tv->dsize = 20; + alg_type = WCRYPTO_SHA1; + break; + case 3: + switch (alg_op_type) { + case 0: + mode_type = WCRYPTO_DIGEST_NORMAL; + SEC_TST_PRT("test alg: %s\n", "normal(sha256)"); + tv = &sha256_tv_template[0]; + break; + case 1: + mode_type = WCRYPTO_DIGEST_HMAC; + SEC_TST_PRT("test alg: %s\n", "hmac(sha256)"); + tv = &hmac_sha256_tv_template[0]; + break; + } + tv->dsize = 32; + alg_type = WCRYPTO_SHA256; + break; + case 4: + switch (alg_op_type) { + case 0: + mode_type = WCRYPTO_DIGEST_NORMAL; + SEC_TST_PRT("test alg: %s\n", "normal(sha224)"); + tv = &sha224_tv_template[0]; + break; + case 1: + mode_type = WCRYPTO_DIGEST_HMAC; + SEC_TST_PRT("test alg: %s\n", "hmac(sha224)"); + tv = &hmac_sha224_tv_template[0]; + break; + } + tv->dsize = 28; + alg_type = WCRYPTO_SHA224; + break; + case 5: + switch (alg_op_type) { + case 0: + mode_type = WCRYPTO_DIGEST_NORMAL; + SEC_TST_PRT("test alg: %s\n", "normal(sha384)"); + tv = &sha384_tv_template[0]; + break; + case 1: + mode_type = WCRYPTO_DIGEST_HMAC; + SEC_TST_PRT("test alg: %s\n", "hmac(sha384)"); + tv = &hmac_sha384_tv_template[0]; + break; + } + tv->dsize = 48; + alg_type = WCRYPTO_SHA384; + break; + case 6: + switch (alg_op_type) { + case 0: + mode_type = WCRYPTO_DIGEST_NORMAL; + SEC_TST_PRT("test alg: %s\n", "normal(sha512)"); + tv = &sha512_tv_template[0]; + break; + case 1: + mode_type = WCRYPTO_DIGEST_HMAC; + SEC_TST_PRT("test alg: %s\n", "hmac(sha512)"); + tv = &hmac_sha512_tv_template[0]; + break; + } + tv->dsize = 64; + alg_type = WCRYPTO_SHA512; + break; + case 7: + switch (alg_op_type) { + case 0: + mode_type = WCRYPTO_DIGEST_NORMAL; + SEC_TST_PRT("test alg: %s\n", "normal(sha512_224)"); + tv = &sha512_224_tv_template[0]; + break; + case 1: + mode_type = WCRYPTO_DIGEST_HMAC; + SEC_TST_PRT("test alg: %s\n", "hmac(sha512_224"); + tv = &hmac_sha512_224_tv_template[0]; + break; + } + tv->dsize = 28; + alg_type = WCRYPTO_SHA512_224; + break; + case 8: + switch (alg_op_type) { + case 0: + mode_type = WCRYPTO_DIGEST_NORMAL; + SEC_TST_PRT("test alg: %s\n", "normal(sha512_256)"); + tv = &sha512_256_tv_template[0]; + break; + case 1: + mode_type = WCRYPTO_DIGEST_HMAC; + SEC_TST_PRT("test alg: %s\n", "hmac(sha512_256)"); + tv = &hmac_sha512_256_tv_template[0]; + break; + } + tv->dsize = 32; + alg_type = WCRYPTO_SHA512_256; + break; + default: + SEC_TST_PRT("keylenth error, default test alg: %s\n", "normal(sm3)"); + return -EINVAL; + } + if (g_ivlen == 1) { + tmp_tv = tv; + tv = &long_hash_tv_template[0]; + tv->dsize = tmp_tv->dsize; + } else if (g_ivlen == 2) { + tmp_tv = tv; + tv = &hmac_abnormal1024_tv_template[0]; + tv->dsize = tmp_tv->dsize; + } else if (g_ivlen == 3) { + tmp_tv = tv; + tv = &hmac_abnormal512_tv_template[0]; + tv->dsize = tmp_tv->dsize; + } + + *alg = alg_type; + *mode = mode_type; + *alg_tv = tv; + + return 0; +} + +int wd_digests_doimpl(void *ctx, struct wcrypto_digest_op_data *opdata, u32 *send_count) +{ + int ret; + int trycount = 0; + *send_count = 0; +again: + ret = wcrypto_burst_digest(ctx, &opdata, NULL, 1); + if (ret == 0) { + if (trycount <= 5) { // try 5 times + SEC_TST_PRT("do digest busy, retry again!"); + trycount++; + goto again; + } else { + SEC_TST_PRT("do digest failed..\n!"); + return -1; + } + } else if (ret < 0) { + SEC_TST_PRT("do digest failed ret < 0!"); + return -1; + } + + (*send_count)++; + return 0; +} + +int alloc_from_pool(struct wcrypto_digest_op_data *opdata, struct test_sec_pthread_dt *pdata) +{ + opdata->in = wd_alloc_blk(pdata->pool); + if (!opdata->in) { + SEC_TST_PRT("alloc in buffer fail!\n"); + return -1; + } + + opdata->out = wd_alloc_blk(pdata->pool); + if (!opdata->out) { + SEC_TST_PRT("alloc out buffer fail!\n"); + return -1; + } + + return 0; +} + +int sec_sync_digest_test(struct test_sec_pthread_dt *pdata) +{ + struct wcrypto_digest_op_data *opdata = malloc(sizeof(struct wcrypto_digest_op_data)); + enum sec_digest_state state = SEC_DIGEST_INIT; + int thread_id = (int)syscall(__NR_gettid); + struct wcrypto_digest_ctx_setup setup; + struct wd_queue *q = pdata->q; + struct timeval cur_tval; + struct hash_testvec *tv; + float time_used, speed; + unsigned long Perf = 0; + int pid = getpid(); + void *ctx = NULL; + int data_len; + int ret; + + memset(&setup, 0, sizeof(setup)); + memset(opdata, 0, sizeof(struct wcrypto_digest_op_data)); + + setup.alg = WCRYPTO_SM3; + setup.mode = WCRYPTO_DIGEST_NORMAL; + setup.br.alloc = (void *)wd_alloc_blk; + setup.br.free = (void *)wd_free_blk; + setup.br.iova_map = (void *)wd_blk_iova_map; + setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + setup.br.get_bufsize = (void *)wd_blksize; + setup.br.usr = pdata->pool; + + ret = get_digest_resource(&tv, (int *)&setup.alg, (int *)&setup.mode); + if (ret) + return -EINVAL; + + ctx = wcrypto_create_digest_ctx(q, &setup); + if (!ctx) { + SEC_TST_PRT("Proc-%d, %d-TD:create %s ctx fail!\n", + pid, thread_id, q->capa.alg); + ret = -EINVAL; + return ret; + } else { + SEC_TST_PRT("Proc-%d, %d-TD:create %s ctx success!\n", + pid, thread_id, q->capa.alg); + } + if (setup.mode == WCRYPTO_DIGEST_HMAC) { + hexdump((char *)tv->key, tv->ksize); + ret = wcrypto_set_digest_key(ctx, (__u8*)tv->key, (__u16)tv->ksize); + if (ret) { + SEC_TST_PRT("set key fail!\n"); + goto fail_release; + } + } + + ret = alloc_from_pool(opdata, pdata); + if(ret) + goto fail_release; + + memset(opdata->in, 0, tv->psize); + memcpy(opdata->in, tv->plaintext, tv->psize); + // opdata->in_bytes = tv->psize; + SEC_TST_PRT("digest len:%d\n", opdata->in_bytes); + hexdump(tv->plaintext, tv->psize); + opdata->priv = NULL; + opdata->out_bytes = tv->dsize; + memset(opdata->out, 0, opdata->out_bytes); + opdata->has_next = 0; + + data_len = tv->psize; + while (1) { + if (state == SEC_DIGEST_INIT) { + state = SEC_DIGEST_FIRST_UPDATING; + } else if (state == SEC_DIGEST_FIRST_UPDATING) + state = SEC_DIGEST_DOING; + + if (data_len > 256) { + opdata->in_bytes = 256; + data_len -= 256; + } else if (data_len <= 0) { + break; + } else { + state = SEC_DIGEST_FINAL; + opdata->in_bytes = data_len; + } + SEC_TST_PRT("data_len:%d in_bytes:%d\n", data_len, opdata->in_bytes); + hexdump(opdata->in, opdata->in_bytes); + opdata->has_next = (state == SEC_DIGEST_FINAL) ? false : true; + ret = wd_digests_doimpl(ctx, opdata, &pdata->send_task_num); + if (ret) + goto fail_release; + + if (state == SEC_DIGEST_FINAL) + break; + else + opdata->in += 256; + } + SEC_TST_PRT("digest out data:\n"); + hexdump(opdata->out, tv->dsize); + + gettimeofday(&cur_tval, NULL); + time_used = (float)((cur_tval.tv_sec - pdata->start_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - pdata->start_tval.tv_usec); + SEC_TST_PRT("time_used:%0.0f us, send task num:%d\n", time_used, pdata->send_task_num++); + speed = pdata->send_task_num / time_used * 1000000; + Perf = speed * pktlen / 1024; //B->KB + SEC_TST_PRT("Pro-%d, thread_id-%d, speed:%0.3f ops, Perf: %ld KB/s\n", pid, + thread_id, speed, Perf); + +fail_release: + if (opdata->in) + wd_free_blk(pdata->pool, opdata->in); + if (opdata->out) + wd_free_blk(pdata->pool, opdata->out); + if (ctx) + wcrypto_del_digest_ctx(ctx); + free(opdata); + + return ret; +} + +void *_sec_sys_test_thread(void *data) +{ + if (!data) { + SEC_TST_PRT("test data input error!\n"); + return NULL; + } + struct test_sec_pthread_dt *pdata = data; + + if (!g_algclass) + sec_sync_func_test(pdata); + else + sec_sync_digest_test(pdata); + + return NULL; +} + +static int sec_cipher_sync_test(int thread_num, __u64 lcore_mask, + __u64 hcore_mask, enum cipher_op_type op_type, + char *dev_path, unsigned int node_mask) +{ + struct wd_blkpool_setup setup; + int i, ret, cnt = 0, j; + int block_num = 128; + struct wd_queue *q; + void **pool; + int qidx; + + pthread_mutex_init(&perf_mutex, NULL); + q = malloc(q_num * sizeof(struct wd_queue)); + if (!q) { + SEC_TST_PRT("malloc q memory fail!\n"); + return -ENOMEM; + } + + memset(q, 0, q_num * sizeof(struct wd_queue)); + + /* create pool for every queue */ + pool = malloc(q_num * sizeof(pool)); + if (!pool) { + SEC_TST_PRT("malloc pool memory fail!\n"); + return -ENOMEM; + } + + for (j = 0; j < q_num; j++) { + if (!g_algclass){ + q[j].capa.alg = "cipher"; + if (op_type == ENCRYPTION) { + q[j].capa.priv.direction = 0; //0 is ENC, 1 is DEC + } else { + q[j].capa.priv.direction = 1; + } + } else { + q[j].capa.alg = "digest"; + } + + if (dev_path) { + strncpy(q[j].dev_path, dev_path, sizeof(q[j].dev_path)); + } + //q[j].node_mask = node_mask; + + ret = wd_request_queue(&q[j]); + if (ret) { + SEC_TST_PRT("request queue %d fail!\n", j); + return ret; + } + memset(&setup, 0, sizeof(setup)); + setup.block_size = MAX_BLOCK_SZ; //set pool inv + key + in + out + setup.block_num = MAX_BLOCK_NM; + setup.align_size = SQE_SIZE; + + SEC_TST_PRT("create pool memory: %lld\n", MAX_BLOCK_NM * setup.block_size); + pool[j] = wd_blkpool_create(&q[j], &setup); + if (!pool[j]) { + SEC_TST_PRT("%s(): create %dth pool fail!\n", __func__, j); + return -ENOMEM; + } + } + + if (_get_one_bits(lcore_mask) == 0 && + _get_one_bits(hcore_mask) == 0) + cnt = thread_num; + else + cnt = 1; + + for (i = 0 ; i < cnt; i++) { + qidx = i / ctx_num_per_q; + test_thrds_data[i].pool = pool[qidx]; + test_thrds_data[i].q = &q[qidx]; + test_thrds_data[i].thread_num = thread_num; + test_thrds_data[i].op_type = op_type; + test_thrds_data[i].cpu_id = _get_cpu_id(i, lcore_mask); + + gettimeofday(&test_thrds_data[i].start_tval, NULL); + + ret = pthread_create(&system_test_thrds[i], NULL, + _sec_sys_test_thread, &test_thrds_data[i]); + if (ret) { + SEC_TST_PRT("Create %dth thread fail!\n", i); + return ret; + } + } + + for (i = 0; i < thread_num; i++) { + ret = pthread_join(system_test_thrds[i], NULL); + if (ret) { + SEC_TST_PRT("Join %dth thread fail!\n", i); + return ret; + } + } + + SEC_TST_PRT("%d-threads, total Perf: %lld KB/s\n", thread_num, g_total_perf); + + return 0; +} + +static void *_cipher_async_poll_test_thread(void *data) +{ + struct test_sec_pthread_dt *pdata = data; + struct wd_queue *q = pdata->q; + int ret; + + while (1) { + if (!g_algclass) + ret = wcrypto_cipher_poll(q, 1); + else + ret = wcrypto_digest_poll(q, 1); + if (ret < 0) { + break; + } + + if (asyn_thread_exit) + break; + } + + return NULL; +} + +void _cipher_cb(void *message, void *cipher_tag) +{ + struct cipher_async_tag *tag = cipher_tag; + struct test_sec_pthread_dt *thread_info = tag->thread_info; + thread_info->recv_task_num++; +} + +int sec_async_func_test(struct test_sec_pthread_dt *pdata) +{ + int thread_id = (int)syscall(__NR_gettid); + struct wcrypto_cipher_ctx_setup setup; + struct wcrypto_cipher_op_data opdata; + struct cipher_async_tag *tag = NULL; //async + struct wd_queue *q = pdata->q; + struct cipher_testvec *tv; + struct timeval cur_tval; + float time_used, speed; + unsigned long Perf = 0; + int pid = getpid(); + void *ctx = NULL; + int i = 0; + int ret; + + memset(&setup, 0, sizeof(setup)); + memset(&opdata, 0, sizeof(opdata)); + + setup.alg = WCRYPTO_CIPHER_AES; + setup.mode = WCRYPTO_CIPHER_CBC; + + ret = get_resource(&tv, (int *)&setup.alg, (int *)&setup.mode); + if (ret) + return -EINVAL; + + setup.cb = (void *)_cipher_cb; //call back functions of user + setup.br.alloc = (void *)wd_alloc_blk; + setup.br.free = (void *)wd_free_blk; + setup.br.iova_map = (void *)wd_blk_iova_map; + setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + setup.br.get_bufsize = (void *)wd_blksize; + setup.br.usr = pdata->pool; + + ctx = wcrypto_create_cipher_ctx(q, &setup); + if (!ctx) { + SEC_TST_PRT("Proc-%d, %d-TD:create %s ctx fail!\n", + pid, thread_id, q->capa.alg); + ret = -EINVAL; + return ret; + } + + // hexdump((char *)tv->key, tv->klen); + ret = wcrypto_set_cipher_key(ctx, (__u8*)tv->key, (__u16)tv->klen); + if (ret) { + SEC_TST_PRT("set key fail!\n"); + goto fail_release; + } + if (q->capa.priv.direction == 0) { + opdata.op_type = WCRYPTO_CIPHER_ENCRYPTION; + } else { + opdata.op_type = WCRYPTO_CIPHER_DECRYPTION; + } + opdata.in = wd_alloc_blk(pdata->pool); + if (!opdata.in) { + SEC_TST_PRT("alloc in buffer fail!\n"); + goto fail_release; + } + if (q->capa.priv.direction == 0) { + memcpy(opdata.in, tv->ptext, strlen(tv->ptext)); + if (strlen(tv->ptext) > pktlen) { + opdata.in_bytes = strlen(tv->ptext); + } else { + opdata.in_bytes = pktlen; + } + } else { + memcpy(opdata.in, tv->ctext, strlen(tv->ctext)); + if (strlen(tv->ctext) > pktlen) { + opdata.in_bytes = strlen(tv->ctext); + } else { + opdata.in_bytes = pktlen; + } + } + + opdata.priv = NULL; + + printf("ptext:\n"); + hexdump(opdata.in, opdata.in_bytes); + + opdata.out = wd_alloc_blk(pdata->pool); + opdata.out_bytes = opdata.in_bytes; + if (!opdata.out) { + SEC_TST_PRT("alloc out buffer fail!\n"); + goto fail_release; + } + + opdata.iv = wd_alloc_blk(pdata->pool); + if (!opdata.iv) { + SEC_TST_PRT("alloc iv buffer fail!\n"); + goto fail_release; + } + sec_sync_test_set_iv(pdata, &opdata, tv); + + do { + tag = malloc(sizeof(struct cipher_async_tag)); // set the user tag + if (!tag) + goto fail_release; + tag->ctx = ctx; + tag->thread_id = thread_id; + tag->cnt = i; + tag->thread_info = pdata; + try_do_again: + ret = wcrypto_do_cipher(ctx, &opdata, tag); + if (ret == -WD_EBUSY) { + usleep(200); + SEC_TST_PRT("wcrypto_do_cipher busy!\n"); + goto try_do_again; + } + pdata->send_task_num++; + i++; + } while(!is_exit(pdata)); + + gettimeofday(&cur_tval, NULL); + time_used = (float)((cur_tval.tv_sec - pdata->start_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - pdata->start_tval.tv_usec); + SEC_TST_PRT("time_used:%0.0f us, send task num:%d, recv task num: %d\n", time_used, + pdata->send_task_num++, pdata->recv_task_num); + if (t_seconds) { + speed = pdata->send_task_num / time_used * 1000000; + Perf = speed * pktlen / 1024; //B->KB + pthread_mutex_lock(&perf_mutex); + g_total_perf += Perf; + total_recv_task += pdata->recv_task_num; + pthread_mutex_unlock(&perf_mutex); + SEC_TST_PRT("Pro-%d, thread_id-%d, speed:%0.3f ops, Perf: %ld KB/s\n", pid, thread_id, speed, Perf); + } else if (t_times) { + speed = (t_times / time_used) * 1000000; //ops + Perf = speed * pktlen / 1024; //B->KB + pthread_mutex_lock(&perf_mutex); + g_total_perf += Perf; + total_recv_task += pdata->recv_task_num; + pthread_mutex_unlock(&perf_mutex); + SEC_TST_PRT("Pro-%d, thread_id-%d, speed:%0.3f ops, Perf: %ld KB/s\n", pid, thread_id, speed, Perf); + } + +fail_release: + if (opdata.in) + wd_free_blk(pdata->pool, opdata.in); + if (opdata.iv) + wd_free_blk(pdata->pool, opdata.iv); + if (opdata.out) + wd_free_blk(pdata->pool, opdata.out); + if (ctx) + wcrypto_del_cipher_ctx(ctx); + if (tag) + free(tag); + + return ret; +} + +void _digest_cb(void *message, void *digest_tag) +{ + struct digest_async_tag *tag = digest_tag; + struct test_sec_pthread_dt *thread_info = tag->thread_info; + thread_info->recv_task_num++; +} + +int sec_async_digest_test(struct test_sec_pthread_dt *pdata) +{ + int thread_id = (int)syscall(__NR_gettid); + struct wcrypto_digest_ctx_setup setup; + struct wcrypto_digest_op_data opdata; + struct hash_testvec *tv; + struct timeval cur_tval; + float time_used, speed; + unsigned long Perf = 0; + int pid = getpid(); + void *ctx = NULL; + struct digest_async_tag *tag = NULL; //async + struct wd_queue *q = pdata->q; + int i = 0; + int ret; + + memset(&setup, 0, sizeof(setup)); + memset(&opdata, 0, sizeof(opdata)); + /* default AES-CBC */ + setup.alg = WCRYPTO_SM3; + setup.mode = WCRYPTO_DIGEST_NORMAL; + + ret = get_digest_resource(&tv, (int *)&setup.alg, (int *)&setup.mode); + if (ret) + return -EINVAL; + + setup.cb = (void *)_digest_cb; //call back functions of user + setup.br.alloc = (void *)wd_alloc_blk; + setup.br.free = (void *)wd_free_blk; + setup.br.iova_map = (void *)wd_blk_iova_map; + setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + setup.br.get_bufsize = (void *)wd_blksize; + setup.br.usr = pdata->pool; + + ctx = wcrypto_create_digest_ctx(q, &setup); + if (!ctx) { + SEC_TST_PRT("Proc-%d, %d-TD:create %s ctx fail!\n", + pid, thread_id, q->capa.alg); + ret = -EINVAL; + return ret; + } + + if (setup.mode == WCRYPTO_DIGEST_HMAC) { + ret = wcrypto_set_digest_key(ctx, (__u8*)tv->key, + (__u16)tv->ksize); + if (ret) { + SEC_TST_PRT("set key fail!\n"); + goto fail_release; + } + } + + hexdump(tv->key, tv->ksize); + + opdata.in = wd_alloc_blk(pdata->pool); + if (!opdata.in) { + SEC_TST_PRT("alloc in buffer fail!\n"); + goto fail_release; + } + memcpy(opdata.in, tv->plaintext, tv->psize); + opdata.in_bytes = tv->psize; + SEC_TST_PRT("digest len:%d\n", opdata.in_bytes); + + hexdump(opdata.in, opdata.in_bytes); + + opdata.priv = NULL; + opdata.out = wd_alloc_blk(pdata->pool); + opdata.out_bytes = tv->dsize; + if (!opdata.out) { + SEC_TST_PRT("alloc out buffer fail!\n"); + goto fail_release; + } + + do { + tag = malloc(sizeof(struct digest_async_tag)); //set the user tag is async + if (!tag) + goto fail_release; + tag->ctx = ctx; + tag->thread_id = thread_id; + tag->cnt = i; + tag->thread_info = pdata; +try_do_again: + ret = wcrypto_do_digest(ctx, &opdata, tag); + if (ret == -WD_EBUSY) { + usleep(100); + goto try_do_again; + } + pdata->send_task_num++; + i++; + + } while(!is_exit(pdata)); + + gettimeofday(&cur_tval, NULL); + time_used = (float)((cur_tval.tv_sec - pdata->start_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - pdata->start_tval.tv_usec); + SEC_TST_PRT("time_used:%0.0f us, send task num:%d\n", time_used, pdata->send_task_num++); + if (t_seconds) { + speed = pdata->send_task_num / time_used * 1000000; + Perf = speed * pktlen / 1024; //B->KB + pthread_mutex_lock(&perf_mutex); + g_total_perf += Perf; + pthread_mutex_unlock(&perf_mutex); + SEC_TST_PRT("Pro-%d, thread_id-%d, speed:%0.3f ops, Perf: %ld KB/s\n", pid, thread_id, speed, Perf); + } else if (t_times) { + speed = (t_times / time_used) * 1000000; //ops + Perf = speed * pktlen / 1024; //B->KB + pthread_mutex_lock(&perf_mutex); + g_total_perf += Perf; + pthread_mutex_unlock(&perf_mutex); + SEC_TST_PRT("Pro-%d, thread_id-%d, speed:%0.3f ops, Perf: %ld KB/s\n", pid, thread_id, speed, Perf); + } + +fail_release: + if (opdata.in) + wd_free_blk(pdata->pool, opdata.in); + if (opdata.out) + wd_free_blk(pdata->pool, opdata.out); + if (ctx) + wcrypto_del_digest_ctx(ctx); + if (tag) + free(tag); + + return ret; +} + +void *_sec_async_test_thread(void *data) +{ + if (!data) { + SEC_TST_PRT("test data input error!\n"); + return NULL; + } + struct test_sec_pthread_dt *pdata = data; + if (!g_algclass) + sec_async_func_test(pdata); + else + sec_async_digest_test(pdata); + + return NULL; +} + +static int sec_cipher_async_test(int thread_num, __u64 lcore_mask, + __u64 hcore_mask, enum cipher_op_type op_type, + char *dev_path, unsigned int node_mask) +{ + struct wd_blkpool_setup setup; + int i, ret, cnt = 0; + struct wd_queue q; + void **pool; + + memset(&q, 0, sizeof(q)); + + if (!g_algclass){ + q.capa.alg = "cipher"; + if (op_type == ENCRYPTION) { + q.capa.priv.direction = 0; //0 is ENC, 1 is DEC + } else + q.capa.priv.direction = 1; + } else { + q.capa.alg = "digest"; + } + + ret = wd_request_queue(&q); + if (ret) { + SEC_TST_PRT("request queue fail!\n"); + return ret; + } + memset(&setup, 0, sizeof(setup)); + /* set pool inv + key + in + out */ + setup.block_size = MAX_BLOCK_SZ; + setup.block_num = MAX_BLOCK_NM; + setup.align_size = SQE_SIZE; + + /* create pool for every queue */ + SEC_TST_PRT("create pool memory: %d\n", MAX_BLOCK_NM * setup.block_size); + pool = wd_blkpool_create(&q, &setup); + if (!pool) { + SEC_TST_PRT("%s(): create pool fail!\n", __func__); + return -ENOMEM; + } + /* frist create the async poll thread! */ + test_thrds_data[0].pool = pool; + test_thrds_data[0].q = &q; + test_thrds_data[0].thread_num = 1; + test_thrds_data[0].op_type = op_type; + test_thrds_data[0].cpu_id = 0; + ret = pthread_create(&system_test_thrds[0], NULL, + _cipher_async_poll_test_thread, &test_thrds_data[0]); + if (ret) { + SEC_TST_PRT("Create poll thread fail!\n"); + return ret; + } + + //??? ??? + if (_get_one_bits(lcore_mask) == 0 && + _get_one_bits(hcore_mask) == 0) + cnt = thread_num; + else + cnt = 1; + + for (i = 1 ; i <= cnt; i++) { + test_thrds_data[i].pool = pool; + test_thrds_data[i].q = &q; + test_thrds_data[i].thread_num = thread_num; + test_thrds_data[i].op_type = op_type; + test_thrds_data[i].cpu_id = _get_cpu_id(i, lcore_mask); + + gettimeofday(&test_thrds_data[i].start_tval, NULL); + + ret = pthread_create(&system_test_thrds[i], NULL, + _sec_async_test_thread, &test_thrds_data[i]); + if (ret) { + SEC_TST_PRT("Create %dth thread fail!\n", i); + return ret; + } + } + + for (i = 1; i <= thread_num; i++) { + ret = pthread_join(system_test_thrds[i], NULL); + if (ret) { + SEC_TST_PRT("Join %dth thread fail!\n", i); + return ret; + } + } + asyn_thread_exit = 1; + ret = pthread_join(system_test_thrds[0], NULL); + if (ret) { + SEC_TST_PRT("Join %dth thread fail!\n", i); + return ret; + } + + SEC_TST_PRT("%d-threads, total Perf: %lld KB/s, total recv task nums:%lld\n", + thread_num, g_total_perf, total_recv_task); + + wd_release_queue(&q); + wd_blkpool_destroy(pool); + return 0; +} + +int sec_aead_sync_func_test(void *data) +{ + int thread_id = (int)syscall(__NR_gettid); + struct test_sec_pthread_dt *pdata = data; + struct wcrypto_aead_ctx_setup setup; + struct wcrypto_aead_op_data *opdata = malloc(sizeof(struct wcrypto_aead_op_data)); + struct wd_queue *q = pdata->q; + struct timeval cur_tval; + struct aead_testvec *tv; + float time_used, speed; + unsigned long Perf = 0; + int pid = getpid(); + void *ctx = NULL; + void *tag = NULL; + int auth_size; + int in_size; + int iv_len; + int ret; + + memset(&setup, 0, sizeof(setup)); + memset(opdata, 0, sizeof(struct wcrypto_aead_op_data)); + + setup.calg = WCRYPTO_CIPHER_AES; + setup.cmode = WCRYPTO_CIPHER_CCM; + setup.br.alloc = (void *)wd_alloc_blk; + setup.br.free = (void *)wd_free_blk; + setup.br.iova_map = (void *)wd_blk_iova_map; + setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + setup.br.get_bufsize = (void *)wd_blksize; + setup.br.usr = pdata->pool; + + ret = get_aead_resource(&tv, (int *)&setup.calg, + (int *)&setup.cmode, (int *)&setup.dalg, (int *)&setup.dmode); + if (ret) + return -EINVAL; + + ctx = wcrypto_create_aead_ctx(q, &setup); + if (!ctx) { + SEC_TST_PRT("Proc-%d, %d-TD:create %s ctx fail!\n", + pid, thread_id, q->capa.alg); + ret = -EINVAL; + return ret; + } + + hexdump((char *)tv->key, tv->klen); + if (setup.cmode == WCRYPTO_CIPHER_CCM || + setup.cmode == WCRYPTO_CIPHER_GCM) { + ret = wcrypto_set_aead_ckey(ctx, (__u8*)tv->key, (__u16)tv->klen); + if (ret) { + SEC_TST_PRT("set key fail!\n"); + goto fail_release; + } + }else { + // AEAD template's cipher key is the tail data + ret = wcrypto_set_aead_ckey(ctx, (__u8*)tv->key + 0x28, 0x10); + if (ret) { + SEC_TST_PRT("set key fail!\n"); + goto fail_release; + } + // AEAD template's auth key is the mid data + ret = wcrypto_set_aead_akey(ctx, (__u8*)tv->key + 0x08, 0x20); + if (ret) { + SEC_TST_PRT("set auth key fail!\n"); + goto fail_release; + } + } + + auth_size = (__u16)(tv->clen - tv->plen); + ret = wcrypto_aead_setauthsize(ctx, auth_size); + if (ret) { + SEC_TST_PRT("set authsize fail!\n"); + goto fail_release; + } + + // test the auth size + ret = wcrypto_aead_getauthsize(ctx); + if (ret != auth_size) { + SEC_TST_PRT("get authsize fail!\n"); + goto fail_release; + } + ret = wcrypto_aead_get_maxauthsize(ctx); + if (ret < auth_size) { + SEC_TST_PRT("get max authsize fail!\n"); + goto fail_release; + } + SEC_TST_PRT("max authsize : %d!\n", ret); + + if (q->capa.priv.direction == 0) { + opdata->op_type = WCRYPTO_CIPHER_ENCRYPTION_DIGEST; + } else { + opdata->op_type = WCRYPTO_CIPHER_DECRYPTION_DIGEST; + } + + opdata->assoc_size = tv->alen; + opdata->in = wd_alloc_blk(pdata->pool); + if (!opdata->in) { + SEC_TST_PRT("alloc in buffer fail!\n"); + goto fail_release; + } + + in_size = tv->alen + tv->plen + auth_size; + if (in_size > MAX_BLOCK_SZ) { + SEC_TST_PRT("alloc in buffer block size too small!\n"); + goto fail_release; + } + + // copy the assoc data in the front of in data + memset(opdata->in, 0, in_size); + if (q->capa.priv.direction == 0) { + memcpy(opdata->in, tv->assoc, tv->alen); + memcpy((opdata->in + tv->alen), tv->ptext, tv->plen); + opdata->in_bytes = tv->plen; + } else { + memcpy(opdata->in, tv->assoc, tv->alen); + memcpy((opdata->in + tv->alen), tv->ctext, tv->clen); + opdata->in_bytes = tv->clen - auth_size; + } + + SEC_TST_PRT("aead input len:%d\n", tv->alen + opdata->in_bytes); + hexdump(opdata->in, tv->alen + opdata->in_bytes); + opdata->priv = NULL; + opdata->out = wd_alloc_blk(pdata->pool); + if (!opdata->out) { + SEC_TST_PRT("alloc out buffer fail!\n"); + goto fail_release; + } + if (q->capa.priv.direction == 0) { + opdata->out_bytes = tv->alen + tv->clen; + } else { + opdata->out_bytes = tv->alen + tv->plen; + } + opdata->out_buf_bytes = MAX_BLOCK_SZ; + //set iv + opdata->iv = wd_alloc_blk(pdata->pool); + if (!opdata->iv) { + SEC_TST_PRT("alloc iv buffer fail!\n"); + goto fail_release; + } + + // if data is \0x00, the strlen will end and return + // iv_len = strlen(tv->iv); + if (setup.cmode == WCRYPTO_CIPHER_GCM) { + iv_len = 12; + } else { + iv_len = 16; + } + memset(opdata->iv, 0, iv_len); + memcpy(opdata->iv, tv->iv, iv_len); + opdata->iv_bytes = iv_len; + SEC_TST_PRT("dump set input IV! IV lenght:%d\n", iv_len); + hexdump(opdata->iv, opdata->iv_bytes); + + do { + ret = wcrypto_do_aead(ctx, opdata, tag); + pdata->send_task_num++; + if (pdata->send_task_num == 1) { + SEC_TST_PRT("dump output!\n"); + hexdump(opdata->out, opdata->out_bytes + auth_size); + } + } while(!is_exit(pdata)); + + gettimeofday(&cur_tval, NULL); + time_used = (float)((cur_tval.tv_sec - pdata->start_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - pdata->start_tval.tv_usec); + SEC_TST_PRT("time_used:%0.0f us, send task num:%d\n", time_used, pdata->send_task_num++); + speed = pdata->send_task_num / time_used * 1000000; + Perf = speed * in_size / 1024; //B->KB + SEC_TST_PRT("Pro-%d, thread_id-%d, speed:%0.3f ops, Perf: %ld KB/s\n", pid, + thread_id, speed, Perf); + +fail_release: + if (opdata->in) + wd_free_blk(pdata->pool, opdata->in); + if (opdata->iv) + wd_free_blk(pdata->pool, opdata->iv); + if (opdata->out) + wd_free_blk(pdata->pool, opdata->out); + if (ctx) + wcrypto_del_aead_ctx(ctx); + free(opdata); + + return ret; +} + +void *__sec_aead_sync_func_test(void *data) +{ + sec_aead_sync_func_test(data); + + return NULL; +} + +static int sec_aead_sync_test(int thread_num, __u64 lcore_mask, + __u64 hcore_mask, enum cipher_op_type op_type, + char *dev_path, unsigned int node_mask) +{ + void **pool; + struct wd_blkpool_setup setup; + int i, ret, cnt = 0, j; + struct wd_queue *q; + int qidx; + + SEC_TST_PRT("SEC q_num is : %d!\n", q_num); + q = malloc(q_num * sizeof(struct wd_queue)); + if (!q) { + SEC_TST_PRT("malloc q memory fail!\n"); + return -ENOMEM; + } + + memset(q, 0, q_num * sizeof(struct wd_queue)); + + /* create pool for every queue */ + pool = malloc(q_num * sizeof(pool)); + if (!pool) { + SEC_TST_PRT("malloc pool memory fail!\n"); + return -ENOMEM; + } + + for (j = 0; j < q_num; j++) { + q[j].capa.alg = "aead"; + if (op_type == ENCRYPTION) { + q[j].capa.priv.direction = 0; //0 is ENC, 1 is DEC + } else { + q[j].capa.priv.direction = 1; + } + + if (dev_path) { + strncpy(q[j].dev_path, dev_path, sizeof(q[j].dev_path)); + } + // q[j].node_mask = node_mask; + + ret = wd_request_queue(&q[j]); + if (ret) { + SEC_TST_PRT("request queue %d fail!\n", j); + return ret; + } + memset(&setup, 0, sizeof(setup)); + setup.block_size = MAX_BLOCK_SZ; //set pool inv + key + in + out + setup.block_num = MAX_BLOCK_NM; + setup.align_size = SQE_SIZE; + + SEC_TST_PRT("create pool memory: %d\n", MAX_BLOCK_NM * setup.block_size); + pool[j] = wd_blkpool_create(&q[j], &setup); + if (!pool[j]) { + SEC_TST_PRT("%s(): create %dth pool fail!\n", __func__, j); + return -ENOMEM; + } + } + + //Ïß³ÌÊý Óë°óºË + if (_get_one_bits(lcore_mask) == 0 && + _get_one_bits(hcore_mask) == 0) + cnt = thread_num; + else + cnt = 1; + + for (i = 0 ; i < cnt; i++) { + qidx = i / ctx_num_per_q; + test_thrds_data[i].pool = pool[qidx]; + test_thrds_data[i].q = &q[qidx]; + test_thrds_data[i].thread_num = thread_num; + test_thrds_data[i].op_type = op_type; + test_thrds_data[i].cpu_id = _get_cpu_id(i, lcore_mask); + + gettimeofday(&test_thrds_data[i].start_tval, NULL); + + ret = pthread_create(&system_test_thrds[i], NULL, + __sec_aead_sync_func_test, &test_thrds_data[i]); + if (ret) { + SEC_TST_PRT("Create %dth thread fail!\n", i); + return ret; + } + } + + for (i = 0; i < thread_num; i++) { + ret = pthread_join(system_test_thrds[i], NULL); + if (ret) { + SEC_TST_PRT("Join %dth thread fail!\n", i); + return ret; + } + } + + return 0; +} + +static void *_aead_async_poll_test_thread(void *data) +{ + struct test_sec_pthread_dt *pdata = data; + struct wd_queue *q = pdata->q; + int ret; + + while (1) { + ret = wcrypto_aead_poll(q, 1); + if (ret < 0) { + break; + } + + if (asyn_thread_exit) + break; + } + + return NULL; +} + +int sec_aead_async_func_test(void *data) +{ + int thread_id = (int)syscall(__NR_gettid); + struct test_sec_pthread_dt *pdata = data; + struct wcrypto_aead_ctx_setup setup; + struct wcrypto_aead_op_data *opdata = malloc(sizeof(struct wcrypto_aead_op_data)); + struct cipher_async_tag *tag = NULL; //async + struct wd_queue *q = pdata->q; + struct timeval cur_tval; + struct aead_testvec *tv; + float time_used, speed; + unsigned long Perf = 0; + int pid = getpid(); + void *ctx = NULL; + int auth_size; + int in_size; + int iv_len; + int i = 0; + int ret; + + memset(&setup, 0, sizeof(setup)); + memset(opdata, 0, sizeof(struct wcrypto_aead_op_data)); + + setup.calg = WCRYPTO_CIPHER_AES; + setup.cmode = WCRYPTO_CIPHER_CCM; + setup.cb = (void *)_cipher_cb; //call back functions of user + setup.br.alloc = (void *)wd_alloc_blk; + setup.br.free = (void *)wd_free_blk; + setup.br.iova_map = (void *)wd_blk_iova_map; + setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + setup.br.get_bufsize = (void *)wd_blksize; + setup.br.usr = pdata->pool; + + ret = get_aead_resource(&tv, (int *)&setup.calg, + (int *)&setup.cmode, (int *)&setup.dalg, (int *)&setup.dmode); + if (ret) + return -EINVAL; + + ctx = wcrypto_create_aead_ctx(q, &setup); + if (!ctx) { + SEC_TST_PRT("Proc-%d, %d-TD:create %s ctx fail!\n", + pid, thread_id, q->capa.alg); + ret = -EINVAL; + return ret; + } + + hexdump((char *)tv->key, tv->klen); + if (setup.cmode == WCRYPTO_CIPHER_CCM || + setup.cmode == WCRYPTO_CIPHER_GCM) { + ret = wcrypto_set_aead_ckey(ctx, (__u8*)tv->key, (__u16)tv->klen); + if (ret) { + SEC_TST_PRT("set key fail!\n"); + goto fail_release; + } + }else { + // AEAD template's cipher key is the tail data + ret = wcrypto_set_aead_ckey(ctx, (__u8*)tv->key + 0x28, 0x10); + if (ret) { + SEC_TST_PRT("set key fail!\n"); + goto fail_release; + } + // AEAD template's auth key is the mid data + ret = wcrypto_set_aead_akey(ctx, (__u8*)tv->key + 0x08, 0x20); + if (ret) { + SEC_TST_PRT("set auth key fail!\n"); + goto fail_release; + } + } + + auth_size = (__u16)(tv->clen - tv->plen); + ret = wcrypto_aead_setauthsize(ctx, auth_size); + if (ret) { + SEC_TST_PRT("set authsize fail!\n"); + goto fail_release; + } + + // test the auth size + ret = wcrypto_aead_getauthsize(ctx); + if (ret != auth_size) { + SEC_TST_PRT("get authsize fail!\n"); + goto fail_release; + } + ret = wcrypto_aead_get_maxauthsize(ctx); + if (ret < auth_size) { + SEC_TST_PRT("get max authsize fail!\n"); + goto fail_release; + } + SEC_TST_PRT("max authsize : %d!\n", ret); + + if (q->capa.priv.direction == 0) { + opdata->op_type = WCRYPTO_CIPHER_ENCRYPTION_DIGEST; + } else { + opdata->op_type = WCRYPTO_CIPHER_DECRYPTION_DIGEST; + } + + opdata->assoc_size = tv->alen; + opdata->in = wd_alloc_blk(pdata->pool); + if (!opdata->in) { + SEC_TST_PRT("alloc in buffer fail!\n"); + goto fail_release; + } + + in_size = tv->alen + tv->plen + auth_size; + if (in_size > MAX_BLOCK_SZ) { + SEC_TST_PRT("alloc in buffer block size too small!\n"); + goto fail_release; + } + + // copy the assoc data in the front of in data + memset(opdata->in, 0, in_size); + if (q->capa.priv.direction == 0) { + memcpy(opdata->in, tv->assoc, tv->alen); + memcpy((opdata->in + tv->alen), tv->ptext, tv->plen); + opdata->in_bytes = tv->plen; + } else { + memcpy(opdata->in, tv->assoc, tv->alen); + memcpy((opdata->in + tv->alen), tv->ctext, tv->clen); + opdata->in_bytes = tv->clen - auth_size; + } + + SEC_TST_PRT("aead input len:%d\n", tv->alen + opdata->in_bytes); + hexdump(opdata->in, tv->alen + opdata->in_bytes); + opdata->priv = NULL; + opdata->out = wd_alloc_blk(pdata->pool); + if (!opdata->out) { + SEC_TST_PRT("alloc out buffer fail!\n"); + goto fail_release; + } + if (q->capa.priv.direction == 0) { + opdata->out_bytes = tv->alen + tv->clen; + } else { + opdata->out_bytes = tv->alen + tv->plen; + } + opdata->out_buf_bytes = MAX_BLOCK_SZ; + //set iv + opdata->iv = wd_alloc_blk(pdata->pool); + if (!opdata->iv) { + SEC_TST_PRT("alloc iv buffer fail!\n"); + goto fail_release; + } + + // if data is \0x00, the strlen will end and return + // iv_len = strlen(tv->iv); + if (setup.cmode == WCRYPTO_CIPHER_GCM) { + iv_len = 12; + } else { + iv_len = 16; + } + memset(opdata->iv, 0, iv_len); + memcpy(opdata->iv, tv->iv, iv_len); + opdata->iv_bytes = iv_len; + SEC_TST_PRT("dump set input IV! IV lenght:%d\n", iv_len); + hexdump(opdata->iv, opdata->iv_bytes); + + do { + tag = malloc(sizeof(struct cipher_async_tag)); // set the user tag + if (!tag) + goto fail_release; + + tag->ctx = ctx; + tag->thread_id = thread_id; + tag->cnt = i; + tag->thread_info = pdata; + try_do_again: + ret = wcrypto_do_aead(ctx, opdata, tag); + if (ret == -WD_EBUSY) { + usleep(100); + SEC_TST_PRT("wcrypto_do_aead busy!\n"); + goto try_do_again; + } + pdata->send_task_num++; + i++; + if (pdata->send_task_num == 1) { + SEC_TST_PRT("dump output!\n"); + hexdump(opdata->out, opdata->out_bytes + auth_size); + } + } while(!is_exit(pdata)); + + gettimeofday(&cur_tval, NULL); + time_used = (float)((cur_tval.tv_sec - pdata->start_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - pdata->start_tval.tv_usec); + SEC_TST_PRT("time_used:%0.0f us, send task num:%d\n", time_used, pdata->send_task_num++); + speed = pdata->send_task_num / time_used * 1000000; + Perf = speed * in_size / 1024; //B->KB + SEC_TST_PRT("Pro-%d, thread_id-%d, speed:%0.3f ops, Perf: %ld KB/s\n", pid, thread_id, + speed, Perf); + +fail_release: + if (opdata->in) + wd_free_blk(pdata->pool, opdata->in); + if (opdata->iv) + wd_free_blk(pdata->pool, opdata->iv); + if (opdata->out) + wd_free_blk(pdata->pool, opdata->out); + if (ctx) + wcrypto_del_aead_ctx(ctx); + if (tag) + free(tag); + free(opdata); + + return ret; +} +void *__sec_aead_async_func_test(void *data) +{ + sec_aead_async_func_test(data); + + return NULL; +} + +static int sec_aead_async_test(int thd_num, __u64 lcore_mask, + __u64 hcore_mask, enum cipher_op_type op_type, + char *dev_path, unsigned int node_mask) +{ + struct wd_blkpool_setup setup; + int i, ret,cnt = 0; + struct wd_queue q; + void **pool; + + memset(&q, 0, sizeof(q)); + + q.capa.alg = "aead"; + if (op_type == ENCRYPTION) { + q.capa.priv.direction = 0; // 0 is ENC, 1 is DEC + } else { + q.capa.priv.direction = 1; + } + + ret = wd_request_queue(&q); + if (ret) { + SEC_TST_PRT("request queue fail!\n"); + return ret; + } + memset(&setup, 0, sizeof(setup)); + /* set pool inv + key + in + out */ + setup.block_size = MAX_BLOCK_SZ; + setup.block_num = MAX_BLOCK_NM; + setup.align_size = SQE_SIZE; + + /* create pool for every queue */ + SEC_TST_PRT("create pool memory: %d\n", MAX_BLOCK_NM * setup.block_size); + pool = wd_blkpool_create(&q, &setup); + if (!pool) { + SEC_TST_PRT("%s(): create pool fail!\n", __func__); + return -ENOMEM; + } + /* frist create the async poll thread! */ + test_thrds_data[0].pool = pool; + test_thrds_data[0].q = &q; + test_thrds_data[0].thread_num = 1; + test_thrds_data[0].op_type = op_type; + test_thrds_data[0].cpu_id = 0; + ret = pthread_create(&system_test_thrds[0], NULL, + _aead_async_poll_test_thread, &test_thrds_data[0]); + if (ret) { + SEC_TST_PRT("Create poll thread fail!\n"); + return ret; + } + + //Ïß³ÌÊý Óë°óºË + if (_get_one_bits(lcore_mask) == 0 && + _get_one_bits(hcore_mask) == 0) + cnt = thd_num; + else + cnt = 1; + + for (i = 1 ; i <= cnt; i++) { + test_thrds_data[i].pool = pool; + test_thrds_data[i].q = &q; + test_thrds_data[i].thread_num = thd_num; + test_thrds_data[i].op_type = op_type; + test_thrds_data[i].cpu_id = _get_cpu_id(i, lcore_mask); + + gettimeofday(&test_thrds_data[i].start_tval, NULL); + + ret = pthread_create(&system_test_thrds[i], NULL, + __sec_aead_async_func_test, &test_thrds_data[i]); + if (ret) { + SEC_TST_PRT("Create %dth thread fail!\n", i); + return ret; + } + } + + for (i = 1; i <= thd_num; i++) { + ret = pthread_join(system_test_thrds[i], NULL); + if (ret) { + SEC_TST_PRT("Join %dth thread fail!\n", i); + return ret; + } + } + asyn_thread_exit = 1; + ret = pthread_join(system_test_thrds[0], NULL); + if (ret) { + SEC_TST_PRT("Join %dth thread fail!\n", i); + return ret; + } + + wd_release_queue(&q); + wd_blkpool_destroy(pool); + return 0; +} + +static void print_help(void) +{ + SEC_TST_PRT("NAME\n"); + SEC_TST_PRT(" test_hisi_sec: test wd sec function,etc\n"); + SEC_TST_PRT("USAGE\n"); + SEC_TST_PRT(" test_hisi_sec [--cipher] [--digest] [--aead]\n"); + SEC_TST_PRT(" test_hisi_sec [--optype] [--pktlen] [--keylen] [--times]\n"); + SEC_TST_PRT(" test_hisi_sec [--sync] [--async] [--help]\n"); + SEC_TST_PRT(" numactl --cpubind=0 --membind=0,1 ./test_hisi_sec xxxx\n"); + SEC_TST_PRT("DESCRIPTION\n"); + SEC_TST_PRT(" [--cipher ]:\n"); + SEC_TST_PRT(" specify symmetric cipher algorithm\n"); + SEC_TST_PRT(" 0 : AES-ECB; 1 : AES-CBC; 2 : AES-XTS; 3 : AES-OFB\n"); + SEC_TST_PRT(" 4 : AES-CFB; 5 : 3DES-ECB; 6 : 3DES-CBC; 7 : SM4-CBC\n"); + SEC_TST_PRT(" 8 : SM4-XTS; 9 : SM4-OFB; 10 : SM4-CFB; 11 : SM4-ECB\n"); + SEC_TST_PRT(" [--digest ]:\n"); + SEC_TST_PRT(" specify symmetric hash algorithm\n"); + SEC_TST_PRT(" 0 : SM3; 1 : MD5; 2 : SHA1; 3 : SHA256\n"); + SEC_TST_PRT(" 4 : SHA224; 5 : SHA384; 6 : SHA512; 7 : SHA512_224\n"); + SEC_TST_PRT(" 8 : SHA512_256\n"); + SEC_TST_PRT(" [--aead ]:\n"); + SEC_TST_PRT(" specify symmetric aead algorithm\n"); + SEC_TST_PRT(" 0 : AES-CCM; 1 : AES-GCM; 2 : Hmac(sha256),cbc(aes)\n"); + SEC_TST_PRT(" [--optype]:\n"); + SEC_TST_PRT(" 0 : encryption operation or normal mode for hash\n"); + SEC_TST_PRT(" 1 : decryption operation or hmac mode for hash\n"); + SEC_TST_PRT(" [--seconds]:\n"); + SEC_TST_PRT(" set the time for test\n"); + SEC_TST_PRT(" [--cycles]:\n"); + SEC_TST_PRT(" set the number of sent messages\n"); + SEC_TST_PRT(" [--pktlen]:\n"); + SEC_TST_PRT(" set the length of BD message in bytes\n"); + SEC_TST_PRT(" [--keylen]:\n"); + SEC_TST_PRT(" set the key length in bytes\n"); + SEC_TST_PRT(" [--sync]: start synchronous mode test\n"); + SEC_TST_PRT(" [--async]: start asynchronous mode test\n"); + SEC_TST_PRT(" [--dump]: dump message operation mode test, 0: default, not dump, 1: dump\n"); + SEC_TST_PRT(" [--help] = usage\n"); + SEC_TST_PRT("Example\n"); + SEC_TST_PRT(" ./test_hisi_sec --cipher 0 --t 1 --optype 0 \n"); + SEC_TST_PRT(" --cycles 100 --pktlen 16 --keylen 16 --ivlen 16 --sync\n"); + SEC_TST_PRT("UPDATE:2021-04-27\n"); +} + +static void test_sec_cmd_parse(int argc, char *argv[], struct test_sec_option *option) +{ + int option_index = 0; + int c; + + static struct option long_options[] = { + {"cipher", required_argument, 0, 1}, + {"digest", required_argument, 0, 2}, + {"aead", required_argument, 0, 3}, + {"t", required_argument, 0, 4}, + {"optype", required_argument, 0, 5}, + {"seconds", required_argument, 0, 6}, + {"cycles", required_argument, 0, 7}, + {"pktlen", required_argument, 0, 8}, + {"keylen", required_argument, 0, 9}, + {"ivlen", required_argument, 0, 10}, + {"sync", no_argument, 0, 11}, + {"async", no_argument, 0, 12}, + {"dump", required_argument, 0, 13}, + {"help", no_argument, 0, 14}, + {0, 0, 0, 0} + }; + + while (1) { + c = getopt_long(argc, argv, "", long_options, &option_index); + if (c == -1) + break; + + switch (c) { + case 1: + option->algclass = CIPHER_CLASS; + option->algtype = strtol(optarg, NULL, 0); + break; + case 2: + option->algclass = DIGEST_CLASS; + option->algtype = strtol(optarg, NULL, 0); + break; + case 3: + option->algclass = AEAD_CLASS; + option->algtype = strtol(optarg, NULL, 0); + break; + case 4: + option->t = strtol(optarg, NULL, 0); + break; + case 5: + option->optype = strtol(optarg, NULL, 0); + break; + case 6: + option->timeclass = SECONDS_CLASS; + option->times = strtol(optarg, NULL, 0); + break; + case 7: + option->timeclass = CYCLES_CLASS; + option->times = strtol(optarg, NULL, 0); + break; + case 8: + option->pktlen = strtol(optarg, NULL, 0); + break; + case 9: + option->keylen = strtol(optarg, NULL, 0); + break; + case 10: + option->ivlen = strtol(optarg, NULL, 0); + break; + case 11: + option->syncmode = 0; + break; + case 12: + option->syncmode = 1; + break; + case 13: + option->dump = strtol(optarg, NULL, 0); + break; + case 14: + print_help(); + exit(-1); + default: + SEC_TST_PRT("bad input parameter, exit\n"); + print_help(); + exit(-1); + } + } +} + +static int test_sec_default_case(void) +{ + unsigned int node_msk = 0; + int thread_num = 1; + int direction = 0; + + pktlen = 16; + g_keylen = 16; + g_ivlen = 16; + + g_algclass = CIPHER_CLASS; + g_testalg = 0; + t_times = 10; + + SEC_TST_PRT("Test sec Cipher parameter default, alg:ecb(aes), set_times:10," + "set_pktlen:16 bytes, set_keylen:128 bit.\n"); + return sec_cipher_sync_test(thread_num, 0, 0, ENCRYPTION, NULL, node_msk); +} + +static int test_sec_option_convert(struct test_sec_option *option) +{ + if (option->algclass > DIGEST_CLASS) { + print_help(); + return -EINVAL; + } + + if (option->syncmode > 1) { + print_help(); + return -EINVAL; + } + + g_testalg = option->algtype; + g_thread_num = option->t; + if (g_thread_num <= 0 || g_thread_num > TEST_MAX_THRD) { + SEC_TST_PRT("Invalid threads num:%d, Now set threads num as 2!\n", g_thread_num); + g_thread_num = 2; + } + + alg_op_type = option->optype ? DECRYPTION : ENCRYPTION; + pktlen = option->pktlen; + g_keylen = option->keylen; + g_ivlen = option->ivlen; + g_algclass = option->algclass; + g_dump = option->dump; + if (option->timeclass == SECONDS_CLASS) { + t_seconds = option->times; + SEC_TST_PRT("set test seconds:%d\n", t_seconds); + } else { + t_times = option->times; + SEC_TST_PRT("set test cycles:%lld\n", t_times); + } + SEC_TST_PRT("test set: pktlen: %d, key len:%d, iv len:%d\n", pktlen, g_keylen, g_ivlen); + + return 0; +} + +static int test_sec_run(u32 sync_mode, u32 alg_class) +{ + __u64 lcore_mask = 0; + __u64 hcore_mask = 0; + u32 node_msk = 0; + int thread_num = g_thread_num; + int ret = 0; + + q_num = thread_num * ctx_num_per_q; + SEC_TST_PRT("set alg index: %d, Currently set q number is: %d!\n", alg_class, q_num); + + if (sync_mode == 0) { + if (alg_class == CIPHER_CLASS || alg_class == DIGEST_CLASS) { + if (alg_class == CIPHER_CLASS) + SEC_TST_PRT("currently cipher test is synchronize multi -%d threads!\n", thread_num); + else + SEC_TST_PRT("currently digest test is synchronize multi -%d threads!\n", thread_num); + ret = sec_cipher_sync_test(thread_num, lcore_mask, hcore_mask, + alg_op_type, NULL, node_msk); + } else if (alg_class == AEAD_CLASS) { + SEC_TST_PRT("currently aead test is synchronize multi -%d threads!\n", thread_num); + ret = sec_aead_sync_test(thread_num, lcore_mask, hcore_mask, + alg_op_type, NULL, node_msk); + } + + } else { + if (alg_class == CIPHER_CLASS || alg_class == DIGEST_CLASS) { + if (alg_class == CIPHER_CLASS) + SEC_TST_PRT("currently cipher test is asynchronous multi -%d threads!\n", thread_num); + else + SEC_TST_PRT("currently digest test is asynchronous multi -%d threads!\n", thread_num); + ret = sec_cipher_async_test(thread_num, lcore_mask, hcore_mask, + alg_op_type, NULL, node_msk); + } else if (alg_class == AEAD_CLASS) { + SEC_TST_PRT("currently aead test is asynchronous multi -%d threads!\n", thread_num); + ret = sec_aead_async_test(thread_num, lcore_mask, hcore_mask, + alg_op_type, NULL, node_msk); + } + } + + return ret; +} + +int main(int argc, char *argv[]) +{ + struct test_sec_option option = {0}; + int ret = 0; + + SEC_TST_PRT("this is a hisi sec test.\n"); + int thread_num = 1; + if (!argv[1]) + return test_sec_default_case(); + + test_sec_cmd_parse(argc, argv, &option); + ret = test_sec_option_convert(&option); + if (ret) + return ret; + + return test_sec_run(option.syncmode, option.algclass); +} diff --git a/uadk/v1/test/hisi_sec_test/test_hisi_sec.h b/uadk/v1/test/hisi_sec_test/test_hisi_sec.h new file mode 100644 index 0000000..337b5ba --- /dev/null +++ b/uadk/v1/test/hisi_sec_test/test_hisi_sec.h @@ -0,0 +1,1588 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#ifndef __HISI_TEST_SEC_H +#define __HISI_TEST_SEC_H + +enum alg_class { + CIPHER_CLASS, + AEAD_CLASS, + DIGEST_CLASS, +}; + +enum times_class { + SECONDS_CLASS, + CYCLES_CLASS, +}; + +enum cipher_op_type { + ENCRYPTION, + DECRYPTION, +}; + +enum cipher_alg { + CIPHER_SM4, + CIPHER_AES, + CIPHER_DES, + CIPHER_3DES, +}; + +enum cipher_mode { + ECB, + CBC, + CTR, + XTS, + OFB +}; + +struct cipher_testvec { + const char *key; + int klen; + const char *iv; + int ivlen; + const char *iv_out; + const char *ptext; + const char *ctext; + int len; +}; + +enum sec_digest_state { + SEC_DIGEST_INIT = 0, + SEC_DIGEST_FIRST_UPDATING, + SEC_DIGEST_DOING, + SEC_DIGEST_FINAL +}; + +struct hash_testvec { + const char *key; + const char *plaintext; + const char *digest; + unsigned int psize; + unsigned short ksize; + unsigned int dsize; +}; + +struct aead_testvec { + const char *key; + const char *iv; + const char *ptext; + const char *assoc; + const char *ctext; + unsigned char novrfy; + unsigned char wk; + unsigned char klen; + unsigned int plen; + unsigned int clen; + unsigned int alen; + int setkey_error; + int setauthsize_error; + int crypt_error; +}; + +/* 192bit */ +struct cipher_testvec des3_ecb_tv_template_192[] = { + { + .key = "\x10\x46\x10\x34\x89\x98\x80\x20" + "\x91\x07\xd0\x15\x89\x19\x01\x01" + "\x19\x07\x92\x10\x98\x1a\x01\x01", + .klen = 24, + .ptext = "\x00\x00\x00\x00\x00\x00\x00\x00", + .ctext = "\xe1\xef\x62\xc3\x32\xfe\x82\x5b", + .len = 8, + } +}; + +/* 128bit */ +struct cipher_testvec des3_ecb_tv_template_128[] = { + { + .key = "\x10\x46\x10\x34\x89\x98\x80\x20" + "\x91\x07\xd0\x15\x89\x19\x01\x01", + .klen = 16, + .ptext = "\x00\x00\x00\x00\x00\x00\x00\x00", + .ctext = "\x8C\x78\x59\xEB\x1B\xD7\x4F\x0C", + .len = 8, + } +}; + +/* 192bit */ +struct cipher_testvec des3_cbc_tv_template_192[] = { + { + .key = "\xE9\xC0\xFF\x2E\x76\x0B\x64\x24" + "\x44\x4D\x99\x5A\x12\xD6\x40\xC0" + "\xEA\xC2\x84\xE8\x14\x95\xDB\xE8", + .klen = 24, + .iv = "\x7D\x33\x88\x93\x0F\x93\xB2\x42", + .iv_out = "\x6b\xfa\xb1\x91\x13\xb0\xd9\x19", + .ptext = "\x6f\x54\x20\x6f\x61\x4d\x79\x6e" + "\x53\x20\x63\x65\x65\x72\x73\x74" + "\x54\x20\x6f\x6f\x4d\x20\x6e\x61" + "\x20\x79\x65\x53\x72\x63\x74\x65" + "\x20\x73\x6f\x54\x20\x6f\x61\x4d" + "\x79\x6e\x53\x20\x63\x65\x65\x72" + "\x73\x74\x54\x20\x6f\x6f\x4d\x20" + "\x6e\x61\x20\x79\x65\x53\x72\x63" + "\x74\x65\x20\x73\x6f\x54\x20\x6f" + "\x61\x4d\x79\x6e\x53\x20\x63\x65" + "\x65\x72\x73\x74\x54\x20\x6f\x6f" + "\x4d\x20\x6e\x61\x20\x79\x65\x53" + "\x72\x63\x74\x65\x20\x73\x6f\x54" + "\x20\x6f\x61\x4d\x79\x6e\x53\x20" + "\x63\x65\x65\x72\x73\x74\x54\x20" + "\x6f\x6f\x4d\x20\x6e\x61\x0a\x79", + .ctext = "\x0e\x2d\xb6\x97\x3c\x56\x33\xf4" + "\x67\x17\x21\xc7\x6e\x8a\xd5\x49" + "\x74\xb3\x49\x05\xc5\x1c\xd0\xed" + "\x12\x56\x5c\x53\x96\xb6\x00\x7d" + "\x90\x48\xfc\xf5\x8d\x29\x39\xcc" + "\x8a\xd5\x35\x18\x36\x23\x4e\xd7" + "\x76\xd1\xda\x0c\x94\x67\xbb\x04" + "\x8b\xf2\x03\x6c\xa8\xcf\xb6\xea" + "\x22\x64\x47\xaa\x8f\x75\x13\xbf" + "\x9f\xc2\xc3\xf0\xc9\x56\xc5\x7a" + "\x71\x63\x2e\x89\x7b\x1e\x12\xca" + "\xe2\x5f\xaf\xd8\xa4\xf8\xc9\x7a" + "\xd6\xf9\x21\x31\x62\x44\x45\xa6" + "\xd6\xbc\x5a\xd3\x2d\x54\x43\xcc" + "\x9d\xde\xa5\x70\xe9\x42\x45\x8a" + "\x6b\xfa\xb1\x91\x13\xb0\xd9\x19", + .len = 128, + } +}; + +/* 128bit */ +struct cipher_testvec des3_cbc_tv_template_128[] = { + { + .key = "\xE9\xC0\xFF\x2E\x76\x0B\x64\x24" + "\x44\x4D\x99\x5A\x12\xD6\x40\xC0", + .klen = 16, + .iv = "\x7D\x33\x88\x93\x0F\x93\xB2\x42", + .iv_out = "\x6b\xfa\xb1\x91\x13\xb0\xd9\x19", + .ptext = "\x6f\x54\x20\x6f\x61\x4d\x79\x6e" + "\x53\x20\x63\x65\x65\x72\x73\x74" + "\x54\x20\x6f\x6f\x4d\x20\x6e\x61" + "\x20\x79\x65\x53\x72\x63\x74\x65" + "\x20\x73\x6f\x54\x20\x6f\x61\x4d" + "\x79\x6e\x53\x20\x63\x65\x65\x72" + "\x73\x74\x54\x20\x6f\x6f\x4d\x20" + "\x6e\x61\x20\x79\x65\x53\x72\x63" + "\x74\x65\x20\x73\x6f\x54\x20\x6f" + "\x61\x4d\x79\x6e\x53\x20\x63\x65" + "\x65\x72\x73\x74\x54\x20\x6f\x6f" + "\x4d\x20\x6e\x61\x20\x79\x65\x53" + "\x72\x63\x74\x65\x20\x73\x6f\x54" + "\x20\x6f\x61\x4d\x79\x6e\x53\x20" + "\x63\x65\x65\x72\x73\x74\x54\x20" + "\x6f\x6f\x4d\x20\x6e\x61\x0a\x79", + .ctext = "\xC2\x3D\x49\x51\x0B\x2E\xA7\x4C" + "\x8D\x71\x42\x0F\xDD\xFF\xA0\x2D" + "\x5A\xBD\x2F\x0A\xD5\xAF\xEA\xA3" + "\x25\x5A\x22\x99\x71\xB0\xE6\x66" + "\x51\xC2\x31\x79\x82\xEE\x23\xE7" + "\x98\xCD\xFE\x11\x47\x29\xE3\x01" + "\x3F\x8F\xCC\x87\x37\x90\xC3\xA9" + "\x86\xAC\x98\x5C\x2B\x97\xA4\x1E" + "\xE2\xFD\x51\xEA\xBC\x9F\x20\x4A" + "\x80\xFC\xA1\xE8\xDE\x93\x34\x01" + "\xB5\xBF\x6D\xDC\x81\x3E\x71\xB4" + "\x90\x16\x20\xF0\x4E\x4D\xBC\x95" + "\x62\xC1\x89\x91\x72\xEB\xF6\xF6" + "\x58\x4E\x7C\x5B\x73\x17\xD0\x96" + "\xAF\x15\x97\x0D\x6D\xAB\xD0\xFB" + "\x2E\xCD\x07\xF2\xF6\xE6\xB0\x75", + .len = 128, + } +}; + +/* 128bit */ +struct cipher_testvec aes_ecb_tv_template_128[] = { + { + .key = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .klen = 16, + .ptext = "\x00\x11\x22\x33\x44\x55\x66\x77" + "\x88\x99\xaa\xbb\xcc\xdd\xee\xff", + .ctext = "\x69\xc4\xe0\xd8\x6a\x7b\x04\x30" + "\xd8\xcd\xb7\x80\x70\xb4\xc5\x5a", + .len = 16, + } +}; + +/* 192bit */ +struct cipher_testvec aes_ecb_tv_template_192[] = { + { + .key = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17", + .klen = 24, + .ptext = "\x00\x11\x22\x33\x44\x55\x66\x77" + "\x88\x99\xaa\xbb\xcc\xdd\xee\xff", + .ctext = "\xdd\xa9\x7c\xa4\x86\x4c\xdf\xe0" + "\x6e\xaf\x70\xa0\xec\x0d\x71\x91", + .len = 16, + } +}; + +/* 128bit */ +struct cipher_testvec sm4_cbc_tv_template[] = { + { + .key = "\x01\x23\x45\x67\x89\xAB\xCD\xEF" + "\xFE\xDC\xBA\x98\x76\x54\x32\x10", + .klen = 16, + .ptext = "\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb" + "\xcc\xcc\xcc\xcc\xdd\xdd\xdd\xdd" + "\xee\xee\xee\xee\xff\xff\xff\xff" + "\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb", + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", + .iv_out = "\x4C\xB7\x01\x69\x51\x90\x92\x26" + "\x97\x9B\x0D\x15\xDC\x6A\x8F\x6D", + .ctext = "\x78\xEB\xB1\x1C\xC4\x0B\x0A\x48" + "\x31\x2A\xAE\xB2\x04\x02\x44\xCB" + "\x4C\xB7\x01\x69\x51\x90\x92\x26" + "\x97\x9B\x0D\x15\xDC\x6A\x8F\x6D", + .len = 32, + } +}; + +/* 256bit */ +struct cipher_testvec sm4_xts_tv_template[] = { + { + .key = "\x11\x11\x11\x11\x11\x11\x11\x11" + "\x11\x11\x11\x11\x11\x11\x11\x11" + "\x22\x22\x22\x22\x22\x22\x22\x22" + "\x22\x22\x22\x22\x22\x22\x22\x22", + .klen = 32, + .iv = "\x33\x33\x33\x33\x33\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00", + .ptext = "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44", + .ctext = "\xA7\x4D\x72\x6C\x11\x19\x6A\x32" + "\xBE\x04\xE0\x01\xFF\x29\xD0\xC7" + "\x93\x2F\x9F\x3E\xC2\x9B\xFC\xB6" + "\x4D\xD1\x7F\x63\xCB\xD3\xEA\x31", + .len = 32, + } +}; + +/* 256bit */ +struct cipher_testvec aes_ecb_tv_template_256[] = { + { + .key = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", + .klen = 32, + .ptext = "\x00\x11\x22\x33\x44\x55\x66\x77" + "\x88\x99\xaa\xbb\xcc\xdd\xee\xff", + .ctext = "\x8e\xa2\xb7\xca\x51\x67\x45\xbf" + "\xea\xfc\x49\x90\x4b\x49\x60\x89", + .len = 16, + } +}; + +/* 256bit */ +struct cipher_testvec aes_xts_tv_template_256[] = { + { + .key = "\x11\x11\x11\x11\x11\x11\x11\x11" + "\x11\x11\x11\x11\x11\x11\x11\x11" + "\x22\x22\x22\x22\x22\x22\x22\x22" + "\x22\x22\x22\x22\x22\x22\x22\x22", + .klen = 32, + .iv = "\x33\x33\x33\x33\x33\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00", + .ptext = "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44", + .ctext = "\xc4\x54\x18\x5e\x6a\x16\x93\x6e" + "\x39\x33\x40\x38\xac\xef\x83\x8b" + "\xfb\x18\x6f\xff\x74\x80\xad\xc4" + "\x28\x93\x82\xec\xd6\xd3\x94\xf0", + .len = 32, + } +}; + +/* 512bit */ +struct cipher_testvec aes_xts_tv_template_512[] = { + { + .key = "\x27\x18\x28\x18\x28\x45\x90\x45" + "\x23\x53\x60\x28\x74\x71\x35\x26" + "\x62\x49\x77\x57\x24\x70\x93\x69" + "\x99\x59\x57\x49\x66\x96\x76\x27" + "\x31\x41\x59\x26\x53\x58\x97\x93" + "\x23\x84\x62\x64\x33\x83\x27\x95" + "\x02\x88\x41\x97\x16\x93\x99\x37" + "\x51\x05\x82\x09\x74\x94\x45\x92", + .klen = 64, + .iv = "\xff\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00", + .ptext = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + "\x20\x21\x22\x23\x24\x25\x26\x27" + "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" + "\x30\x31\x32\x33\x34\x35\x36\x37" + "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" + "\x40\x41\x42\x43\x44\x45\x46\x47" + "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f" + "\x50\x51\x52\x53\x54\x55\x56\x57" + "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f" + "\x60\x61\x62\x63\x64\x65\x66\x67" + "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f" + "\x70\x71\x72\x73\x74\x75\x76\x77" + "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f" + "\x80\x81\x82\x83\x84\x85\x86\x87" + "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" + "\x90\x91\x92\x93\x94\x95\x96\x97" + "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" + "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7" + "\xa8\xa9\xaa\xab\xac\xad\xae\xaf" + "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7" + "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" + "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" + "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" + "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7" + "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" + "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7" + "\xe8\xe9\xea\xeb\xec\xed\xee\xef" + "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7" + "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff" + "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + "\x20\x21\x22\x23\x24\x25\x26\x27" + "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" + "\x30\x31\x32\x33\x34\x35\x36\x37" + "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" + "\x40\x41\x42\x43\x44\x45\x46\x47" + "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f" + "\x50\x51\x52\x53\x54\x55\x56\x57" + "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f" + "\x60\x61\x62\x63\x64\x65\x66\x67" + "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f" + "\x70\x71\x72\x73\x74\x75\x76\x77" + "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f" + "\x80\x81\x82\x83\x84\x85\x86\x87" + "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" + "\x90\x91\x92\x93\x94\x95\x96\x97" + "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" + "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7" + "\xa8\xa9\xaa\xab\xac\xad\xae\xaf" + "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7" + "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" + "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" + "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" + "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7" + "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" + "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7" + "\xe8\xe9\xea\xeb\xec\xed\xee\xef" + "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7" + "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff", + .ctext = "\x1c\x3b\x3a\x10\x2f\x77\x03\x86" + "\xe4\x83\x6c\x99\xe3\x70\xcf\x9b" + "\xea\x00\x80\x3f\x5e\x48\x23\x57" + "\xa4\xae\x12\xd4\x14\xa3\xe6\x3b" + "\x5d\x31\xe2\x76\xf8\xfe\x4a\x8d" + "\x66\xb3\x17\xf9\xac\x68\x3f\x44" + "\x68\x0a\x86\xac\x35\xad\xfc\x33" + "\x45\xbe\xfe\xcb\x4b\xb1\x88\xfd" + "\x57\x76\x92\x6c\x49\xa3\x09\x5e" + "\xb1\x08\xfd\x10\x98\xba\xec\x70" + "\xaa\xa6\x69\x99\xa7\x2a\x82\xf2" + "\x7d\x84\x8b\x21\xd4\xa7\x41\xb0" + "\xc5\xcd\x4d\x5f\xff\x9d\xac\x89" + "\xae\xba\x12\x29\x61\xd0\x3a\x75" + "\x71\x23\xe9\x87\x0f\x8a\xcf\x10" + "\x00\x02\x08\x87\x89\x14\x29\xca" + "\x2a\x3e\x7a\x7d\x7d\xf7\xb1\x03" + "\x55\x16\x5c\x8b\x9a\x6d\x0a\x7d" + "\xe8\xb0\x62\xc4\x50\x0d\xc4\xcd" + "\x12\x0c\x0f\x74\x18\xda\xe3\xd0" + "\xb5\x78\x1c\x34\x80\x3f\xa7\x54" + "\x21\xc7\x90\xdf\xe1\xde\x18\x34" + "\xf2\x80\xd7\x66\x7b\x32\x7f\x6c" + "\x8c\xd7\x55\x7e\x12\xac\x3a\x0f" + "\x93\xec\x05\xc5\x2e\x04\x93\xef" + "\x31\xa1\x2d\x3d\x92\x60\xf7\x9a" + "\x28\x9d\x6a\x37\x9b\xc7\x0c\x50" + "\x84\x14\x73\xd1\xa8\xcc\x81\xec" + "\x58\x3e\x96\x45\xe0\x7b\x8d\x96" + "\x70\x65\x5b\xa5\xbb\xcf\xec\xc6" + "\xdc\x39\x66\x38\x0a\xd8\xfe\xcb" + "\x17\xb6\xba\x02\x46\x9a\x02\x0a" + "\x84\xe1\x8e\x8f\x84\x25\x20\x70" + "\xc1\x3e\x9f\x1f\x28\x9b\xe5\x4f" + "\xbc\x48\x14\x57\x77\x8f\x61\x60" + "\x15\xe1\x32\x7a\x02\xb1\x40\xf1" + "\x50\x5e\xb3\x09\x32\x6d\x68\x37" + "\x8f\x83\x74\x59\x5c\x84\x9d\x84" + "\xf4\xc3\x33\xec\x44\x23\x88\x51" + "\x43\xcb\x47\xbd\x71\xc5\xed\xae" + "\x9b\xe6\x9a\x2f\xfe\xce\xb1\xbe" + "\xc9\xde\x24\x4f\xbe\x15\x99\x2b" + "\x11\xb7\x7c\x04\x0f\x12\xbd\x8f" + "\x6a\x97\x5a\x44\xa0\xf9\x0c\x29" + "\xa9\xab\xc3\xd4\xd8\x93\x92\x72" + "\x84\xc5\x87\x54\xcc\xe2\x94\x52" + "\x9f\x86\x14\xdc\xd2\xab\xa9\x91" + "\x92\x5f\xed\xc4\xae\x74\xff\xac" + "\x6e\x33\x3b\x93\xeb\x4a\xff\x04" + "\x79\xda\x9a\x41\x0e\x44\x50\xe0" + "\xdd\x7a\xe4\xc6\xe2\x91\x09\x00" + "\x57\x5d\xa4\x01\xfc\x07\x05\x9f" + "\x64\x5e\x8b\x7e\x9b\xfd\xef\x33" + "\x94\x30\x54\xff\x84\x01\x14\x93" + "\xc2\x7b\x34\x29\xea\xed\xb4\xed" + "\x53\x76\x44\x1a\x77\xed\x43\x85" + "\x1a\xd7\x7f\x16\xf5\x41\xdf\xd2" + "\x69\xd5\x0d\x6a\x5f\x14\xfb\x0a" + "\xab\x1c\xbb\x4c\x15\x50\xbe\x97" + "\xf7\xab\x40\x66\x19\x3c\x4c\xaa" + "\x77\x3d\xad\x38\x01\x4b\xd2\x09" + "\x2f\xa7\x55\xc8\x24\xbb\x5e\x54" + "\xc4\xf3\x6f\xfd\xa9\xfc\xea\x70" + "\xb9\xc6\xe6\x93\xe1\x48\xc1\x51", + .len = 512, + } +}; + +/* 128bit */ +struct cipher_testvec aes_cbc_tv_template_128[] = { + { + .key = "\x06\xa9\x21\x40\x36\xb8\xa1\x5b" + "\x51\x2e\x03\xd5\x34\x12\x00\x06", + .klen = 16, + .iv = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30" + "\xb4\x22\xda\x80\x2c\x9f\xac\x41", + .iv_out = "\xe3\x53\x77\x9c\x10\x79\xae\xb8" + "\x27\x08\x94\x2d\xbe\x77\x18\x1a", + .ptext = "Single block msg", + .ctext = "\xe3\x53\x77\x9c\x10\x79\xae\xb8" + "\x27\x08\x94\x2d\xbe\x77\x18\x1a", + .len = 16, + } +}; +/* 192bit */ +struct cipher_testvec aes_cbc_tv_template_192[] = { + /* From NIST SP800-38A */ + { + .key = "\x8e\x73\xb0\xf7\xda\x0e\x64\x52" + "\xc8\x10\xf3\x2b\x80\x90\x79\xe5" + "\x62\xf8\xea\xd2\x52\x2c\x6b\x7b", + .klen = 24, + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .iv_out = "\x08\xb0\xe2\x79\x88\x59\x88\x81" + "\xd9\x20\xa9\xe6\x4f\x56\x15\xcd", + .ptext = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" + "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" + "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" + "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" + "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" + "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + .ctext = "\x4f\x02\x1d\xb2\x43\xbc\x63\x3d" + "\x71\x78\x18\x3a\x9f\xa0\x71\xe8" + "\xb4\xd9\xad\xa9\xad\x7d\xed\xf4" + "\xe5\xe7\x38\x76\x3f\x69\x14\x5a" + "\x57\x1b\x24\x20\x12\xfb\x7a\xe0" + "\x7f\xa9\xba\xac\x3d\xf1\x02\xe0" + "\x08\xb0\xe2\x79\x88\x59\x88\x81" + "\xd9\x20\xa9\xe6\x4f\x56\x15\xcd", + .len = 64, + } +}; + +struct cipher_testvec aes_ctr_tv_template_128[] = { + { + .key = "\x2b\x7e\x15\x16\x28\xae\xd2\xa6" + "\xab\xf7\x15\x88\x09\xcf\x4f\x3c", + .klen = 16, + .iv = "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7" + "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff", + .iv_out = "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7" + "\xf8\xf9\xfa\xfb\xfc\xfd\xff\x03", + .ptext = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" + "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" + "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" + "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" + "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" + "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + .ctext = "\x87\x4d\x61\x91\xb6\x20\xe3\x26" + "\x1b\xef\x68\x64\x99\x0d\xb6\xce" + "\x98\x06\xf6\x6b\x79\x70\xfd\xff" + "\x86\x17\x18\x7b\xb9\xff\xfd\xff" + "\x5a\xe4\xdf\x3e\xdb\xd5\xd3\x5e" + "\x5b\x4f\x09\x02\x0d\xb0\x3e\xab" + "\x1e\x03\x1d\xda\x2f\xbe\x03\xd1" + "\x79\x21\x70\xa0\xf3\x00\x9c\xee", + .len = 64, + } +}; + +struct cipher_testvec aes_ctr_tv_template_192[] = { + { + .key = "\x8e\x73\xb0\xf7\xda\x0e\x64\x52" + "\xc8\x10\xf3\x2b\x80\x90\x79\xe5" + "\x62\xf8\xea\xd2\x52\x2c\x6b\x7b", + .klen = 24, + .iv = "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7" + "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff", + .iv_out = "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7" + "\xf8\xf9\xfa\xfb\xfc\xfd\xff\x03", + .ptext = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" + "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" + "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" + "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" + "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" + "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + .ctext = "\x1a\xbc\x93\x24\x17\x52\x1c\xa2" + "\x4f\x2b\x04\x59\xfe\x7e\x6e\x0b" + "\x09\x03\x39\xec\x0a\xa6\xfa\xef" + "\xd5\xcc\xc2\xc6\xf4\xce\x8e\x94" + "\x1e\x36\xb2\x6b\xd1\xeb\xc6\x70" + "\xd1\xbd\x1d\x66\x56\x20\xab\xf7" + "\x4f\x78\xa7\xf6\xd2\x98\x09\x58" + "\x5a\x97\xda\xec\x58\xc6\xb0\x50", + .len = 64, + } +}; + +struct cipher_testvec aes_ctr_tv_template_256[] = { + { + .key = "\x60\x3d\xeb\x10\x15\xca\x71\xbe" + "\x2b\x73\xae\xf0\x85\x7d\x77\x81" + "\x1f\x35\x2c\x07\x3b\x61\x08\xd7" + "\x2d\x98\x10\xa3\x09\x14\xdf\xf4", + .klen = 32, + .iv = "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7" + "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff", + .iv_out = "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7" + "\xf8\xf9\xfa\xfb\xfc\xfd\xff\x03", + .ptext = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" + "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" + "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" + "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" + "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" + "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + .ctext = "\x60\x1e\xc3\x13\x77\x57\x89\xa5" + "\xb7\xa7\xf5\x04\xbb\xf3\xd2\x28" + "\xf4\x43\xe3\xca\x4d\x62\xb5\x9a" + "\xca\x84\xe9\x90\xca\xca\xf5\xc5" + "\x2b\x09\x30\xda\xa2\x3d\xe9\x4c" + "\xe8\x70\x17\xba\x2d\x84\x98\x8d" + "\xdf\xc9\xc5\x8d\xb6\x7a\xad\xa6" + "\x13\xc2\xdd\x08\x45\x79\x41\xa6", + .len = 64, + } +}; + +/* 256bit */ +struct cipher_testvec aes_cbc_tv_template_256[] = { + { + .key = "\x60\x3d\xeb\x10\x15\xca\x71\xbe" + "\x2b\x73\xae\xf0\x85\x7d\x77\x81" + "\x1f\x35\x2c\x07\x3b\x61\x08\xd7" + "\x2d\x98\x10\xa3\x09\x14\xdf\xf4", + .klen = 32, + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .iv_out = "\xb2\xeb\x05\xe2\xc3\x9b\xe9\xfc" + "\xda\x6c\x19\x07\x8c\x6a\x9d\x1b", + .ptext = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" + "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" + "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" + "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" + "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" + "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + .ctext = "\xf5\x8c\x4c\x04\xd6\xe5\xf1\xba" + "\x77\x9e\xab\xfb\x5f\x7b\xfb\xd6" + "\x9c\xfc\x4e\x96\x7e\xdb\x80\x8d" + "\x67\x9f\x77\x7b\xc6\x70\x2c\x7d" + "\x39\xf2\x33\x69\xa9\xd9\xba\xcf" + "\xa5\x30\xe2\x63\x04\x23\x14\x61" + "\xb2\xeb\x05\xe2\xc3\x9b\xe9\xfc" + "\xda\x6c\x19\x07\x8c\x6a\x9d\x1b", + .len = 64, + } +}; + +struct cipher_testvec aes_ofb_tv_template_128[] = { + { + .key = "\x2b\x7e\x15\x16\x28\xae\xd2\xa6" + "\xab\xf7\x15\x88\x09\xcf\x4f\x3c", + .klen = 16, + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07\x08" + "\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .ptext = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" + "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" + "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" + "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" + "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" + "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + .ctext = "\x3b\x3f\xd9\x2e\xb7\x2d\xad\x20" + "\x33\x34\x49\xf8\xe8\x3c\xfb\x4a" + "\x77\x89\x50\x8d\x16\x91\x8f\x03" + "\xf5\x3c\x52\xda\xc5\x4e\xd8\x25" + "\x97\x40\x05\x1e\x9c\x5f\xec\xf6" + "\x43\x44\xf7\xa8\x22\x60\xed\xcc" + "\x30\x4c\x65\x28\xf6\x59\xc7\x78" + "\x66\xa5\x10\xd9\xc1\xd6\xae\x5e", + .len = 64, + } +}; + +//openssl create +struct cipher_testvec aes_ofb_tv_template_192[] = { + { + .key = "\x2b\x7e\x15\x16\x28\xae\xd2\xa6" + "\xab\xf7\x15\x88\x09\xcf\x4f\x3c" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .klen = 24, + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .ptext = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" + "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" + "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" + "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" + "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" + "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + .ctext = "\x6e\x29\x6a\xb1\x64\x8b\x7b\x81" + "\xfa\x62\x8f\xfa\xc6\x9f\x48\x6f" + "\x32\xe2\xaa\x04\x6a\x81\x04\xb8" + "\xc1\xe4\xe5\x1b\xb0\xc1\x89\xca" + "\x41\x6d\x43\xf1\x83\xf4\x9d\x90" + "\xbf\x68\xe6\xea\xd5\xed\x83\x1c" + "\xff\xf2\xf9\xfa\xf8\x3e\xba\x82" + "\x7e\xca\x94\x72\x64\x3f\x72\xdf", + .len = 64, + } +}; + +struct cipher_testvec aes_ofb_tv_template_256[] = { + { + .key = "\x2b\x7e\x15\x16\x28\xae\xd2\xa6" + "\xab\xf7\x15\x88\x09\xcf\x4f\x3c" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x00\x01\x02\x03\x04\x05\x06\x07", + .klen = 32, + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .ptext = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" + "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" + "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" + "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" + "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" + "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + .ctext = "\x36\x7d\xf9\x01\x2f\x31\xde\x8c" + "\x7f\xc1\x26\x1a\xbc\x8a\x35\xe5" + "\x00\x24\xad\xcb\x60\x5d\xb9\xea" + "\x12\xdd\x0b\xd2\x44\x2a\x24\x51" + "\x4f\x13\x1e\x7c\xa2\xad\xe9\x8c" + "\x55\x80\x75\xc6\x4d\xf2\x24\xde" + "\x30\xa0\xbb\xe7\x6d\xf8\xd1\x23" + "\x9d\x9f\xad\xd2\x9f\x87\x4f\x1c", + .len = 64, + } +}; + + +struct cipher_testvec aes_cfb_tv_template_128[] = { + { /* From NIST SP800-38A */ + .key = "\x2b\x7e\x15\x16\x28\xae\xd2\xa6" + "\xab\xf7\x15\x88\x09\xcf\x4f\x3c", + .klen = 16, + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .ptext = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" + "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" + "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" + "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" + "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" + "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + .ctext = "\x3b\x3f\xd9\x2e\xb7\x2d\xad\x20" + "\x33\x34\x49\xf8\xe8\x3c\xfb\x4a" + "\xc8\xa6\x45\x37\xa0\xb3\xa9\x3f" + "\xcd\xe3\xcd\xad\x9f\x1c\xe5\x8b" + "\x26\x75\x1f\x67\xa3\xcb\xb1\x40" + "\xb1\x80\x8c\xf1\x87\xa4\xf4\xdf" + "\xc0\x4b\x05\x35\x7c\x5d\x1c\x0e" + "\xea\xc4\xc6\x6f\x9f\xf7\xf2\xe6", + .len = 64, + } +}; + +struct cipher_testvec aes_cfb_tv_template_192[] = { + { + .key = "\x8e\x73\xb0\xf7\xda\x0e\x64\x52" + "\xc8\x10\xf3\x2b\x80\x90\x79\xe5" + "\x62\xf8\xea\xd2\x52\x2c\x6b\x7b", + .klen = 24, + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .ptext = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" + "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" + "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" + "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" + "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" + "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + .ctext = "\xcd\xc8\x0d\x6f\xdd\xf1\x8c\xab" + "\x34\xc2\x59\x09\xc9\x9a\x41\x74" + "\x67\xce\x7f\x7f\x81\x17\x36\x21" + "\x96\x1a\x2b\x70\x17\x1d\x3d\x7a" + "\x2e\x1e\x8a\x1d\xd5\x9b\x88\xb1" + "\xc8\xe6\x0f\xed\x1e\xfa\xc4\xc9" + "\xc0\x5f\x9f\x9c\xa9\x83\x4f\xa0" + "\x42\xae\x8f\xba\x58\x4b\x09\xff", + .len = 64, + } +}; + +struct cipher_testvec aes_cfb_tv_template_256[] = { + { + .key = "\x60\x3d\xeb\x10\x15\xca\x71\xbe" + "\x2b\x73\xae\xf0\x85\x7d\x77\x81" + "\x1f\x35\x2c\x07\x3b\x61\x08\xd7" + "\x2d\x98\x10\xa3\x09\x14\xdf\xf4", + .klen = 32, + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .ptext = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" + "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" + "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" + "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" + "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" + "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + .ctext = "\xdc\x7e\x84\xbf\xda\x79\x16\x4b" + "\x7e\xcd\x84\x86\x98\x5d\x38\x60" + "\x39\xff\xed\x14\x3b\x28\xb1\xc8" + "\x32\x11\x3c\x63\x31\xe5\x40\x7b" + "\xdf\x10\x13\x24\x15\xe5\x4b\x92" + "\xa1\x3e\xd0\xa8\x26\x7a\xe2\xf9" + "\x75\xa3\x85\x74\x1a\xb9\xce\xf8" + "\x20\x31\x62\x3d\x55\xb1\xe4\x71", + .len = 64, + } +}; + +struct cipher_testvec sm4_ctr_tv_template_128[] = { + { /* A.2.5.1 SM4-CTR Example 1 */ + .key = "\x01\x23\x45\x67\x89\xAB\xCD\xEF" + "\xFE\xDC\xBA\x98\x76\x54\x32\x10", + .klen = 16, + .ptext = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb" + "\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xee\xee\xee\xee\xee\xee\xee\xee" + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb", + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", + .iv_out = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0A\x0B\x0C\x0D\x0E\x13", + .ctext = "\xac\x32\x36\xcb\x97\x0c\xc2\x07" + "\x91\x36\x4c\x39\x5a\x13\x42\xd1" + "\xa3\xcb\xc1\x87\x8c\x6f\x30\xcd" + "\x07\x4c\xce\x38\x5c\xdd\x70\xc7" + "\xf2\x34\xbc\x0e\x24\xc1\x19\x80" + "\xfd\x12\x86\x31\x0c\xe3\x7b\x92" + "\x6e\x02\xfc\xd0\xfa\xa0\xba\xf3" + "\x8b\x29\x33\x85\x1d\x82\x45\x14", + .len = 64, + } +}; + +struct cipher_testvec sm4_ecb_tv_template_128[] = { + { /* A.2.1.1 SM4-ECB Example 1 */ + .key = "\x01\x23\x45\x67\x89\xAB\xCD\xEF" + "\xFE\xDC\xBA\x98\x76\x54\x32\x10", + .klen = 16, + .ptext = "\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb" + "\xcc\xcc\xcc\xcc\xdd\xdd\xdd\xdd" + "\xee\xee\xee\xee\xff\xff\xff\xff" + "\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb", + .ctext = "\x5e\xc8\x14\x3d\xe5\x09\xcf\xf7" + "\xb5\x17\x9f\x8f\x47\x4b\x86\x19" + "\x2f\x1d\x30\x5a\x7f\xb1\x7d\xf9" + "\x85\xf8\x1c\x84\x82\x19\x23\x04", + .len = 32, + } +}; + +//openssl create sm4_ofb template +struct cipher_testvec sm4_ofb_tv_template_128[] = { + { /* From NIST SP800-38A */ + .key = "\x2b\x7e\x15\x16\x28\xae\xd2\xa6" + "\xab\xf7\x15\x88\x09\xcf\x4f\x3c", + .klen = 16, + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .ptext = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a", + .ctext = "\xbc\x71\x0d\x76\x2d\x07\x0b\x26" + "\x36\x1d\xa8\x2b\x54\x56\x5e\x46", + .len = 16, + } +}; +//openssl create sm4_cfb template +struct cipher_testvec sm4_cfb_tv_template_128[] = { + { /* From NIST SP800-38A */ + .key = "\x2b\x7e\x15\x16\x28\xae\xd2\xa6" + "\xab\xf7\x15\x88\x09\xcf\x4f\x3c", + .klen = 16, + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .ptext = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a", + .ctext = "\xbc\x71\x0d\x76\x2d\x07\x0b\x26" + "\x36\x1d\xa8\x2b\x54\x56\x5e\x46", + .len = 16, + } +}; + +/* 128bit */ +struct aead_testvec aes_ccm_tv_template_128[] = { + { + .key = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" + "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf", + .klen = 16, + .iv = "\x01\x00\x00\x00\x03\x02\x01\x00" + "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00", + .assoc = "\x00\x01\x02\x03\x04\x05\x06\x07", + .alen = 8, + .ptext = "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e", + .plen = 23, + .ctext = "\x58\x8c\x97\x9a\x61\xc6\x63\xd2" + "\xf0\x66\xd0\xc2\xc0\xf9\x89\x80" + "\x6d\x5f\x6b\x61\xda\xc3\x84\x17" + "\xe8\xd1\x2c\xfd\xf9\x26\xe0", + .clen = 31, + } +}; + +/* 192bit */ +struct aead_testvec aes_ccm_tv_template_192[] = { + { + .key = "\x56\xdf\x5c\x8f\x26\x3f\x0e\x42" + "\xef\x7a\xd3\xce\xfc\x84\x60\x62" + "\xca\xb4\x40\xaf\x5f\xc9\xc9\x01", + .klen = 24, + .iv = "\x03\xd6\x3c\x8c\x86\x84\xb6\xcd" + "\xef\x09\x2e\x94\x00\x00\x00\x00", + .assoc = "\x02\x65\x78\x3c\xe9\x21\x30\x91" + "\xb1\xb9\xda\x76\x9a\x78\x6d\x95" + "\xf2\x88\x32\xa3\xf2\x50\xcb\x4c" + "\xe3\x00\x73\x69\x84\x69\x87\x79", + .alen = 32, + .ptext = "\x9f\xd2\x02\x4b\x52\x49\x31\x3c" + "\x43\x69\x3a\x2d\x8e\x70\xad\x7e" + "\xe0\xe5\x46\x09\x80\x89\x13\xb2" + "\x8c\x8b\xd9\x3f\x86\xfb\xb5\x6b", + .plen = 32, + .ctext = "\x39\xdf\x7c\x3c\x5a\x29\xb9\x62" + "\x5d\x51\xc2\x16\xd8\xbd\x06\x9f" + "\x9b\x6a\x09\x70\xc1\x51\x83\xc2" + "\x66\x88\x1d\x4f\x9a\xda\xe0\x1e" + "\xc7\x79\x11\x58\xe5\x6b\x20\x40" + "\x7a\xea\x46\x42\x8b\xe4\x6f\xe1", + .clen = 48, + } +}; + +/* 256bit */ +struct aead_testvec aes_ccm_tv_template_256[] = { + { + .key = "\xe0\x8d\x99\x71\x60\xd7\x97\x1a" + "\xbd\x01\x99\xd5\x8a\xdf\x71\x3a" + "\xd3\xdf\x24\x4b\x5e\x3d\x4b\x4e" + "\x30\x7a\xb9\xd8\x53\x0a\x5e\x2b", + .klen = 32, + .iv = "\x03\x1e\x29\x91\xad\x8e\xc1\x53" + "\x0a\xcf\x2d\xbe\x00\x00\x00\x00", + .assoc = "\x19\xb6\x1f\x57\xc4\xf3\xf0\x8b" + "\x78\x2b\x94\x02\x29\x0f\x42\x27" + "\x6b\x75\xcb\x98\x34\x08\x7e\x79" + "\xe4\x3e\x49\x0d\x84\x8b\x22\x87", + .alen = 32, + .ptext = "\xe1\xd9\xd8\x13\xeb\x3a\x75\x3f" + "\x9d\xbd\x5f\x66\xbe\xdc\xbb\x66" + "\xbf\x17\x99\x62\x4a\x39\x27\x1f" + "\x1d\xdc\x24\xae\x19\x2f\x98\x4c", + .plen = 32, + .ctext = "\x19\xb8\x61\x33\x45\x2b\x43\x96" + "\x6f\x51\xd0\x20\x30\x7d\x9b\xc6" + "\x26\x3d\xf8\xc9\x65\x16\xa8\x9f" + "\xf0\x62\x17\x34\xf2\x1e\x8d\x75" + "\x4e\x13\xcc\xc0\xc3\x2a\x54\x2d", + .clen = 40, + } +}; + +/* 128bit */ +struct aead_testvec aes_gcm_tv_template_128[] = { + { + .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c" + "\x6d\x6a\x8f\x94\x67\x30\x83\x08", + .klen = 16, + .iv = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad" + "\xde\xca\xf8\x88", + .ptext = "\xd9\x31\x32\x25\xf8\x84\x06\xe5" + "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" + "\x86\xa7\xa9\x53\x15\x34\xf7\xda" + "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" + "\x1c\x3c\x0c\x95\x95\x68\x09\x53" + "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" + "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57" + "\xba\x63\x7b\x39\x1a\xaf\xd2\x55", + .plen = 64, + .ctext = "\x42\x83\x1e\xc2\x21\x77\x74\x24" + "\x4b\x72\x21\xb7\x84\xd0\xd4\x9c" + "\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0" + "\x35\xc1\x7e\x23\x29\xac\xa1\x2e" + "\x21\xd5\x14\xb2\x54\x66\x93\x1c" + "\x7d\x8f\x6a\x5a\xac\x84\xaa\x05" + "\x1b\xa3\x0b\x39\x6a\x0a\xac\x97" + "\x3d\x58\xe0\x91\x47\x3f\x59\x85" + "\x4d\x5c\x2a\xf3\x27\xcd\x64\xa6" + "\x2c\xf3\x5a\xbd\x2b\xa6\xfa\xb4", + .clen = 80, + } +}; + +/* 192bit */ +struct aead_testvec aes_gcm_tv_template_192[] = { + { + .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c" + "\x6d\x6a\x8f\x94\x67\x30\x83\x08" + "\xfe\xff\xe9\x92\x86\x65\x73\x1c", + .klen = 24, + .iv = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad" + "\xde\xca\xf8\x88", + .ptext = "\xd9\x31\x32\x25\xf8\x84\x06\xe5" + "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" + "\x86\xa7\xa9\x53\x15\x34\xf7\xda" + "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" + "\x1c\x3c\x0c\x95\x95\x68\x09\x53" + "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" + "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57" + "\xba\x63\x7b\x39\x1a\xaf\xd2\x55", + .plen = 64, + .ctext = "\x39\x80\xca\x0b\x3c\x00\xe8\x41" + "\xeb\x06\xfa\xc4\x87\x2a\x27\x57" + "\x85\x9e\x1c\xea\xa6\xef\xd9\x84" + "\x62\x85\x93\xb4\x0c\xa1\xe1\x9c" + "\x7d\x77\x3d\x00\xc1\x44\xc5\x25" + "\xac\x61\x9d\x18\xc8\x4a\x3f\x47" + "\x18\xe2\x44\x8b\x2f\xe3\x24\xd9" + "\xcc\xda\x27\x10\xac\xad\xe2\x56" + "\x99\x24\xa7\xc8\x58\x73\x36\xbf" + "\xb1\x18\x02\x4d\xb8\x67\x4a\x14", + .clen = 80, + } +}; + +/* 256bit */ +struct aead_testvec aes_gcm_tv_template_256[] = { + { + .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c" + "\x6d\x6a\x8f\x94\x67\x30\x83\x08" + "\xfe\xff\xe9\x92\x86\x65\x73\x1c" + "\x6d\x6a\x8f\x94\x67\x30\x83\x08", + .klen = 32, + .iv = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad" + "\xde\xca\xf8\x88", + .ptext = "\xd9\x31\x32\x25\xf8\x84\x06\xe5" + "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" + "\x86\xa7\xa9\x53\x15\x34\xf7\xda" + "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" + "\x1c\x3c\x0c\x95\x95\x68\x09\x53" + "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" + "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57" + "\xba\x63\x7b\x39", + .plen = 60, + .assoc = "\xfe\xed\xfa\xce\xde\xad\xbe\xef" + "\xfe\xed\xfa\xce\xde\xad\xbe\xef" + "\xab\xad\xda\xd2", + .alen = 20, + .ctext = "\x52\x2d\xc1\xf0\x99\x56\x7d\x07" + "\xf4\x7f\x37\xa3\x2a\x84\x42\x7d" + "\x64\x3a\x8c\xdc\xbf\xe5\xc0\xc9" + "\x75\x98\xa2\xbd\x25\x55\xd1\xaa" + "\x8c\xb0\x8e\x48\x59\x0d\xbb\x3d" + "\xa7\xb0\x8b\x10\x56\x82\x88\x38" + "\xc5\xf6\x1e\x63\x93\xba\x7a\x0a" + "\xbc\xc9\xf6\x62" + "\x76\xfc\x6e\xce\x0f\x4e\x17\x68" + "\xcd\xdf\x88\x53\xbb\x2d\x55\x1b", + .clen = 76, + } +}; + +struct aead_testvec hmac_sha256_aes_cbc_tv_temp[] = { + { +#ifdef __LITTLE_ENDIAN + .key = "\x08\x00" /* rta length */ + "\x01\x00" /* rta type */ +#else + .key = "\x00\x08" /* rta length */ + "\x00\x01" /* rta type */ +#endif + "\x00\x00\x00\x10" /* enc key length */ + "\x20\x21\x22\x23\x24\x25\x26\x27" + "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" + "\x30\x31\x32\x33\x34\x35\x36\x37" + "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" + "\xc2\x86\x69\x6d\x88\x7c\x9a\xa0" + "\x61\x1b\xbb\x3e\x20\x25\xa4\x5a", + .klen = 8 + 32 + 16, + .iv = "\x56\x2e\x17\x99\x6d\x09\x3d\x28" + "\xdd\xb3\xba\x69\x5a\x2e\x6f\x58", + .assoc = "\x56\x2e\x17\x99\x6d\x09\x3d\x28" + "\xdd\xb3\xba\x69\x5a\x2e\x6f\x58", + .alen = 16, + .ptext = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", + .plen = 32, + .ctext = "\xd2\x96\xcd\x94\xc2\xcc\xcf\x8a" + "\x3a\x86\x30\x28\xb5\xe1\xdc\x0a" + "\x75\x86\x60\x2d\x25\x3c\xff\xf9" + "\x1b\x82\x66\xbe\xa6\xd6\x1a\xb1" + "\xf5\x33\x53\xf3\x68\x85\x2a\x99" + "\x0e\x06\x58\x8f\xba\xf6\x06\xda" + "\x49\x69\x0d\x5b\xd4\x36\x06\x62" + "\x35\x5e\x54\x58\x53\x4d\xdf\xbf", + .clen = 32 + 32, + } +}; + +/* 128bit */ +struct aead_testvec sm4_ccm_tv_template_128[] = { + { + .key = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" + "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf", + .klen = 16, + .iv = "\x01\x00\x00\x00\x03\x02\x01\x00" + "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00", + .assoc = "\x00\x01\x02\x03\x04\x05\x06\x07", + .alen = 8, + .ptext = "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e", + .plen = 23, + .ctext = "\x7B\xFF\x4A\x15\xF5\x73\xCE\x82" + "\x6E\xC2\x31\x1D\xE2\x53\x02\xAC" + "\xA4\x48\xF9\xE4\xF5\x1F\x81\x70" + "\x18\xBC\xB6\x84\x01\xB8\xAE", + .clen = 31, + } +}; + +/* 128bit */ +struct aead_testvec sm4_gcm_tv_template_128[] = { + { + .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c" + "\x6d\x6a\x8f\x94\x67\x30\x83\x08", + .klen = 16, + .iv = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad" + "\xde\xca\xf8\x88", + .ptext = "\xd9\x31\x32\x25\xf8\x84\x06\xe5" + "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" + "\x86\xa7\xa9\x53\x15\x34\xf7\xda" + "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" + "\x1c\x3c\x0c\x95\x95\x68\x09\x53" + "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" + "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57" + "\xba\x63\x7b\x39\x1a\xaf\xd2\x55", + .plen = 64, + .ctext = "\xe4\x11\x0f\xf1\xc1\x41\x97\xe6" + "\x76\x21\x6a\x33\x83\x10\x41\xeb" + "\x09\x58\x00\x11\x7b\xdc\x3f\x75" + "\x1a\x49\x6e\xfc\xf2\xbb\xdf\xdb" + "\x3a\x2e\x13\xfd\xc5\xc1\x9d\x07" + "\x1a\xe5\x48\x3f\xed\xde\x98\x5d" + "\x3f\x2d\x5b\x4e\xee\x0b\xb6\xdf" + "\xe3\x63\x36\x83\x23\xf7\x5b\x80" + "\x7d\xfe\x77\xef\x71\xb1\x5e\xc9" + "\x52\x6b\x09\xab\x84\x28\x4b\x8a", + .clen = 80, + } +}; + +struct hash_testvec sm3_tv_template[] = { +/* { + .plaintext = "abc", + .psize = 3, + .digest = "\x66\xC7\xF0\xF4\x62\xEE\xED\xD9" + "\xD1\xF2\xD4\x6B\xDC\x10\xE4\xE2" + "\x41\x67\xC4\x87\x5C\xF2\xF7\xA2" + "\x29\x7D\xA0\x2B\x8F\x4B\xA8\xE0", + }*/ + { + .plaintext = "abcdefghijklmnopqrstuvwxyz", + .psize = 26, + .digest = "\xB8\x0F\xE9\x7A\x4D\xA2\x4A\xFC" + "\x27\x75\x64\xF6\x6A\x35\x9E\xF4" + "\x40\x46\x2A\xD2\x8D\xCC\x6D\x63" + "\xAD\xB2\x4D\x5C\x20\xA6\x15\x95", + } +}; + +struct hash_testvec hmac_sm3_tv_template[] = { + { + .key = "Jefe", + .ksize = 4, + .plaintext = "what do ya want for nothing?", + .psize = 28, + .digest = "\x2e\x87\xf1\xd1\x68\x62\xe6\xd9" + "\x64\xb5\x0a\x52\x00\xbf\x2b\x10" + "\xb7\x64\xfa\xa9\x68\x0a\x29\x6a" + "\x24\x05\xf2\x4b\xec\x39\xf8\x82", + }, +}; + +struct hash_testvec md5_tv_template[] = { + { + .plaintext = "abcdefghijklmnopqrstuvwxyz", + .psize = 26, + .digest = "\xc3\xfc\xd3\xd7\x61\x92\xe4\x00" + "\x7d\xfb\x49\x6c\xca\x67\xe1\x3b", + } +}; + +struct hash_testvec hmac_md5_tv_template[] = +{ + { + .key = "Jefe", + .ksize = 4, + .plaintext = "what do ya want for nothing?", + .psize = 28, + .digest = "\x75\x0C\x78\x3E\x6A\xB0\xB5\x03" + "\xEA\xA8\x6E\x31\x0A\x5D\xB7\x38" + }, +}; + +struct hash_testvec sha1_tv_template[] = { + { + .plaintext = "abc", + .psize = 3, + .digest = "\xa9\x99\x3e\x36\x47\x06\x81\x6a\xba\x3e" + "\x25\x71\x78\x50\xc2\x6c\x9c\xd0\xd8\x9d", + } +}; + +struct hash_testvec hmac_sha1_tv_template[] = { + { + .key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", + .ksize = 20, + .plaintext = "Hi There", + .psize = 8, + .digest = "\xb6\x17\x31\x86\x55\x05\x72\x64" + "\xe2\x8b\xc0\xb6\xfb\x37\x8c\x8e\xf1" + "\x46\xbe", + } +}; + +struct hash_testvec sha256_tv_template[] = { + { + .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-", + .psize = 64, + .digest = "\xb5\xfe\xad\x56\x7d\xff\xcb\xa4" + "\x2c\x32\x29\x32\x19\xbb\xfb\xfa" + "\xd6\xff\x94\xa3\x72\x91\x85\x66" + "\x3b\xa7\x87\x77\x58\xa3\x40\x3a", + } +}; + +struct hash_testvec hmac_sha256_tv_template[] = { + { + .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa", + .ksize = 32, + .plaintext = "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd", + .psize = 50, + .digest = "\xcd\xcb\x12\x20\xd1\xec\xcc\xea" + "\x91\xe5\x3a\xba\x30\x92\xf9\x62" + "\xe5\x49\xfe\x6c\xe9\xed\x7f\xdc" + "\x43\x19\x1f\xbd\xe4\x5c\x30\xb0", + } +}; + +struct hash_testvec sha224_tv_template[] = { + { + .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-", + .psize = 64, + .digest = "\xc4\xdb\x2b\x3a\x58\xc3\x99\x01" + "\x42\xfd\x10\x92\xaa\x4e\x04\x08" + "\x58\xbb\xbb\xe8\xf8\x14\xa7\x0c" + "\xef\x3b\xcb\x0e", + } +}; + +struct hash_testvec hmac_sha224_tv_template[] = { + { + .key = "Jefe", + .ksize = 4, + /* ("what do ya want for nothing?") */ + .plaintext = "\x77\x68\x61\x74\x20\x64\x6f\x20" + "\x79\x61\x20\x77\x61\x6e\x74\x20" + "\x66\x6f\x72\x20\x6e\x6f\x74\x68" + "\x69\x6e\x67\x3f", + .psize = 28, + .digest = "\xa3\x0e\x01\x09\x8b\xc6\xdb\xbf" + "\x45\x69\x0f\x3a\x7e\x9e\x6d\x0f" + "\x8b\xbe\xa2\xa3\x9e\x61\x48\x00" + "\x8f\xd0\x5e\x44", + } +}; + +struct hash_testvec sha384_tv_template[] = { + { + .plaintext = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" + "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + .psize = 112, + .digest = "\x09\x33\x0c\x33\xf7\x11\x47\xe8" + "\x3d\x19\x2f\xc7\x82\xcd\x1b\x47" + "\x53\x11\x1b\x17\x3b\x3b\x05\xd2" + "\x2f\xa0\x80\x86\xe3\xb0\xf7\x12" + "\xfc\xc7\xc7\x1a\x55\x7e\x2d\xb9" + "\x66\xc3\xe9\xfa\x91\x74\x60\x39", + } +}; + +struct hash_testvec hmac_sha384_tv_template[] = { + { + .key = "Jefe", + .ksize = 4, + .plaintext = "what do ya want for nothing?", + .psize = 28, + .digest = "\xaf\x45\xd2\xe3\x76\x48\x40\x31" + "\x61\x7f\x78\xd2\xb5\x8a\x6b\x1b" + "\x9c\x7e\xf4\x64\xf5\xa0\x1b\x47" + "\xe4\x2e\xc3\x73\x63\x22\x44\x5e" + "\x8e\x22\x40\xca\x5e\x69\xe2\xc7" + "\x8b\x32\x39\xec\xfa\xb2\x16\x49", + } +}; + +struct hash_testvec sha512_tv_template[] = { + { + .plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + .psize = 56, + .digest = "\x20\x4a\x8f\xc6\xdd\xa8\x2f\x0a" + "\x0c\xed\x7b\xeb\x8e\x08\xa4\x16" + "\x57\xc1\x6e\xf4\x68\xb2\x28\xa8" + "\x27\x9b\xe3\x31\xa7\x03\xc3\x35" + "\x96\xfd\x15\xc1\x3b\x1b\x07\xf9" + "\xaa\x1d\x3b\xea\x57\x78\x9c\xa0" + "\x31\xad\x85\xc7\xa7\x1d\xd7\x03" + "\x54\xec\x63\x12\x38\xca\x34\x45", + } +}; + +struct hash_testvec hmac_sha512_tv_template[] = { + { + .key = "Jefe", + .ksize = 4, + .plaintext = "what do ya want for nothing?", + .psize = 28, + .digest = "\x16\x4b\x7a\x7b\xfc\xf8\x19\xe2" + "\xe3\x95\xfb\xe7\x3b\x56\xe0\xa3" + "\x87\xbd\x64\x22\x2e\x83\x1f\xd6" + "\x10\x27\x0c\xd7\xea\x25\x05\x54" + "\x97\x58\xbf\x75\xc0\x5a\x99\x4a" + "\x6d\x03\x4f\x65\xf8\xf0\xe6\xfd" + "\xca\xea\xb1\xa3\x4d\x4a\x6b\x4b" + "\x63\x6e\x07\x0a\x38\xbc\xe7\x37", + } +}; + +struct hash_testvec sha512_224_tv_template[] = { + { + .plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + .psize = 56, + .digest = "\xe5\x30\x2d\x6d\x54\xbb\x24\x22" + "\x75\xd1\xe7\x62\x2d\x68\xdf\x6e" + "\xb0\x2d\xed\xd1\x3f\x56\x4c\x13" + "\xdb\xda\x21\x74", + } +}; + +struct hash_testvec hmac_sha512_224_tv_template[] = { + { + .key = "Jefe", + .ksize = 4, + .plaintext = "what do ya want for nothing?", + .psize = 28, + .digest = "\x4a\x53\x0b\x31\xa7\x9e\xbc\xce" + "\x36\x91\x65\x46\x31\x7c\x45\xf2" + "\x47\xd8\x32\x41\xdf\xb8\x18\xfd" + "\x37\x25\x4b\xde", + }, +}; + +struct hash_testvec sha512_256_tv_template[] = { + { + .plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + .psize = 56, + .digest = "\xbd\xe8\xe1\xf9\xf1\x9b\xb9\xfd" + "\x34\x06\xc9\x0e\xc6\xbc\x47\xbd" + "\x36\xd8\xad\xa9\xf1\x18\x80\xdb" + "\xc8\xa2\x2a\x70\x78\xb6\xa4\x61", + } +}; + +struct hash_testvec hmac_sha512_256_tv_template[] = { + { + .key = "Jefe", + .ksize = 4, + .plaintext = "what do ya want for nothing?", + .psize = 28, + .digest = "\x6d\xf7\xb2\x46\x30\xd5\xcc\xb2" + "\xee\x33\x54\x07\x08\x1a\x87\x18" + "\x8c\x22\x14\x89\x76\x8f\xa2\x02" + "\x05\x13\xb2\xd5\x93\x35\x94\x56", + }, +}; + +struct hash_testvec long_hash_tv_template[] = { + { +/* +md5 (stdin)= A89D2C8730E3BB304EDA507035928B86 +sha1 (stdin)= D2E8068B6B648B8793B7DA8D575AE57FA208FD66 +sha256 (stdin)= 1CEA48E3960EE3675BD5663C5F423325110000D26DE11C9B11B0293386C030C0 +sha224 (stdin)= ADBEC39512DCA87CCFD155BB635F519E7B46796C722CC650233BF106 +sha384 (stdin)= 18AB6F0018884BBF7CE7015168B691FEC8A2E15892689E4D632099162 + 54A2A6B527D2DFC0144D5CEECC339857B968308 + */ + .key = "Huawei12", + .ksize = 8, + .plaintext = "\x09\x9f\x13\xaa\x41\x68\x4c\xe3" + "\x5a\x11\x85\xac\xb3\x27\xbe\x55" + "\xec\x60\xf7\x8d\x02\x99\x30\xc7" + "\x4b\xd2\x69\x23\x74\x0b\xa2\x16" + "\xad\x44\xdb\x4f\xe6\x7d\x14\x88" + "\x2f\xb6\x2a\xc1\x58\xef\x63\xfa" + "\x71\x05\x9c\x33\xca\x3e\xd5\x6c" + "\x23\x77\x0e\xa5\x19\xb0\x47\xde" + "\x52\x65\x80\x17\x8b\x22\xb9\x2d" + "\xc4\x5b\xf2\x66\xfd\x94\x08\x9f" + "\x36\xcd\x41\xd8\x6f\x06\x7a\x11" + "\xa8\x1c\xb3\x4a\xe1\x55\xec\x83" + "\x1a\x8e\x25\xbc\x70\xc7\x5e\xf5" + "\x69\x00\x97\x0b\xa2\x39\xd0\x44" + "\xdb\x72\x09\x7d\x14\xab\x1f\xb6" + "\x4d\x87\x58\xef\x86\x1d\x91\x28" + "\xbf\x33\xca\x61\xf8\x6c\x03\x9a" + "\x0e\xa5\x3c\xd3\x49\xde\x75\x0c" + "\x80\x17\xae\x22\xb9\x50\xe7\x5b" + "\xf2\x90\x20\x67\x2b\xc2\x36\xcd" + "\x64\xfb\x6f\x06\x9d\x11\xa8\x3f" + "\xd6\x4a\xe1\x78\x0f\x83\x1a\xb1" + "\x25\xbc\x53\xea\x5e\xf5\x8c\x00" + "\x97\x45\xc5\x39\xd0\x67\xfe\x72" + "\x09\xa0\x14\xab\x02\xd9\x4d\xe4" + "\x0e\xa5\x3c\xd3\x49\xde\x75\x0c" + "\xed\x61\xf8\x8f\x03\x9a\x31\xc8" + "\x3c\xd3\x67\x01\x75\x0c\xa3\x17" + "\xae\x45\xdc\x50\xe7\x7e\x15\x89" + "\x20\xb7\x2b\xc2\x59\xf0\x64\xfb" + "\x92\x06\x9d\x33\xca\x3e\xd5\x6c" + "\x04\x78\x0f\xa6\x1a\xb1\x48\xdf" + "\x53\xea\x81\x18\x8c\x23\xba\x2e" + "\xc5\x5c\xf3\x67\xfe\x95\x09\xa0" + "\x37\xce\x42\xd9\x70\x07\x7b\x12" + "\xa9\x1d\xb4\x4b\xe2\x56\xed\x84" + "\x1b\x8f\x26\xbd\x31\xc8\x5f\xf6" + "\x6a\x01\x98\x0c\xa3\x3a\xd1\x45" + "\xdc\x73\x0a\x7e\x15\xac\x20\xb7" + "\xd6\x4a\xe1\x78\x0f\x83\x1a\xb1" + "\xc0\x34\xcb\x62\xf9\x6d\x04\x9b" + "\x0f\xa6\x3d\xd4\x48\xdf\x76\x0d" + "\x81\x18\xaf\x23\xba\x51\xe8\x5c" + "\xf3\x8a\x21\x95\x2c\xc3\x37\xce" + "\x65\xfc\x70\x07\x9e\x12\xa9\x40" + "\xd7\x4b\xe2\x79\x10\x84\x1b\xb2" + "\x26\xbd\x54\xbd\x31\xc8\x5f\xf6" + "\x98\x2f\xc6\x3a\xd1\x68\xff\x73" + "\x0a\xa1\x15\xac\x43\xda\x4e\xe5" + "\x7c\x13\x87\x1e\xb5\x29\xc0\x57" + "\xee\x62\xf9\x90\x04\x9b\x32\xc9" + "\x3d\xd4\x6b\x02\x76\x0d\xa4\x18" + "\xaf\x46\xdd\x51\xe8\x7f\x16\x8a" + "\x21\xb8\x2c\xc3\x5a\xf1\x65\xfc" + "\x93\x07\x9e\x35\xcc\x40\xd7\x6e" + "\x05\x79\x10\xa7\x1b\xb2\x49\xe0" + "\x20\xb7\x2b\xc2\x59\xf0\x64\xfb" + "\x92\x06\x9d\x33\xca\x3e\xd5\x6c" + "\x04\x78\x0f\xa6\x1a\xb1\x48\xdf" + "\xaa\x1e\xb5\x4c\xe3\x57\xee\x85" + "\x1c\x90\x27\xbe\x32\xc9\x60\xf7" + "\x6b\x02\x99\x0d\xa4\x3b\xd2\x46" + "\xdd\x74\x0b\x7f\x16\xad\x21\xb8" + "\xd7\x4b\xe2\x79\x10\x84\x1b\xb2" + "\x26\xbd\x54\xbd\x31\xc8\x5f\xf6" + "\x10\xa7\x3e\xd5\x49\xe0\x77\x0e" + "\x82\x19\xb0\x24\xbb\x52\xe9\x5d" + "\xf4\x8b\x22\x96\x2d\xc4\x38\xcf" + "\x66\xfd\x71\x98\x9f\x13\xaa\x41" + "\xd8\x4c\xe3\x7a\x11\x85\x1c\xb3" + "\x27\xbe\x55\xec\x60\xf7\x8e\x02" + "\x99\x30\xc7\x3b\xd2\x69\x00\x74" + "\x0b\xa2\x16\xad\x44\xdb\x4f\xe6" + "\x7d\x14\x88\x1f\xb6\x2a\xc1\x58" + "\xef\x78\xfa\x91\x05\x9c\x33\xca" + "\x3e\xd5\x6c\x03\x77\x0e\xa5\x19" + "\xb0\x47\xde\x52\xe9\x80\x17\x8b" + "\x22\xb9\x2d\xc4\x5b\xf2\x66\xfd" + "\x94\x08\x9f\x36\xcd\x41\xd8\x6f" + "\x06\x7a\x11\xa8\x56\xb3\x4a\xe1" + "\x55\xec\x83\x1a\x8e\x25\xbc\x30" + "\xc7\x5e\xf5\x69\x00\x97\x0b\xa2" + "\x05\x79\x10\xa7\x1b\x09\x7d\x14" + "\xab\x1f\xb6\x4d\xe4\x58\xef\x86" + "\x1d\x91\x28\xbf\x33\xca\x61\xf8" + "\x6c\x03\x9a\x0e\xa5\x3c\xd3\x47" + "\xde\x75\x0c\x80\x17\xae\x22\xb9" + "\x50\xe7\x5b\xf2\x89\x20\x94\x2b" + "\xc2\x36\xcd\x64\xfb\x6f\x06\x9d" + "\x11\xa8\x3f\xd6\x4a\xe1\x78\x0f" + "\x83\x1a\xb1\x25\xbc\x53\xea\x5e" + "\xf5\x8c\x00\x97\x2e\xc5\x39\xd0" + "\x67\xfe\x72\x09\xa0\x14\xab\x42" + "\x0d\xa4\x18\xaf\x46\xdd\x51\xe8" + "\x28\xbf\x56\xed\x61\xf8\x8f\x03" + "\x9a\x31\xc8\x3c\xd3\x6a\x01\x75" + "\x0c\xec\x83\x1a\x8e\x25\xbc\x30" + "\x7e\x15\x89\x20\xb7\x2b\xc2\x59" + "\xf0\x64\xfb\x92\x06\x9d\x34\xcb" + "\x3f\xd6\x6d\x04\x78\x0f\xa6\x1a" + "\xb1\x48\xff\x53\xea\x81\x18\x8c" + "\x23\xba\x2e\xc5\x5c\xf3\x67\xfe" + "\x95\x09\x34\x37\xce\x42\xd9\x70" + "\x07\x7b\x12\xa9\x1d\xb4\x4b\xe2" + "\x56\xed\x84\x1b\x8f\x26\xbd\x31" + "\x45\x5f\xf6\x6a\x01\x98\x0c\xa3" + "\x3a\xd1\x45\xdc\x73\x0a\x7e\x15" + "\xac\x20\xb7\x4e\xe5\x59\xf0\x87" + "\x1e\x92\x29\xc0\x25\xcb\x62\xf9" + "\x6d\x04\x9b\x0f\xa6\x3d\xd4\x48" + "\xdf\x76\x0d\x81\x18\xaf\x23\xba" + "\x51\xe8\x5c\x1a\x8e\x25\xbc\x30" + "\xc3\x37\xce\x65\xfc\x70\x07\x9e" + "\x12\xa9\x40\xd7\x4b\xe2\x79\x10" + "\x84\x1b\xb2\x26\xbd\x54\xeb\x5f" + "\xf6\x8d\x01\x98\x2f\xc6\x3a\xd1" + "\x68\xff\x73\x0a\xa1\x15\xac\x43" + "\xda\x4e\xe5\x7c\x13\x87\x1e\xb5" + "\x29\xc0\x57\xee\x62\xf9\x90\x04" + "\x9b\x32\xc9\x3d\xd4\x6b\x02\x76" + "\x0d\xa4\x18\xaf\x46\xdd\x51\xe8" + "\x7f\x16\x8a\x21\xb8\x2c\xc3\x5a" + "\xf1\x65\xfc\x93\x07\x9e\x35\xcc" + "\xd9\x4d\xe4\x7b\x12\x86\x1d\xb4" + "\xb2\x49\xe0\x54\xeb\x82\x19\x8d" + "\x24\xbb\x2f\xc6\x5d\xf4\x68\xff" + "\x96\x0a\x45\x38\xcf\x43\xda\x71" + "\x08\x7c\x13\xaa\x1e\x76\x4c", + .psize = 1023, + } +}; + +struct hash_testvec hmac_abnormal1024_tv_template[] = { + { + .key = "\xab\xfc\x93\x07\x9e\xaa\xbc\x0f" + "\x68\xff\x73\x0a\xa1\x15\xac\x43" + "\xda\x4e\xe5\x7c\x13\x87\x1e\xb5" + "\x29\xc0\x57\xee\x62\xf9\x90\x04" + "\x9b\x32\xc9\x3d\xd4\x6b\x02\x76" + "\x0d\xa4\x18\xaf\x46\xdd\x51\xe8" + "\x7f\x16\x8a\x21\xb8\x2c\xc3\x5a" + "\xf1\x65\xfc\x93\x07\x9e\x35\xcc" + "\x07\xd0\x15\x89\x19\x01\x01\xa2" + "\x54\x18\x5e\x6a\x16\x93\x6e\x56" + "\x43\x19\x1f\xbd\xe4\x5c\x30\xb0" + "\x67\x17\x21\xc7\x6e\x8a\xd5\x49" + "\xac\x20\xb7\x4e\xe5\x59\xf0\x87" + "\x97\x9b\x0f\x15\x56\x6a\x8f\x6d" + "\x21\x2f\x2c\x02\xa4\xe0\x78\x65" + "\xbc\x53\xea\x5e\xf5\x8c\x00\xa3" + "\xab\xca\x0f\x0e", + .ksize = 132, + .plaintext = "Test Using Texts" + "r Than BlockSize" + "e aKey Hash Keys" + " First", + .psize = 54, + } +}; + +struct hash_testvec hmac_abnormal512_tv_template[] = { + { + .key = "\x07\xd0\x15\x89\x19\x01\x01\xa2" + "\x54\x18\x5e\x6a\x16\x93\x6e\x56" + "\x43\x19\x1f\xbd\xe4\x5c\x30\xb0" + "\x67\x17\x21\xc7\x6e\x8a\xd5\x49" + "\xac\x20\xb7\x4e\xe5\x59\xf0\x87" + "\x97\x9b\x0f\x15\x56\x6a\x8f\x6d" + "\x21\x2f\x2c\x02\xa4\xe0\x78\x65" + "\xbc\x53\xea\x5e\xf5\x8c\x00\xa3" + "\xab\xca\x0f\x68", + .ksize = 68, + .plaintext = "Test Using Texts" + "r Than BlockSize" + "e aKey Hash Keys" + " First", + .psize = 54, + } +}; + + +#endif diff --git a/uadk/v1/test/hisi_sec_test_sgl/Makefile.am b/uadk/v1/test/hisi_sec_test_sgl/Makefile.am new file mode 100644 index 0000000..f7f1ffd --- /dev/null +++ b/uadk/v1/test/hisi_sec_test_sgl/Makefile.am @@ -0,0 +1,14 @@ +AM_CFLAGS=-Wall -O0 -fno-strict-aliasing -I$(top_srcdir) -I$(top_srcdir)/include -I$(srcdir) -pthread + +if WITH_OPENSSL_DIR +bin_PROGRAMS=test_hisi_sec_sgl + +test_hisi_sec_sgl_SOURCES=test_hisi_sec_sgl.c test_hisi_sec_sgl.h + +if WD_STATIC_DRV +test_hisi_sec_sgl_LDADD=../../../.libs/libwd.la $(with_openssl_dir)/libcrypto_wd.so +else +test_hisi_sec_sgl_LDADD=../../../.libs/libwd.so $(with_openssl_dir)/libcrypto_wd.so +endif + +endif diff --git a/uadk/v1/test/hisi_sec_test_sgl/test_hisi_sec_sgl.c b/uadk/v1/test/hisi_sec_test_sgl/test_hisi_sec_sgl.c new file mode 100644 index 0000000..b7513d1 --- /dev/null +++ b/uadk/v1/test/hisi_sec_test_sgl/test_hisi_sec_sgl.c @@ -0,0 +1,2809 @@ +/* + * Copyright 2020 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#include +#include +#include +#define __USE_GNU +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "test_hisi_sec_sgl.h" +#include "../../wd.h" +#include "../../wd_cipher.h" +#include "../../wd_aead.h" +#include "../../wd_digest.h" +#include "../../wd_bmm.h" +#include "../../wd_sgl.h" +#include "../../wd_util.h" + +#define SEC_TST_PRT printf +#define TEST_MAX_THRD 128 +#define SQE_SIZE 128 +#define MAX_BLOCK_SZ 1024 +#define MAX_BLOCK_NM 128 +#define MAX_ALGO_PER_TYPE 12 + +#define DEBUG 1 + +typedef unsigned char u8; +typedef unsigned int u32; + +static int q_num = 1; +static int ctx_num_per_q = 1; +static long long g_total_perf = 0; +enum alg_class g_algclass = CIPHER_CLASS; +enum cipher_op_type alg_op_type; + +pthread_mutex_t perf_mutex; + +struct test_sec_pthread_dt { + int cpu_id; + enum cipher_op_type op_type; + int thread_num; + void *pool; + void *q; + struct timeval start_tval; + u32 send_task_num; + u32 recv_task_num; + __u16 data_fmt; +}; + +struct cipher_async_tag { + void *ctx; + int thread_id; + int cnt; + struct test_sec_pthread_dt *thread_info; +}; + +struct digest_async_tag { + void *ctx; + int thread_id; + int cnt; + struct test_sec_pthread_dt *thread_info; +}; + +/* OpenSSL Skcipher APIS */ +static int t_times = 1000; +static int t_seconds = 0; +static int pktlen = 1024; +static int g_testalg = 0; + +static pthread_t system_test_thrds[TEST_MAX_THRD]; +static struct test_sec_pthread_dt test_thrds_data[TEST_MAX_THRD]; +static volatile int asyn_thread_exit = 0; +static u32 g_keylen = 16; +static u32 g_ivlen = 16; + +char *skcipher_names[MAX_ALGO_PER_TYPE] = + {"ecb(aes)", "cbc(aes)", "xts(aes)", "ofb(aes)", "cfb(aes)", "ecb(des3_ede)", + "cbc(des3_ede)", "cbc(sm4)", "xts(sm4)", "ofb(sm4)", "cfb(sm4)", NULL,}; +static inline int _get_cpu_id(int thr, __u64 core_mask) +{ + __u64 i; + int cnt = 0; + + for (i = 1; i < 64; i++) { + if (core_mask & (0x1ull << i)) { + if (thr == cnt) + return i; + cnt++; + } + } + + return 0; +} + +static inline int _get_one_bits(__u64 val) +{ + int count = 0; + + while (val) { + if (val % 2 == 1) + count++; + val = val / 2; + } + + return count; +} + +static bool is_exit(struct test_sec_pthread_dt *pdata) +{ + struct timeval cur_tval; + float time_used; + + gettimeofday(&cur_tval, NULL); + time_used = (float)((cur_tval.tv_sec - pdata->start_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - pdata->start_tval.tv_usec); + if (t_seconds) + return time_used >= t_seconds * t_times; + else if (t_times) + return pdata->send_task_num >= t_times; + + return false; +} + +void hexdump(char *buf, int num) +{ + int i; + + for (i = 0; i < num; i++) { + printf("\\%02X", buf[i]); + if ((i + 1) % 8 == 0) + printf("\n"); + } + printf("\n"); + return; +} + +int get_resource(struct cipher_testvec **alg_tv, int* alg, int* mode) +{ + struct cipher_testvec *tv; + int alg_type; + int mode_type; + + switch (g_testalg) { + case 0: + alg_type = WCRYPTO_CIPHER_AES; + mode_type = WCRYPTO_CIPHER_ECB; + SEC_TST_PRT("test alg: %s\n", "ecb(aes)"); + switch (g_keylen) { + case AES_KEYSIZE_128: + tv = &aes_ecb_tv_template_128[0]; + break; + case AES_KEYSIZE_192: + tv = &aes_ecb_tv_template_192[0]; + break; + case AES_KEYSIZE_256: + tv = &aes_ecb_tv_template_256[0]; + break; + default: + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + break; + case 1: + alg_type = WCRYPTO_CIPHER_AES; + mode_type = WCRYPTO_CIPHER_CBC; + SEC_TST_PRT("test alg: %s\n", "cbc(aes)"); + switch (g_keylen) { + case AES_KEYSIZE_128: + tv = &aes_cbc_tv_template_128[0]; + break; + case AES_KEYSIZE_192: + tv = &aes_cbc_tv_template_192[0]; + break; + case AES_KEYSIZE_256: + tv = &aes_cbc_tv_template_256[0]; + break; + default: + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + break; + case 2: + alg_type = WCRYPTO_CIPHER_AES; + mode_type = WCRYPTO_CIPHER_XTS; + SEC_TST_PRT("test alg: %s\n", "xts(aes)"); + switch (g_keylen / 2) { + case AES_KEYSIZE_128: + tv = &aes_xts_tv_template_256[0]; + break; + case AES_KEYSIZE_256: + tv = &aes_xts_tv_template_512[0]; + break; + default: + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + break; + case 3: + alg_type = WCRYPTO_CIPHER_AES; + mode_type = WCRYPTO_CIPHER_OFB; + SEC_TST_PRT("test alg: %s\n", "ofb(aes)"); + switch (g_keylen) { + case AES_KEYSIZE_128: + tv = &aes_ofb_tv_template_128[0]; + break; + case AES_KEYSIZE_192: + tv = &aes_ofb_tv_template_192[0]; + break; + case AES_KEYSIZE_256: + tv = &aes_ofb_tv_template_256[0]; + break; + default: + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + break; + case 4: + alg_type = WCRYPTO_CIPHER_AES; + mode_type = WCRYPTO_CIPHER_CFB; + SEC_TST_PRT("test alg: %s\n", "cfb(aes)"); + switch (g_keylen) { + case AES_KEYSIZE_128: + tv = &aes_cfb_tv_template_128[0]; + break; + case AES_KEYSIZE_192: + tv = &aes_cfb_tv_template_192[0]; + break; + case AES_KEYSIZE_256: + tv = &aes_cfb_tv_template_256[0]; + break; + default: + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + break; + case 5: + alg_type = WCRYPTO_CIPHER_AES; + mode_type = WCRYPTO_CIPHER_CTR; + SEC_TST_PRT("test alg: %s\n", "ctr(aes)"); + switch (g_keylen) { + case AES_KEYSIZE_128: + tv = &aes_ctr_tv_template_128[0]; + break; + case AES_KEYSIZE_192: + tv = &aes_ctr_tv_template_192[0]; + break; + case AES_KEYSIZE_256: + tv = &aes_ctr_tv_template_256[0]; + break; + default: + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + break; + case 6: + alg_type = WCRYPTO_CIPHER_3DES; + mode_type = WCRYPTO_CIPHER_ECB; + SEC_TST_PRT("test alg: %s\n", "ecb(des3)"); + if (g_keylen == 16) + tv = &des3_ecb_tv_template_128[0]; + else if (g_keylen == 24) + tv = &des3_ecb_tv_template_192[0]; + else { + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + break; + case 7: + alg_type = WCRYPTO_CIPHER_3DES; + mode_type = WCRYPTO_CIPHER_CBC; + SEC_TST_PRT("test alg: %s\n", "cbc(des3)"); + if (g_keylen == 16) + tv = &des3_cbc_tv_template_128[0]; + else if (g_keylen == 24) + tv = &des3_cbc_tv_template_192[0]; + else { + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + break; + case 8: + alg_type = WCRYPTO_CIPHER_SM4; + mode_type = WCRYPTO_CIPHER_CBC; + SEC_TST_PRT("test alg: %s\n", "cbc(sm4)"); + if (g_keylen != 16) { + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + tv = &sm4_cbc_tv_template[0]; + break; + case 9: + alg_type = WCRYPTO_CIPHER_SM4; + mode_type = WCRYPTO_CIPHER_XTS; + SEC_TST_PRT("test alg: %s\n", "xts(sm4)"); + if (g_keylen != 32) { + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + tv = &sm4_xts_tv_template[0]; + break; + case 10: + alg_type = WCRYPTO_CIPHER_SM4; + mode_type = WCRYPTO_CIPHER_OFB; + SEC_TST_PRT("test alg: %s\n", "ofb(sm4)"); + if (g_keylen != 16) { + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + tv = &sm4_ofb_tv_template_128[0]; + break; + case 11: + alg_type = WCRYPTO_CIPHER_SM4; + mode_type = WCRYPTO_CIPHER_CFB; + SEC_TST_PRT("test alg: %s\n", "cfb(sm4)"); + if (g_keylen != 16) { + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + tv = &sm4_cfb_tv_template_128[0]; + break; + case 12: + alg_type = WCRYPTO_CIPHER_SM4; + mode_type = WCRYPTO_CIPHER_CTR; + SEC_TST_PRT("test alg: %s\n", "ctr(sm4)"); + if (g_keylen != 16) { + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + tv = &sm4_ctr_tv_template_128[0]; + break; + default: + SEC_TST_PRT("keylenth error, default test alg: %s\n", "ecb(aes)"); + return -EINVAL; + } + *alg = alg_type; + *mode = mode_type; + *alg_tv = tv; + + return 0; +} + +int get_aead_resource(struct aead_testvec **alg_tv, + int* alg, int* mode, int* dalg, int* dmode) +{ + struct aead_testvec *tv; + int alg_type = 0; + int mode_type = 0; + int dalg_type = 0; + int dmode_type = 0; + + switch (g_testalg) { + case 0: + alg_type = WCRYPTO_CIPHER_AES; + mode_type = WCRYPTO_CIPHER_CCM; + SEC_TST_PRT("test alg: %s\n", "ccm(aes)"); + switch (g_keylen) { + case AES_KEYSIZE_128: + tv = &aes_ccm_tv_template_128[0]; + break; + case AES_KEYSIZE_192: + tv = &aes_ccm_tv_template_192[0]; + break; + case AES_KEYSIZE_256: + tv = &aes_ccm_tv_template_256[0]; + break; + default: + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + break; + case 1: + alg_type = WCRYPTO_CIPHER_AES; + mode_type = WCRYPTO_CIPHER_GCM; + SEC_TST_PRT("test alg: %s\n", "gcm(aes)"); + switch (g_keylen) { + case AES_KEYSIZE_128: + tv = &aes_gcm_tv_template_128[0]; + break; + case AES_KEYSIZE_192: + tv = &aes_gcm_tv_template_192[0]; + break; + case AES_KEYSIZE_256: + tv = &aes_gcm_tv_template_256[0]; + break; + default: + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + break; + case 2: + alg_type = WCRYPTO_CIPHER_AES; + mode_type = WCRYPTO_CIPHER_CBC; + dalg_type = WCRYPTO_SHA256; + dmode_type = WCRYPTO_DIGEST_HMAC; + SEC_TST_PRT("test alg: %s\n", "hmac(sha256),cbc(aes)"); + tv = &hmac_sha256_aes_cbc_tv_temp[0]; + break; + case 3: + alg_type = WCRYPTO_CIPHER_SM4; + mode_type = WCRYPTO_CIPHER_CCM; + SEC_TST_PRT("test alg: %s\n", "ccm(sm4)"); + if (g_keylen != 16) { + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + tv = &sm4_ccm_tv_template_128[0]; + break; + case 4: + alg_type = WCRYPTO_CIPHER_SM4; + mode_type = WCRYPTO_CIPHER_GCM; + SEC_TST_PRT("test alg: %s\n", "gcm(sm4)"); + if (g_keylen != 16) { + SEC_TST_PRT("%s: input key err!\n", __func__); + return -EINVAL; + } + tv = &sm4_gcm_tv_template_128[0]; + break; + default: + SEC_TST_PRT("keylenth error, default test alg: %s\n", "ccm(aes)"); + return -EINVAL; + } + *alg = alg_type; + *mode = mode_type; + *dalg = dalg_type; + *dmode = dmode_type; + *alg_tv = tv; + + return 0; +} + +int sec_sync_test_set_iv(struct test_sec_pthread_dt *pdata, + struct wcrypto_cipher_op_data *opdata, struct cipher_testvec *tv) +{ + int ivlen; + + if (!tv->iv) + return -1; + + ivlen = strlen(tv->iv); + if (ivlen != AES_KEYSIZE_128 && ivlen != (AES_KEYSIZE_128 >> 1)) + ivlen = AES_KEYSIZE_128; + + tv->ivlen = ivlen; + + if (pdata->data_fmt == WD_SGL_BUF) { // use no-sva sgl + wd_sgl_cp_from_pbuf(opdata->iv, 0, (void *)tv->iv, tv->ivlen); + } else { // use no-sva pbuffer + memset(opdata->iv, 0, tv->ivlen); + memcpy(opdata->iv, (void *)tv->iv, tv->ivlen); + } + + opdata->iv_bytes = tv->ivlen; + SEC_TST_PRT("dump set input IV! IV lenght:%d\n", ivlen); + hexdump(opdata->iv, opdata->iv_bytes); + + return 0; +} + +int sec_sync_cipher_test(struct test_sec_pthread_dt *pdata) +{ + int thread_id = (int)syscall(__NR_gettid); + struct wcrypto_cipher_ctx_setup setup; + struct wcrypto_cipher_op_data *opdata = malloc(sizeof(struct wcrypto_cipher_op_data)); + struct wd_queue *q = pdata->q; + struct timeval cur_tval; + struct cipher_testvec *tv; + float time_used, speed; + unsigned long Perf = 0; + char tmp[1024] = { 0 }; + int pid = getpid(); + void *ctx = NULL; + void *tag = NULL; + int ret; + + memset(&setup, 0, sizeof(setup)); + memset(opdata, 0, sizeof(struct wcrypto_cipher_op_data)); + + setup.alg = WCRYPTO_CIPHER_AES; + setup.mode = WCRYPTO_CIPHER_CBC; + setup.data_fmt = pdata->data_fmt; + setup.br.usr = pdata->pool; + + if (pdata->data_fmt == WD_SGL_BUF) { + setup.br.alloc = (void *)wd_alloc_sgl; + setup.br.free = (void *)wd_free_sgl; + setup.br.iova_map = (void *)wd_sgl_iova_map; + setup.br.iova_unmap = (void *)wd_sgl_iova_unmap; + } else { + setup.br.alloc = (void *)wd_alloc_blk; + setup.br.free = (void *)wd_free_blk; + setup.br.iova_map = (void *)wd_blk_iova_map; + setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + setup.br.get_bufsize = (void *)wd_blksize; + } + + ret = get_resource(&tv, (int *)&setup.alg, (int *)&setup.mode); + if (ret) + return -EINVAL; + + ctx = wcrypto_create_cipher_ctx(q, &setup); + if (!ctx) { + SEC_TST_PRT("Proc-%d, %d-TD:create %s ctx fail!\n", + pid, thread_id, q->capa.alg); + ret = -EINVAL; + return ret; + } +#ifdef DEBUG + hexdump((void *)tv->key, tv->klen); +#endif + ret = wcrypto_set_cipher_key(ctx, (__u8*)(void *)tv->key, (__u16)tv->klen); + if (ret) { + SEC_TST_PRT("set key fail!\n"); + goto fail_release; + } + + if (q->capa.priv.direction == 0) { + opdata->op_type = WCRYPTO_CIPHER_ENCRYPTION; + } else { + opdata->op_type = WCRYPTO_CIPHER_DECRYPTION; + } + if (pdata->data_fmt == WD_SGL_BUF) { // use no-sva sgl + opdata->in = wd_alloc_sgl(pdata->pool, MAX_BLOCK_SZ); + if (!opdata->in) { + SEC_TST_PRT("alloc in buffer fail!\n"); + goto fail_release; + } + + if (q->capa.priv.direction == 0) { + wd_sgl_cp_from_pbuf(opdata->in, 0, (void *)tv->ptext, tv->len); + if (strlen(tv->ptext) > pktlen) { + opdata->in_bytes = tv->len; + } else { + opdata->in_bytes = pktlen; + } + } else { + wd_sgl_cp_from_pbuf(opdata->in, 0, (void *)tv->ctext, tv->len); + if (strlen(tv->ctext) > pktlen) { + opdata->in_bytes = tv->len; + } else { + opdata->in_bytes = pktlen; + } + } + + opdata->priv = NULL; + opdata->out = wd_alloc_sgl(pdata->pool, MAX_BLOCK_SZ); + if (!opdata->out) { + SEC_TST_PRT("alloc out buffer fail!\n"); + goto fail_release; + } + opdata->out_bytes = opdata->in_bytes; + //set iv + opdata->iv = wd_alloc_sgl(pdata->pool, MAX_BLOCK_SZ); + if (!opdata->iv) { + SEC_TST_PRT("alloc iv buffer fail!\n"); + goto fail_release; + } + } else { // use no-sva pbuffer + opdata->in = wd_alloc_blk(pdata->pool); + if (!opdata->in) { + SEC_TST_PRT("alloc in buffer fail!\n"); + goto fail_release; + } + + memset(opdata->in, 0, tv->len); + if (q->capa.priv.direction == 0) { + memcpy(opdata->in, (void *)tv->ptext, tv->len); + if (strlen(tv->ptext) > pktlen) { + opdata->in_bytes = tv->len; + } else { + opdata->in_bytes = pktlen; + } + } else { + memcpy(opdata->in, (void *)tv->ctext, tv->len); + if (strlen(tv->ctext) > pktlen) { + opdata->in_bytes = tv->len; + } else { + opdata->in_bytes = pktlen; + } + } + + opdata->priv = NULL; + opdata->out = wd_alloc_blk(pdata->pool); + if (!opdata->out) { + SEC_TST_PRT("alloc out buffer fail!\n"); + goto fail_release; + } + opdata->out_bytes = opdata->in_bytes; + //set iv + opdata->iv = wd_alloc_blk(pdata->pool); + if (!opdata->iv) { + SEC_TST_PRT("alloc iv buffer fail!\n"); + goto fail_release; + } + } + + SEC_TST_PRT("cipher len:%d\n", opdata->in_bytes); +#ifdef DEBUG + if (pdata->data_fmt == WD_SGL_BUF) { // use no-sva sgl + wd_sgl_cp_to_pbuf(opdata->in, 0, tmp, opdata->in_bytes); + hexdump(tmp, opdata->in_bytes); + } else { + hexdump(opdata->in, opdata->in_bytes); + } +#endif + sec_sync_test_set_iv(pdata, opdata, tv); + do { + ret = wcrypto_do_cipher(ctx, opdata, tag); + pdata->send_task_num++; + + if (pdata->send_task_num == 1) { + + if (pdata->data_fmt == WD_SGL_BUF) { // use no-sva sgl + memset(tmp, 0, sizeof(tmp)); + SEC_TST_PRT("dump output:\n"); + wd_sgl_cp_to_pbuf(opdata->out, 0, tmp, opdata->in_bytes); + hexdump(tmp, opdata->out_bytes); + memset(tmp, 0, sizeof(tmp)); + SEC_TST_PRT("dump output IV:\n"); + wd_sgl_cp_to_pbuf(opdata->iv, 0, tmp, opdata->iv_bytes); + hexdump(tmp, opdata->iv_bytes); + } else { + SEC_TST_PRT("dump output:\n"); + hexdump(opdata->out, opdata->out_bytes); + SEC_TST_PRT("dump output IV:\n"); + hexdump(opdata->iv, opdata->iv_bytes); + } + } + + } while(!is_exit(pdata)); + + gettimeofday(&cur_tval, NULL); + time_used = (float)((cur_tval.tv_sec - pdata->start_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - pdata->start_tval.tv_usec); + SEC_TST_PRT("time_used:%0.0f us, send task num:%d\n", time_used, pdata->send_task_num++); + if (t_seconds) { + speed = pdata->send_task_num / time_used * 1000000; + Perf = speed * pktlen / 1024; //B->KB + pthread_mutex_lock(&perf_mutex); + g_total_perf += Perf; + pthread_mutex_unlock(&perf_mutex); + SEC_TST_PRT("Pro-%d, thread_id-%d, speed:%0.3f ops, Perf: %ld KB/s\n", pid, + thread_id, speed, Perf); + } else if (t_times) { + speed = 1 / (time_used / t_times) * 1000000; + Perf = speed * pktlen / 1024; //B->KB + pthread_mutex_lock(&perf_mutex); + g_total_perf += Perf; + pthread_mutex_unlock(&perf_mutex); + SEC_TST_PRT("Pro-%d, thread_id-%d, speed:%0.3f ops, Perf: %ld KB/s\n", pid, + thread_id, speed, Perf); + } + +fail_release: + if (pdata->data_fmt == WD_SGL_BUF) { + if (opdata->in) + wd_free_sgl(pdata->pool, opdata->in); + if (opdata->iv) + wd_free_sgl(pdata->pool, opdata->iv); + if (opdata->out) + wd_free_sgl(pdata->pool, opdata->out); + } else { + + if (opdata->in) + wd_free_blk(pdata->pool, opdata->in); + if (opdata->iv) + wd_free_blk(pdata->pool, opdata->iv); + if (opdata->out) + wd_free_blk(pdata->pool, opdata->out); + } + if (ctx) + wcrypto_del_cipher_ctx(ctx); + free(opdata); + + return ret; +} + +int get_digest_resource(struct hash_testvec **alg_tv, int* alg, int* mode) +{ + struct hash_testvec *tmp_tv; + struct hash_testvec *tv = NULL; + int alg_type; + int mode_type; + + switch (g_testalg) { + case 0: + switch (alg_op_type) { + case 0: + mode_type = WCRYPTO_DIGEST_NORMAL; + SEC_TST_PRT("test alg: %s\n", "normal(sm3)"); + tv = &sm3_tv_template[0]; + break; + case 1: + mode_type = WCRYPTO_DIGEST_HMAC; + SEC_TST_PRT("test alg: %s\n", "hmac(sm3)"); + tv = &hmac_sm3_tv_template[0]; + break; + } + tv->dsize = 32; + alg_type = WCRYPTO_SM3; + break; + case 1: + switch (alg_op_type) { + case 0: + mode_type = WCRYPTO_DIGEST_NORMAL; + SEC_TST_PRT("test alg: %s\n", "normal(md5)"); + tv = &md5_tv_template[0]; + break; + case 1: + mode_type = WCRYPTO_DIGEST_HMAC; + SEC_TST_PRT("test alg: %s\n", "hmac(md5)"); + tv = &hmac_md5_tv_template[0]; + break; + } + tv->dsize = 16; + alg_type = WCRYPTO_MD5; + break; + case 2: + switch (alg_op_type) { + case 0: + mode_type = WCRYPTO_DIGEST_NORMAL; + SEC_TST_PRT("test alg: %s\n", "normal(sha1)"); + tv = &sha1_tv_template[0]; + break; + case 1: + mode_type = WCRYPTO_DIGEST_HMAC; + SEC_TST_PRT("test alg: %s\n", "hmac(sha1)"); + tv = &hmac_sha1_tv_template[0]; + break; + } + tv->dsize = 20; + alg_type = WCRYPTO_SHA1; + break; + case 3: + switch (alg_op_type) { + case 0: + mode_type = WCRYPTO_DIGEST_NORMAL; + SEC_TST_PRT("test alg: %s\n", "normal(sha256)"); + tv = &sha256_tv_template[0]; + break; + case 1: + mode_type = WCRYPTO_DIGEST_HMAC; + SEC_TST_PRT("test alg: %s\n", "hmac(sha256)"); + tv = &hmac_sha256_tv_template[0]; + break; + } + tv->dsize = 32; + alg_type = WCRYPTO_SHA256; + break; + case 4: + switch (alg_op_type) { + case 0: + mode_type = WCRYPTO_DIGEST_NORMAL; + SEC_TST_PRT("test alg: %s\n", "normal(sha224)"); + tv = &sha224_tv_template[0]; + break; + case 1: + mode_type = WCRYPTO_DIGEST_HMAC; + SEC_TST_PRT("test alg: %s\n", "hmac(sha224)"); + tv = &hmac_sha224_tv_template[0]; + break; + } + tv->dsize = 28; + alg_type = WCRYPTO_SHA224; + break; + case 5: + switch (alg_op_type) { + case 0: + mode_type = WCRYPTO_DIGEST_NORMAL; + SEC_TST_PRT("test alg: %s\n", "normal(sha384)"); + tv = &sha384_tv_template[0]; + break; + case 1: + mode_type = WCRYPTO_DIGEST_HMAC; + SEC_TST_PRT("test alg: %s\n", "hmac(sha384)"); + tv = &hmac_sha384_tv_template[0]; + break; + } + tv->dsize = 48; + alg_type = WCRYPTO_SHA384; + break; + case 6: + switch (alg_op_type) { + case 0: + mode_type = WCRYPTO_DIGEST_NORMAL; + SEC_TST_PRT("test alg: %s\n", "normal(sha512)"); + tv = &sha512_tv_template[0]; + break; + case 1: + mode_type = WCRYPTO_DIGEST_HMAC; + SEC_TST_PRT("test alg: %s\n", "hmac(sha512)"); + tv = &hmac_sha512_tv_template[0]; + break; + } + tv->dsize = 64; + alg_type = WCRYPTO_SHA512; + break; + case 7: + switch (alg_op_type) { + case 0: + mode_type = WCRYPTO_DIGEST_NORMAL; + SEC_TST_PRT("test alg: %s\n", "normal(sha512_224)"); + tv = &sha512_224_tv_template[0]; + break; + case 1: + mode_type = WCRYPTO_DIGEST_HMAC; + SEC_TST_PRT("test alg: %s\n", "hmac(sha512_224"); + tv = &hmac_sha512_224_tv_template[0]; + break; + } + tv->dsize = 28; + alg_type = WCRYPTO_SHA512_224; + break; + case 8: + switch (alg_op_type) { + case 0: + mode_type = WCRYPTO_DIGEST_NORMAL; + SEC_TST_PRT("test alg: %s\n", "normal(sha512_256)"); + tv = &sha512_256_tv_template[0]; + break; + case 1: + mode_type = WCRYPTO_DIGEST_HMAC; + SEC_TST_PRT("test alg: %s\n", "hmac(sha512_256)"); + tv = &hmac_sha512_256_tv_template[0]; + break; + } + tv->dsize = 32; + alg_type = WCRYPTO_SHA512_256; + break; + default: + SEC_TST_PRT("keylenth error, default test alg: %s\n", "normal(sm3)"); + return -EINVAL; + } + if (g_ivlen == 1) { + tmp_tv = tv; + tv = &long_hash_tv_template[0]; + tv->dsize = tmp_tv->dsize; + } else if (g_ivlen == 2) { + tmp_tv = tv; + tv = &hmac_abnormal1024_tv_template[0]; + tv->dsize = tmp_tv->dsize; + } else if (g_ivlen == 3) { + tmp_tv = tv; + tv = &hmac_abnormal512_tv_template[0]; + tv->dsize = tmp_tv->dsize; + } + + *alg = alg_type; + *mode = mode_type; + *alg_tv = tv; + + return 0; +} + +int wd_digests_doimpl(void *ctx, struct wcrypto_digest_op_data **opdata, u32 *send_count) +{ + int ret; + int trycount = 0; + *send_count = 0; +again: + ret = wcrypto_burst_digest(ctx, opdata, NULL, 1); + if (ret == 0) { + if (trycount <= 5) { // try 5 times + SEC_TST_PRT("do digest busy, retry again!"); + trycount++; + goto again; + } else { + SEC_TST_PRT("do digest failed..\n!"); + return -1; + } + } else if (ret < 0) { + SEC_TST_PRT("do digest failed ret < 0!"); + return -1; + } + + (*send_count)++; + return 0; +} + +int alloc_from_pool(struct wcrypto_digest_op_data *opdata, struct test_sec_pthread_dt *pdata) +{ + if (pdata->data_fmt == WD_SGL_BUF) + opdata->in = wd_alloc_sgl(pdata->pool, MAX_BLOCK_SZ); + else + opdata->in = wd_alloc_blk(pdata->pool); + + if (!opdata->in) { + SEC_TST_PRT("alloc in buffer fail!\n"); + return -1; + } + + if (pdata->data_fmt == WD_SGL_BUF) + opdata->out = wd_alloc_sgl(pdata->pool, MAX_BLOCK_SZ); + else + opdata->out = wd_alloc_blk(pdata->pool); + + if (!opdata->out) { + SEC_TST_PRT("alloc out buffer fail!\n"); + return -1; + } + + return 0; +} + +int sec_sync_digest_test(struct test_sec_pthread_dt *pdata) +{ + struct wcrypto_digest_op_data *opdata = malloc(sizeof(struct wcrypto_digest_op_data)); + enum sec_digest_state state = SEC_DIGEST_INIT; + int thread_id = (int)syscall(__NR_gettid); + struct wcrypto_digest_ctx_setup setup; + struct wd_queue *q = pdata->q; + struct timeval cur_tval; + struct hash_testvec *tv; + float time_used, speed; + unsigned long Perf = 0; + char tmp[1024] = { 0 }; + int pid = getpid(); + void *ctx = NULL; + int ret; + + memset(&setup, 0, sizeof(setup)); + memset(opdata, 0, sizeof(struct wcrypto_digest_op_data)); + + setup.alg = WCRYPTO_SM3; + setup.mode = WCRYPTO_DIGEST_NORMAL; + setup.data_fmt = pdata->data_fmt; + setup.br.usr = pdata->pool; + + if (pdata->data_fmt == WD_SGL_BUF) { + setup.br.alloc = (void *)wd_alloc_sgl; + setup.br.free = (void *)wd_free_sgl; + setup.br.iova_map = (void *)wd_sgl_iova_map; + setup.br.iova_unmap = (void *)wd_sgl_iova_unmap; + } else { + setup.br.alloc = (void *)wd_alloc_blk; + setup.br.free = (void *)wd_free_blk; + setup.br.iova_map = (void *)wd_blk_iova_map; + setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + setup.br.get_bufsize = (void *)wd_blksize; + } + + ret = get_digest_resource(&tv, (int *)&setup.alg, (int *)&setup.mode); + if (ret) + return -EINVAL; + + ctx = wcrypto_create_digest_ctx(q, &setup); + if (!ctx) { + SEC_TST_PRT("Proc-%d, %d-TD:create %s ctx fail!\n", + pid, thread_id, q->capa.alg); + ret = -EINVAL; + return ret; + } else { + SEC_TST_PRT("Proc-%d, %d-TD:create %s ctx success!\n", + pid, thread_id, q->capa.alg); + } + if (setup.mode == WCRYPTO_DIGEST_HMAC) { + hexdump((char *)(void *)tv->key, tv->ksize); + ret = wcrypto_set_digest_key(ctx, (__u8*)(void *)tv->key, (__u16)tv->ksize); + if (ret) { + SEC_TST_PRT("set key fail!\n"); + goto fail_release; + } + } + + ret = alloc_from_pool(opdata, pdata); + if(ret) + goto fail_release; +#if 0 + SEC_TST_PRT("digest len:%d\n", opdata->in_bytes); + hexdump((void *)tv->plaintext, tv->psize); +#endif + if (pdata->data_fmt == WD_SGL_BUF) { // use no-sva sgl + wd_sgl_cp_from_pbuf(opdata->in, 0, (void *)tv->plaintext, tv->psize); + opdata->priv = NULL; + opdata->out_bytes = tv->dsize; + opdata->has_next = 0; + } else { // use no-sva pbuffer + memset(opdata->in, 0, tv->psize); + memcpy(opdata->in, (void *)tv->plaintext, tv->psize); + // opdata->in_bytes = tv->psize; + opdata->priv = NULL; + opdata->out_bytes = tv->dsize; + memset(opdata->out, 0, opdata->out_bytes); + opdata->has_next = 0; + } + + u32 data_len = tv->psize; + while (1) { + state = SEC_DIGEST_FINAL; + //memcpy(opdata->in, tv->plaintext + last_update_bufflen, data_len); + opdata->in_bytes = data_len; +#if 0 // DEBUG + SEC_TST_PRT("data_len:%d last_update_bufflen:%d\n", data_len, last_update_bufflen); + if (pdata->data_fmt == WD_SGL_BUF) { + wd_sgl_cp_to_pbuf(opdata->in, 0, tmp, opdata->in_bytes); + hexdump(tmp, opdata->in_bytes); + } else { + hexdump(opdata->in, opdata->in_bytes); + } +#endif + opdata->has_next = 0; + ret = wd_digests_doimpl(ctx, &opdata, &pdata->send_task_num); + if (ret) + goto fail_release; + +#if DEBUG + SEC_TST_PRT("digest sync out data:\n"); + if (pdata->data_fmt == WD_SGL_BUF) { // use no-sva sgl + memset(tmp, 0, sizeof(tmp)); + wd_sgl_cp_to_pbuf(opdata->out, 0, tmp, 64); + hexdump(tmp, 64); + } else { + hexdump(opdata->out, 64); + } +#endif + if (state == SEC_DIGEST_FINAL) + break; + } + + gettimeofday(&cur_tval, NULL); + time_used = (float)((cur_tval.tv_sec - pdata->start_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - pdata->start_tval.tv_usec); + SEC_TST_PRT("time_used:%0.0f us, send task num:%d\n", time_used, pdata->send_task_num++); + speed = pdata->send_task_num / time_used * 1000000; + Perf = speed * pktlen / 1024; //B->KB + SEC_TST_PRT("Pro-%d, thread_id-%d, speed:%0.3f ops, Perf: %ld KB/s\n", pid, + thread_id, speed, Perf); + +fail_release: + if (pdata->data_fmt == WD_SGL_BUF) { + if (opdata->in) + wd_free_sgl(pdata->pool, opdata->in); + if (opdata->out) + wd_free_sgl(pdata->pool, opdata->out); + } else { + if (opdata->in) + wd_free_blk(pdata->pool, opdata->in); + if (opdata->out) + wd_free_blk(pdata->pool, opdata->out); + } + + if (ctx) + wcrypto_del_digest_ctx(ctx); + free(opdata); + + return ret; +} + +void *_sec_sys_test_thread(void *data) +{ + if (!data) { + SEC_TST_PRT("test data input error!\n"); + return NULL; + } + struct test_sec_pthread_dt *pdata = data; + + if (!g_algclass) + sec_sync_cipher_test(pdata); + else + sec_sync_digest_test(pdata); + + return NULL; +} + +static int sec_cipher_sync_test(int thread_num, __u64 lcore_mask, + __u64 hcore_mask, enum cipher_op_type op_type, + char *dev_path, unsigned int node_mask, __u16 data_fmt) +{ + void **pool; + struct wd_blkpool_setup setup; + struct wd_sglpool_setup sp; + int i, ret, cnt = 0, j; + struct wd_queue *q; + int qidx; + + pthread_mutex_init(&perf_mutex, NULL); + q = malloc(q_num * sizeof(struct wd_queue)); + if (!q) { + SEC_TST_PRT("malloc q memory fail!\n"); + return -ENOMEM; + } + + memset(q, 0, q_num * sizeof(struct wd_queue)); + + pool = malloc(q_num * sizeof(pool)); + if (!pool) { + SEC_TST_PRT("malloc pool memory fail!\n"); + return -ENOMEM; + } + + for (j = 0; j < q_num; j++) { + if (!g_algclass){ + q[j].capa.alg = "cipher"; + if (op_type == ENCRYPTION) { + q[j].capa.priv.direction = 0; //0 is ENC, 1 is DEC + } else { + q[j].capa.priv.direction = 1; + } + } else { + q[j].capa.alg = "digest"; + } + + if (dev_path) { + strncpy(q[j].dev_path, dev_path, sizeof(q[j].dev_path)); + } + //q[j].node_mask = node_mask; + + ret = wd_request_queue(&q[j]); + if (ret) { + SEC_TST_PRT("request queue %d fail!\n", j); + return ret; + } + + if (data_fmt == WD_SGL_BUF) { // use no-sva sgl + memset(&sp, 0, sizeof(sp)); + sp.buf_size = MAX_BLOCK_SZ * 4; + sp.align_size = 64; + sp.sge_num_in_sgl = 2; + sp.buf_num_in_sgl = sp.sge_num_in_sgl - 1; + sp.sgl_num = MAX_BLOCK_NM; + sp.buf_num = sp.buf_num_in_sgl * sp.sgl_num + sp.sgl_num + 2; + pool[j] = wd_sglpool_create(&q[j], &sp); + if (!pool[j]) { + SEC_TST_PRT("%s(): create %dth pool fail!\n", __func__, j); + return -ENOMEM; + } + } else { // use no-sva pbuffer + memset(&setup, 0, sizeof(setup)); + setup.block_size = MAX_BLOCK_SZ; //set pool inv + key + in + out + setup.block_num = MAX_BLOCK_NM; + setup.align_size = SQE_SIZE; + + SEC_TST_PRT("%s, create pool memory: %d\n", __func__, MAX_BLOCK_NM * setup.block_size); + pool[j] = wd_blkpool_create(&q[j], &setup); + if (!pool[j]) { + SEC_TST_PRT("%s(): create %dth pool fail!\n", __func__, j); + return -ENOMEM; + } + } + SEC_TST_PRT("create pool succ, pool[%d] = %p\n", j, pool[j]); + } + + //??? ??? + if (_get_one_bits(lcore_mask) == 0 && + _get_one_bits(hcore_mask) == 0) + cnt = thread_num; + else + cnt = 1; + + for (i = 0 ; i < cnt; i++) { + qidx = i / ctx_num_per_q; + test_thrds_data[i].pool = pool[qidx]; + test_thrds_data[i].q = &q[qidx]; + test_thrds_data[i].thread_num = thread_num; + test_thrds_data[i].op_type = op_type; + test_thrds_data[i].cpu_id = _get_cpu_id(i, lcore_mask); + test_thrds_data[i].data_fmt = data_fmt; + + gettimeofday(&test_thrds_data[i].start_tval, NULL); + + ret = pthread_create(&system_test_thrds[i], NULL, + _sec_sys_test_thread, &test_thrds_data[i]); + if (ret) { + SEC_TST_PRT("Create %dth thread fail!\n", i); + return ret; + } + } + + for (i = 0; i < thread_num; i++) { + ret = pthread_join(system_test_thrds[i], NULL); + if (ret) { + SEC_TST_PRT("Join %dth thread fail!\n", i); + return ret; + } + } + + SEC_TST_PRT("%d-threads, total Perf: %lld KB/s\n", thread_num, g_total_perf); + + return 0; +} + +static void *_cipher_async_poll_test_thread(void *data) +{ + struct test_sec_pthread_dt *pdata = data; + struct wd_queue *q = pdata->q; + int ret; + + while (1) { + if (!g_algclass) + ret = wcrypto_cipher_poll(q, 1); + else + ret = wcrypto_digest_poll(q, 1); + if (ret < 0) { + break; + } + + if (asyn_thread_exit) + break; + } + + return NULL; +} + +void _cipher_cb(void *message, void *cipher_tag) +{ + struct cipher_async_tag *tag = cipher_tag; + struct test_sec_pthread_dt *thread_info = tag->thread_info; + thread_info->recv_task_num++; +} + +int sec_async_cipher_test(struct test_sec_pthread_dt *pdata) +{ + int thread_id = (int)syscall(__NR_gettid); + struct wcrypto_cipher_ctx_setup setup; + struct wcrypto_cipher_op_data opdata; + struct cipher_async_tag *tag = NULL; //async + struct wd_queue *q = pdata->q; + struct cipher_testvec *tv; + struct timeval cur_tval; + float time_used, speed; + unsigned long Perf = 0; + char tmp[1024] = { 0 }; + int pid = getpid(); + void *ctx = NULL; + int i = 0; + int ret; + + memset(&setup, 0, sizeof(setup)); + memset(&opdata, 0, sizeof(opdata)); + + setup.alg = WCRYPTO_CIPHER_AES; + setup.mode = WCRYPTO_CIPHER_CBC; + + ret = get_resource(&tv, (int *)&setup.alg, (int *)&setup.mode); + if (ret) + return -EINVAL; + + setup.cb = (void *)_cipher_cb; //call back functions of user + setup.data_fmt = pdata->data_fmt; + setup.br.usr = pdata->pool; + + if (pdata->data_fmt == WD_SGL_BUF) { // use no-sva sgl + setup.br.alloc = (void *)wd_alloc_sgl; + setup.br.free = (void *)wd_free_sgl; + setup.br.iova_map = (void *)wd_sgl_iova_map; + setup.br.iova_unmap = (void *)wd_sgl_iova_unmap; + } else { // use no-sva pbuffer + setup.br.alloc = (void *)wd_alloc_blk; + setup.br.free = (void *)wd_free_blk; + setup.br.iova_map = (void *)wd_blk_iova_map; + setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + setup.br.get_bufsize = (void *)wd_blksize; + } + + ctx = wcrypto_create_cipher_ctx(q, &setup); + if (!ctx) { + SEC_TST_PRT("Proc-%d, %d-TD:create %s ctx fail!\n", + pid, thread_id, q->capa.alg); + ret = -EINVAL; + return ret; + } + + hexdump((char *)(void *)tv->key, tv->klen); + + ret = wcrypto_set_cipher_key(ctx, (__u8*)(void *)tv->key, (__u16)tv->klen); + if (ret) { + SEC_TST_PRT("set key fail!\n"); + goto fail_release; + } + if (q->capa.priv.direction == 0) { + opdata.op_type = WCRYPTO_CIPHER_ENCRYPTION; + } else { + opdata.op_type = WCRYPTO_CIPHER_DECRYPTION; + } + if (pdata->data_fmt == WD_SGL_BUF) { // use no-sva sgl + opdata.in = wd_alloc_sgl(pdata->pool, MAX_BLOCK_SZ); + if (!opdata.in) { + SEC_TST_PRT("alloc sgl in buffer fail!\n"); + goto fail_release; + } + + if (q->capa.priv.direction == 0) { + printf("ptext:\n"); + hexdump((void *)tv->ptext, tv->len); + ret = wd_sgl_cp_from_pbuf(opdata.in, 0, (void *)tv->ptext, tv->len); + if (ret < 0) + goto fail_release; + if (tv->len > pktlen) + opdata.in_bytes = tv->len; + else + opdata.in_bytes = pktlen; + } else { + printf("ctext:\n"); + hexdump((void *)tv->ctext, tv->len); + ret = wd_sgl_cp_from_pbuf(opdata.in, 0, (void *)tv->ctext, tv->len); + if (ret < 0) + goto fail_release; + + if (tv->len > pktlen) + opdata.in_bytes = tv->len; + else + opdata.in_bytes = pktlen; + } + + opdata.priv = NULL; + opdata.out = wd_alloc_sgl(pdata->pool, MAX_BLOCK_SZ); + opdata.out_bytes = opdata.in_bytes; + if (!opdata.out) { + SEC_TST_PRT("alloc sgl out buffer fail!\n"); + goto fail_release; + } + + opdata.iv = wd_alloc_sgl(pdata->pool, MAX_BLOCK_SZ); + if (!opdata.iv) { + SEC_TST_PRT("alloc sgl iv buffer fail!\n"); + goto fail_release; + } + if (tv->iv) + wd_sgl_cp_from_pbuf(opdata.iv, 0, (void *)tv->iv, tv->ivlen); + opdata.iv_bytes = tv->ivlen; + } else { // use no-sva pbuffer + opdata.in = wd_alloc_blk(pdata->pool); + if (!opdata.in) { + SEC_TST_PRT("alloc in buffer fail!\n"); + goto fail_release; + } + if (q->capa.priv.direction == 0) { + memcpy(opdata.in, (void *)tv->ptext, tv->len); + if (tv->len > pktlen) { + opdata.in_bytes = tv->len; + } else { + opdata.in_bytes = pktlen; + } + } else { + memcpy(opdata.in, (void *)tv->ctext, tv->len); + if (tv->len > pktlen) { + opdata.in_bytes = tv->len; + } else { + opdata.in_bytes = pktlen; + } + } + + opdata.priv = NULL; + printf("ptext:\n"); + hexdump(opdata.in, opdata.in_bytes); + opdata.out = wd_alloc_blk(pdata->pool); + opdata.out_bytes = opdata.in_bytes; + if (!opdata.out) { + SEC_TST_PRT("alloc out buffer fail!\n"); + goto fail_release; + } + + opdata.iv = wd_alloc_blk(pdata->pool); + if (!opdata.iv) { + SEC_TST_PRT("alloc iv buffer fail!\n"); + goto fail_release; + } + + if (tv->iv) + memcpy(opdata.iv, (void *)tv->iv, tv->ivlen); + opdata.iv_bytes = tv->ivlen; + } + + do { + tag = malloc(sizeof(struct cipher_async_tag)); // set the user tag + if (!tag) + goto fail_release; + tag->ctx = ctx; + tag->thread_id = thread_id; + tag->cnt = i; + tag->thread_info = pdata; + try_do_again: + ret = wcrypto_do_cipher(ctx, &opdata, tag); + if (ret == -WD_EBUSY) { + usleep(100); + SEC_TST_PRT("wcrypto_do_cipher busy!\n"); + goto try_do_again; + } + pdata->send_task_num++; +#if DEBUG + usleep(10); + if (pdata->recv_task_num == 1) { + SEC_TST_PRT("cipher async output!\n"); + if (pdata->data_fmt == WD_SGL_BUF) { // use no-sva sgl + wd_sgl_cp_to_pbuf(opdata.out, 0, tmp, opdata.out_bytes); + hexdump(tmp, opdata.out_bytes); + } else { + hexdump(opdata.out, opdata.out_bytes); + } + } +#endif + i++; + } while(!is_exit(pdata)); + + gettimeofday(&cur_tval, NULL); + time_used = (float)((cur_tval.tv_sec - pdata->start_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - pdata->start_tval.tv_usec); + SEC_TST_PRT("time_used:%0.0f us, send task num:%d\n", time_used, pdata->send_task_num++); + if (t_seconds) { + speed = pdata->send_task_num / time_used * 1000000; + Perf = speed * pktlen / 1024; //B->KB + pthread_mutex_lock(&perf_mutex); + g_total_perf += Perf; + pthread_mutex_unlock(&perf_mutex); + SEC_TST_PRT("Pro-%d, thread_id-%d, speed:%0.3f ops, Perf: %ld KB/s\n", pid, thread_id, speed, Perf); + } else if (t_times) { + speed = (t_times / time_used) * 1000000; //ops + Perf = speed * pktlen / 1024; //B->KB + pthread_mutex_lock(&perf_mutex); + g_total_perf += Perf; + pthread_mutex_unlock(&perf_mutex); + SEC_TST_PRT("Pro-%d, thread_id-%d, speed:%0.3f ops, Perf: %ld KB/s\n", pid, thread_id, speed, Perf); + } + +fail_release: + if (pdata->data_fmt == WD_SGL_BUF) { // use no-sva sgl + if (opdata.in) + wd_free_sgl(pdata->pool, opdata.in); + if (opdata.iv) + wd_free_sgl(pdata->pool, opdata.iv); + if (opdata.out) + wd_free_sgl(pdata->pool, opdata.out); + } else { // use no-sva pbuffer + if (opdata.in) + wd_free_blk(pdata->pool, opdata.in); + if (opdata.iv) + wd_free_blk(pdata->pool, opdata.iv); + if (opdata.out) + wd_free_blk(pdata->pool, opdata.out); + } + + if (ctx) + wcrypto_del_cipher_ctx(ctx); + if (tag) + free(tag); + + return ret; +} + +void _digest_cb(void *message, void *digest_tag) +{ + struct digest_async_tag *tag = digest_tag; + struct test_sec_pthread_dt *thread_info = tag->thread_info; + thread_info->recv_task_num++; + WD_ERR(" --- %s, thread_info->recv_task_num = %d\n", __func__, thread_info->recv_task_num); +} + +int sec_async_digest_test(struct test_sec_pthread_dt *pdata) +{ + int thread_id = (int)syscall(__NR_gettid); + struct wcrypto_digest_ctx_setup setup; + struct wcrypto_digest_op_data opdata; + struct hash_testvec *tv; + struct timeval cur_tval; + float time_used, speed; + unsigned long Perf = 0; + int pid = getpid(); + void *ctx = NULL; + struct digest_async_tag *tag = NULL; //async + struct wd_queue *q = pdata->q; + char tmp[1024] = { 0 }; + int i = 0; + int ret; + + memset(&setup, 0, sizeof(setup)); + memset(&opdata, 0, sizeof(opdata)); + /* default AES-CBC */ + setup.alg = WCRYPTO_SM3; + setup.mode = WCRYPTO_DIGEST_NORMAL; + + ret = get_digest_resource(&tv, (int *)&setup.alg, (int *)&setup.mode); + if (ret) + return -EINVAL; + + setup.cb = (void *)_digest_cb; //call back functions of user + setup.data_fmt = pdata->data_fmt; + setup.br.usr = pdata->pool; + + if (pdata->data_fmt == WD_SGL_BUF) { // use no-sva sgl + setup.br.alloc = (void *)wd_alloc_sgl; + setup.br.free = (void *)wd_free_sgl; + setup.br.iova_map = (void *)wd_sgl_iova_map; + setup.br.iova_unmap = (void *)wd_sgl_iova_unmap; + + ctx = wcrypto_create_digest_ctx(q, &setup); + if (!ctx) { + SEC_TST_PRT("Proc-%d, %d-TD:create %s ctx fail!\n", + pid, thread_id, q->capa.alg); + ret = -EINVAL; + return ret; + } + + if (setup.mode == WCRYPTO_DIGEST_HMAC) { + ret = wcrypto_set_digest_key(ctx, (__u8*)(void *)tv->key, + (__u16)tv->ksize); + if (ret) { + SEC_TST_PRT("set key fail!\n"); + goto fail_release; + } + } + #ifdef DEBUG + SEC_TST_PRT("tv->key len: %d\n", tv->ksize); + hexdump((void *)tv->key, tv->ksize); + #endif + opdata.in = wd_alloc_sgl(pdata->pool, MAX_BLOCK_SZ); + if (!opdata.in) { + SEC_TST_PRT("alloc sgl in buffer fail!\n"); + goto fail_release; + } + wd_sgl_cp_from_pbuf(opdata.in, 0, (void *)tv->plaintext, tv->psize); + opdata.in_bytes = tv->psize; + + #if 0 // DEBUG + SEC_TST_PRT("digest len: %d\n", opdata.in_bytes); + hexdump((void *)tv->plaintext, opdata.in_bytes); + #endif + opdata.priv = NULL; + opdata.out = wd_alloc_sgl(pdata->pool, MAX_BLOCK_SZ); + opdata.out_bytes = tv->dsize; + if (!opdata.out) { + SEC_TST_PRT("alloc sgl out buffer fail!\n"); + goto fail_release; + } + } else { // use no-sva pbuffer + setup.br.alloc = (void *)wd_alloc_blk; + setup.br.free = (void *)wd_free_blk; + setup.br.iova_map = (void *)wd_blk_iova_map; + setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + setup.br.get_bufsize = (void *)wd_blksize; + + ctx = wcrypto_create_digest_ctx(q, &setup); + if (!ctx) { + SEC_TST_PRT("Proc-%d, %d-TD:create %s ctx fail!\n", + pid, thread_id, q->capa.alg); + ret = -EINVAL; + return ret; + } + + if (setup.mode == WCRYPTO_DIGEST_HMAC) { + ret = wcrypto_set_digest_key(ctx, (__u8*)(void *)tv->key, + (__u16)tv->ksize); + if (ret) { + SEC_TST_PRT("set key fail!\n"); + goto fail_release; + } + } + + #if DEBUG + SEC_TST_PRT("tv->key len: %d\n", tv->ksize); + hexdump((void *)tv->key, tv->ksize); + #endif + opdata.in = wd_alloc_blk(pdata->pool); + if (!opdata.in) { + SEC_TST_PRT("alloc in buffer fail!\n"); + goto fail_release; + } + memcpy(opdata.in, (void *)tv->plaintext, tv->psize); + opdata.in_bytes = tv->psize; + #if 0 // DEBUG + SEC_TST_PRT("digest len:%d\n", opdata.in_bytes); + hexdump(opdata.in, opdata.in_bytes); + #endif + opdata.priv = NULL; + opdata.out = wd_alloc_blk(pdata->pool); + opdata.out_bytes = tv->dsize; + if (!opdata.out) { + SEC_TST_PRT("alloc out buffer fail!\n"); + goto fail_release; + } + } + + do { + tag = malloc(sizeof(struct digest_async_tag)); //set the user tag is async + if (!tag) + goto fail_release; + tag->ctx = ctx; + tag->thread_id = thread_id; + tag->cnt = i; + tag->thread_info = pdata; +try_do_again: + ret = wcrypto_do_digest(ctx, &opdata, tag); + if (ret == -WD_EBUSY) { + usleep(100); + goto try_do_again; + } +#if DEBUG + usleep(100); + if (pdata->recv_task_num == 1) { + SEC_TST_PRT("digest async out data:\n"); + if (pdata->data_fmt == WD_SGL_BUF) { + wd_sgl_cp_to_pbuf(opdata.out, 0, tmp, tv->dsize); + hexdump(tmp, tv->dsize); + } else { + hexdump(opdata.out, tv->dsize); + } + } +#endif + + pdata->send_task_num++; + i++; + } while(!is_exit(pdata)); + + gettimeofday(&cur_tval, NULL); + time_used = (float)((cur_tval.tv_sec - pdata->start_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - pdata->start_tval.tv_usec); + SEC_TST_PRT("time_used:%0.0f us, send task num:%d\n", time_used, pdata->send_task_num++); + if (t_seconds) { + speed = pdata->send_task_num / time_used * 1000000; + Perf = speed * pktlen / 1024; //B->KB + pthread_mutex_lock(&perf_mutex); + g_total_perf += Perf; + pthread_mutex_unlock(&perf_mutex); + SEC_TST_PRT("Pro-%d, thread_id-%d, speed:%0.3f ops, Perf: %ld KB/s\n", pid, thread_id, speed, Perf); + } else if (t_times) { + speed = (t_times / time_used) * 1000000; //ops + Perf = speed * pktlen / 1024; //B->KB + pthread_mutex_lock(&perf_mutex); + g_total_perf += Perf; + pthread_mutex_unlock(&perf_mutex); + SEC_TST_PRT("Pro-%d, thread_id-%d, speed:%0.3f ops, Perf: %ld KB/s\n", pid, thread_id, speed, Perf); + } + +fail_release: + if (pdata->data_fmt == WD_SGL_BUF) { // use no-sva sgl + if (opdata.in) + wd_free_sgl(pdata->pool, opdata.in); + if (opdata.out) + wd_free_sgl(pdata->pool, opdata.out); + } else { // use no-sva pbuffer + if (opdata.in) + wd_free_blk(pdata->pool, opdata.in); + if (opdata.out) + wd_free_blk(pdata->pool, opdata.out); + } + + if (ctx) + wcrypto_del_digest_ctx(ctx); + if (tag) + free(tag); + + return ret; +} + +void *_sec_async_test_thread(void *data) +{ + if (!data) { + SEC_TST_PRT("test data input error!\n"); + return NULL; + } + struct test_sec_pthread_dt *pdata = data; + if (!g_algclass) + sec_async_cipher_test(pdata); + else + sec_async_digest_test(pdata); + + return NULL; +} + +static int sec_cipher_async_test(int thread_num, __u64 lcore_mask, + __u64 hcore_mask, enum cipher_op_type op_type, + char *dev_path, unsigned int node_mask, __u16 data_fmt) +{ + struct wd_blkpool_setup setup; + struct wd_sglpool_setup sp; + int i, ret, cnt = 0; + struct wd_queue q; + void **pool; + + memset(&q, 0, sizeof(q)); + + if (!g_algclass){ + q.capa.alg = "cipher"; + if (op_type == ENCRYPTION) { + q.capa.priv.direction = 0; //0 is ENC, 1 is DEC + } else + q.capa.priv.direction = 1; + } else { + q.capa.alg = "digest"; + } + + ret = wd_request_queue(&q); + if (ret) { + SEC_TST_PRT("request queue fail!\n"); + return ret; + } + + if (data_fmt == WD_SGL_BUF) { // use no-sva sgl + /* set pool inv + key + in + out */ + memset(&sp, 0, sizeof(sp)); + sp.buf_size = MAX_BLOCK_SZ * 4; + sp.align_size = SQE_SIZE; + sp.sge_num_in_sgl = 2; + sp.buf_num_in_sgl = sp.sge_num_in_sgl; + sp.sgl_num = 60; //MAX_BLOCK_NM; + sp.buf_num = sp.buf_num_in_sgl * sp.sgl_num + sp.sgl_num + 2; + /* create pool for every queue */ + SEC_TST_PRT("%s, create pool memory: %d\n", __func__, MAX_BLOCK_NM * setup.block_size); + pool = wd_sglpool_create(&q, &sp); + } else { + memset(&setup, 0, sizeof(setup)); + /* set pool inv + key + in + out */ + setup.block_size = MAX_BLOCK_SZ; + setup.block_num = MAX_BLOCK_NM; + setup.align_size = SQE_SIZE; + + /* create pool for every queue */ + SEC_TST_PRT("%s, create pool memory: %d\n", __func__, MAX_BLOCK_NM * setup.block_size); + pool = wd_blkpool_create(&q, &setup); + } + + if (!pool) { + SEC_TST_PRT("%s(): create pool fail!\n", __func__); + return -ENOMEM; + } + /* frist create the async poll thread! */ + test_thrds_data[0].pool = pool; + test_thrds_data[0].q = &q; + test_thrds_data[0].thread_num = 1; + test_thrds_data[0].op_type = op_type; + test_thrds_data[0].cpu_id = 0; + test_thrds_data[0].data_fmt = data_fmt; + ret = pthread_create(&system_test_thrds[0], NULL, + _cipher_async_poll_test_thread, &test_thrds_data[0]); + if (ret) { + SEC_TST_PRT("Create poll thread fail!\n"); + return ret; + } + + //??? ??? + if (_get_one_bits(lcore_mask) == 0 && + _get_one_bits(hcore_mask) == 0) + cnt = thread_num; + else + cnt = 1; + printf("cnt:%d\n", cnt); + for (i = 1 ; i <= cnt; i++) { + test_thrds_data[i].pool = pool; + test_thrds_data[i].q = &q; + test_thrds_data[i].thread_num = thread_num; + test_thrds_data[i].op_type = op_type; + test_thrds_data[i].cpu_id = _get_cpu_id(i, lcore_mask); + test_thrds_data[i].data_fmt = data_fmt; + + gettimeofday(&test_thrds_data[i].start_tval, NULL); + + ret = pthread_create(&system_test_thrds[i], NULL, + _sec_async_test_thread, &test_thrds_data[i]); + if (ret) { + SEC_TST_PRT("Create %dth thread fail!\n", i); + return ret; + } + } + + for (i = 1; i <= thread_num; i++) { + ret = pthread_join(system_test_thrds[i], NULL); + if (ret) { + SEC_TST_PRT("Join %dth thread fail!\n", i); + return ret; + } + } + asyn_thread_exit = 1; + ret = pthread_join(system_test_thrds[0], NULL); + if (ret) { + SEC_TST_PRT("Join %dth thread fail!\n", i); + return ret; + } + + if (data_fmt == WD_SGL_BUF) // use no-sva sgl + wd_sglpool_destroy(pool); // err + else // use no-sva pbuffer + wd_blkpool_destroy(pool); + + wd_release_queue(&q); + return 0; +} + +int sec_aead_sync_func_test(void *data) +{ + int thread_id = (int)syscall(__NR_gettid); + struct test_sec_pthread_dt *pdata = data; + struct wcrypto_aead_ctx_setup setup; + struct wcrypto_aead_op_data *opdata = malloc(sizeof(struct wcrypto_aead_op_data)); + struct wd_queue *q = pdata->q; + struct timeval cur_tval; + struct aead_testvec *tv; + float time_used, speed; + unsigned long Perf = 0; + int pid = getpid(); + void *ctx = NULL; + void *tag = NULL; + int auth_size; + int in_size; + int iv_len; + int ret; + + memset(&setup, 0, sizeof(setup)); + memset(opdata, 0, sizeof(struct wcrypto_aead_op_data)); + + setup.calg = WCRYPTO_CIPHER_AES; + setup.cmode = WCRYPTO_CIPHER_CCM; + setup.br.usr = pdata->pool; + setup.data_fmt = pdata->data_fmt; + if (pdata->data_fmt == WD_SGL_BUF) { // use no-sva sgl + char tmp[MAX_BLOCK_SZ] = {0}; + setup.br.alloc = (void *)wd_alloc_sgl; + setup.br.free = (void *)wd_free_sgl; + setup.br.iova_map = (void *)wd_sgl_iova_map; + setup.br.iova_unmap = (void *)wd_sgl_iova_unmap; + + ret = get_aead_resource(&tv, (int *)&setup.calg, + (int *)&setup.cmode, (int *)&setup.dalg, (int *)&setup.dmode); + if (ret) + return -EINVAL; + + ctx = wcrypto_create_aead_ctx(q, &setup); + if (!ctx) { + SEC_TST_PRT("Proc-%d, %d-TD:create %s ctx fail!\n", + pid, thread_id, q->capa.alg); + ret = -EINVAL; + return ret; + } + + hexdump((char *)(void *)tv->key, tv->klen); + if (setup.cmode == WCRYPTO_CIPHER_CCM || + setup.cmode == WCRYPTO_CIPHER_GCM) { + ret = wcrypto_set_aead_ckey(ctx, (__u8*)(void *)tv->key, (__u16)tv->klen); + if (ret) { + SEC_TST_PRT("set key fail!\n"); + goto fail_release; + } + }else { + // AEAD template's cipher key is the tail data + ret = wcrypto_set_aead_ckey(ctx, (__u8*)tv->key + 0x28, 0x10); + if (ret) { + SEC_TST_PRT("set key fail!\n"); + goto fail_release; + } + // AEAD template's auth key is the mid data + ret = wcrypto_set_aead_akey(ctx, (__u8*)tv->key + 0x08, 0x20); + if (ret) { + SEC_TST_PRT("set auth key fail!\n"); + goto fail_release; + } + } + + auth_size = (__u16)(tv->clen - tv->plen); + ret = wcrypto_aead_setauthsize(ctx, auth_size); + if (ret) { + SEC_TST_PRT("set authsize fail!\n"); + goto fail_release; + } + + // test the auth size + ret = wcrypto_aead_getauthsize(ctx); + if (ret != auth_size) { + SEC_TST_PRT("get authsize fail!\n"); + goto fail_release; + } + ret = wcrypto_aead_get_maxauthsize(ctx); + if (ret < auth_size) { + SEC_TST_PRT("get max authsize fail!\n"); + goto fail_release; + } + SEC_TST_PRT("max authsize : %d!\n", ret); + + if (q->capa.priv.direction == 0) { + opdata->op_type = WCRYPTO_CIPHER_ENCRYPTION_DIGEST; + } else { + opdata->op_type = WCRYPTO_CIPHER_DECRYPTION_DIGEST; + } + + opdata->assoc_size = tv->alen; + opdata->in = wd_alloc_sgl(pdata->pool, MAX_BLOCK_SZ); + if (!opdata->in) { + SEC_TST_PRT("alloc in buffer fail!\n"); + goto fail_release; + } + + in_size = tv->alen + tv->plen + auth_size; + if (in_size > MAX_BLOCK_SZ) { + SEC_TST_PRT("alloc in buffer block size too small!\n"); + goto fail_release; + } + + // copy the assoc data in the front of in data + if (q->capa.priv.direction == 0) { + wd_sgl_cp_from_pbuf(opdata->in, 0, (void *)tv->assoc, tv->alen); + wd_sgl_cp_from_pbuf(opdata->in, tv->alen, (void *)tv->ptext, tv->plen); + opdata->in_bytes = tv->plen; + } else { + wd_sgl_cp_from_pbuf(opdata->in, 0, (void *)tv->assoc, tv->alen); + wd_sgl_cp_from_pbuf(opdata->in, tv->alen, (void *)tv->ctext, tv->clen); + opdata->in_bytes = tv->clen - auth_size; + } + + SEC_TST_PRT("aead input len:%d\n", tv->alen + opdata->in_bytes); + wd_sgl_cp_to_pbuf(opdata->in, 0, tmp, tv->alen + opdata->in_bytes); + hexdump(tmp, tv->alen + opdata->in_bytes); + + opdata->priv = NULL; + opdata->out = wd_alloc_sgl(pdata->pool, MAX_BLOCK_SZ); + if (!opdata->out) { + SEC_TST_PRT("alloc out buffer fail!\n"); + goto fail_release; + } + if (q->capa.priv.direction == 0) { + opdata->out_bytes = tv->alen + tv->clen; + } else { + opdata->out_bytes = tv->alen + tv->plen; + } + opdata->out_buf_bytes = MAX_BLOCK_SZ; + //set iv + opdata->iv = wd_alloc_sgl(pdata->pool, MAX_BLOCK_SZ); + if (!opdata->iv) { + SEC_TST_PRT("alloc iv buffer fail!\n"); + goto fail_release; + } + + // if data is \0x00, the strlen will end and return + // iv_len = strlen(tv->iv); + if (setup.cmode == WCRYPTO_CIPHER_GCM) { + iv_len = 12; + } else { + iv_len = 16; + } + + wd_sgl_cp_from_pbuf(opdata->iv, 0, (void *)tv->iv, iv_len); + opdata->iv_bytes = iv_len; +#if DEBUG + SEC_TST_PRT("dump set input IV! IV lenght:%d\n", iv_len); + memset(tmp, 0, sizeof(tmp)); + wd_sgl_cp_to_pbuf(opdata->iv, 0, tmp, opdata->iv_bytes); + hexdump(tmp, opdata->iv_bytes); +#endif + do { + ret = wcrypto_do_aead(ctx, opdata, tag); + pdata->send_task_num++; +#if DEBUG + if (pdata->send_task_num == 1) { + SEC_TST_PRT("aead sync output! opdata->out_bytes(%d) + auth_size(%d) = %d\n", + opdata->out_bytes, auth_size, opdata->out_bytes + auth_size); + memset(tmp, 0, sizeof(tmp)); + wd_sgl_cp_to_pbuf(opdata->out, 0, tmp, opdata->out_bytes + auth_size); + hexdump(tmp, opdata->out_bytes + auth_size); + } +#endif + } while(!is_exit(pdata)); + + gettimeofday(&cur_tval, NULL); + time_used = (float)((cur_tval.tv_sec - pdata->start_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - pdata->start_tval.tv_usec); + SEC_TST_PRT("time_used:%0.0f us, send task num:%d\n", time_used, pdata->send_task_num++); + speed = pdata->send_task_num / time_used * 1000000; + Perf = speed * in_size / 1024; //B->KB + SEC_TST_PRT("Pro-%d, thread_id-%d, speed:%0.3f ops, Perf: %ld KB/s\n", pid, + thread_id, speed, Perf); + } else { // use no-sva pbuffer + setup.br.alloc = (void *)wd_alloc_blk; + setup.br.free = (void *)wd_free_blk; + setup.br.iova_map = (void *)wd_blk_iova_map; + setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + setup.br.get_bufsize = (void *)wd_blksize; + + ret = get_aead_resource(&tv, (int *)&setup.calg, + (int *)&setup.cmode, (int *)&setup.dalg, (int *)&setup.dmode); + if (ret) + return -EINVAL; + + ctx = wcrypto_create_aead_ctx(q, &setup); + if (!ctx) { + SEC_TST_PRT("Proc-%d, %d-TD:create %s ctx fail!\n", + pid, thread_id, q->capa.alg); + ret = -EINVAL; + return ret; + } + + hexdump((char *)(void *)tv->key, tv->klen); + if (setup.cmode == WCRYPTO_CIPHER_CCM || + setup.cmode == WCRYPTO_CIPHER_GCM) { + ret = wcrypto_set_aead_ckey(ctx, (__u8*)(void *)tv->key, (__u16)tv->klen); + if (ret) { + SEC_TST_PRT("set key fail!\n"); + goto fail_release; + } + }else { + // AEAD template's cipher key is the tail data + ret = wcrypto_set_aead_ckey(ctx, (__u8*)tv->key + 0x28, 0x10); + if (ret) { + SEC_TST_PRT("set key fail!\n"); + goto fail_release; + } + // AEAD template's auth key is the mid data + ret = wcrypto_set_aead_akey(ctx, (__u8*)tv->key + 0x08, 0x20); + if (ret) { + SEC_TST_PRT("set auth key fail!\n"); + goto fail_release; + } + } + + auth_size = (__u16)(tv->clen - tv->plen); + ret = wcrypto_aead_setauthsize(ctx, auth_size); + if (ret) { + SEC_TST_PRT("set authsize fail!\n"); + goto fail_release; + } + + // test the auth size + ret = wcrypto_aead_getauthsize(ctx); + if (ret != auth_size) { + SEC_TST_PRT("get authsize fail!\n"); + goto fail_release; + } + ret = wcrypto_aead_get_maxauthsize(ctx); + if (ret < auth_size) { + SEC_TST_PRT("get max authsize fail!\n"); + goto fail_release; + } + SEC_TST_PRT("max authsize : %d!\n", ret); + + if (q->capa.priv.direction == 0) { + opdata->op_type = WCRYPTO_CIPHER_ENCRYPTION_DIGEST; + } else { + opdata->op_type = WCRYPTO_CIPHER_DECRYPTION_DIGEST; + } + + opdata->assoc_size = tv->alen; + opdata->in = wd_alloc_blk(pdata->pool); + if (!opdata->in) { + SEC_TST_PRT("alloc in buffer fail!\n"); + goto fail_release; + } + + in_size = tv->alen + tv->plen + auth_size; + if (in_size > MAX_BLOCK_SZ) { + SEC_TST_PRT("alloc in buffer block size too small!\n"); + goto fail_release; + } + + // copy the assoc data in the front of in data + memset(opdata->in, 0, in_size); + if (q->capa.priv.direction == 0) { + memcpy(opdata->in, (void *)tv->assoc, tv->alen); + memcpy((opdata->in + tv->alen), (void *)tv->ptext, tv->plen); + opdata->in_bytes = tv->plen; + } else { + memcpy(opdata->in, (void *)tv->assoc, tv->alen); + memcpy((opdata->in + tv->alen), (void *)tv->ctext, tv->clen); + opdata->in_bytes = tv->clen - auth_size; + } + + SEC_TST_PRT("aead input len:%d\n", tv->alen + opdata->in_bytes); + hexdump(opdata->in, tv->alen + opdata->in_bytes); + opdata->priv = NULL; + opdata->out = wd_alloc_blk(pdata->pool); + if (!opdata->out) { + SEC_TST_PRT("alloc out buffer fail!\n"); + goto fail_release; + } + if (q->capa.priv.direction == 0) { + opdata->out_bytes = tv->alen + tv->clen; + } else { + opdata->out_bytes = tv->alen + tv->plen; + } + opdata->out_buf_bytes = MAX_BLOCK_SZ; + //set iv + opdata->iv = wd_alloc_blk(pdata->pool); + if (!opdata->iv) { + SEC_TST_PRT("alloc iv buffer fail!\n"); + goto fail_release; + } + + // if data is \0x00, the strlen will end and return + // iv_len = strlen(tv->iv); + if (setup.cmode == WCRYPTO_CIPHER_GCM) { + iv_len = 12; + } else { + iv_len = 16; + } + memset(opdata->iv, 0, iv_len); + memcpy(opdata->iv, (void *)tv->iv, iv_len); + opdata->iv_bytes = iv_len; + SEC_TST_PRT("dump set input IV! IV lenght:%d\n", iv_len); + hexdump(opdata->iv, opdata->iv_bytes); + + do { + ret = wcrypto_do_aead(ctx, opdata, tag); + pdata->send_task_num++; + if (pdata->send_task_num == 1) { + SEC_TST_PRT("dump output!\n"); + hexdump(opdata->out, opdata->out_bytes + auth_size); + } + } while(!is_exit(pdata)); + + gettimeofday(&cur_tval, NULL); + time_used = (float)((cur_tval.tv_sec - pdata->start_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - pdata->start_tval.tv_usec); + SEC_TST_PRT("time_used:%0.0f us, send task num:%d\n", time_used, pdata->send_task_num++); + speed = pdata->send_task_num / time_used * 1000000; + Perf = speed * in_size / 1024; //B->KB + SEC_TST_PRT("Pro-%d, thread_id-%d, speed:%0.3f ops, Perf: %ld KB/s\n", pid, + thread_id, speed, Perf); + } + +fail_release: + if (pdata->data_fmt == WD_SGL_BUF) { // use no-sva sgl + if (opdata->in) + wd_free_sgl(pdata->pool, opdata->in); + if (opdata->iv) + wd_free_sgl(pdata->pool, opdata->iv); + if (opdata->out) + wd_free_sgl(pdata->pool, opdata->out); + } else { // use no-sva pbuffer + if (opdata->in) + wd_free_blk(pdata->pool, opdata->in); + if (opdata->iv) + wd_free_blk(pdata->pool, opdata->iv); + if (opdata->out) + wd_free_blk(pdata->pool, opdata->out); + } + + if (ctx) + wcrypto_del_aead_ctx(ctx); + free(opdata); + + return ret; +} + +void *__sec_aead_sync_func_test(void *data) +{ + sec_aead_sync_func_test(data); + + return NULL; +} + +static int sec_aead_sync_test(int thread_num, __u64 lcore_mask, + __u64 hcore_mask, enum cipher_op_type op_type, + char *dev_path, unsigned int node_mask, __u16 data_fmt) +{ + void **pool; + struct wd_blkpool_setup setup; + struct wd_sglpool_setup sp; + int i, ret, cnt = 0, j; + struct wd_queue *q; + int qidx; + + SEC_TST_PRT("SEC q_num is : %d!\n", q_num); + q = malloc(q_num * sizeof(struct wd_queue)); + if (!q) { + SEC_TST_PRT("malloc q memory fail!\n"); + return -ENOMEM; + } + + memset(q, 0, q_num * sizeof(struct wd_queue)); + + /* create pool for every queue */ + pool = malloc(q_num * sizeof(pool)); + if (!pool) { + SEC_TST_PRT("malloc pool memory fail!\n"); + return -ENOMEM; + } + + for (j = 0; j < q_num; j++) { + q[j].capa.alg = "aead"; + if (op_type == ENCRYPTION) { + q[j].capa.priv.direction = 0; //0 is ENC, 1 is DEC + } else { + q[j].capa.priv.direction = 1; + } + + if (dev_path) { + strncpy(q[j].dev_path, dev_path, sizeof(q[j].dev_path)); + } + // q[j].node_mask = node_mask; + + ret = wd_request_queue(&q[j]); + if (ret) { + SEC_TST_PRT("request queue %d fail!\n", j); + return ret; + } + + if (data_fmt == WD_SGL_BUF) { // use no-sva sgl + memset(&sp, 0, sizeof(sp)); + sp.buf_size = MAX_BLOCK_SZ * 4; + sp.align_size = 64; + sp.sge_num_in_sgl = 2; + sp.buf_num_in_sgl = sp.sge_num_in_sgl - 1; + sp.sgl_num = MAX_BLOCK_NM; + sp.buf_num = sp.buf_num_in_sgl * sp.sgl_num + sp.sgl_num + 2; + + SEC_TST_PRT("create pool memory: %d\n", MAX_BLOCK_NM * setup.block_size); + pool[j] = wd_sglpool_create(&q[j], &sp); + if (!pool[j]) { + SEC_TST_PRT("%s(): create %dth sgl pool fail!\n", __func__, j); + return -ENOMEM; + } + } else { // use no-sva pbuffer + memset(&setup, 0, sizeof(setup)); + setup.block_size = MAX_BLOCK_SZ; //set pool inv + key + in + out + setup.block_num = MAX_BLOCK_NM; + setup.align_size = SQE_SIZE; + + SEC_TST_PRT("create pool memory: %d\n", MAX_BLOCK_NM * setup.block_size); + pool[j] = wd_blkpool_create(&q[j], &setup); + if (!pool[j]) { + SEC_TST_PRT("%s(): create %dth blk pool fail!\n", __func__, j); + return -ENOMEM; + } + } + } + + //Ïß³ÌÊý Óë°óºË + if (_get_one_bits(lcore_mask) == 0 && + _get_one_bits(hcore_mask) == 0) + cnt = thread_num; + else + cnt = 1; + + for (i = 0 ; i < cnt; i++) { + qidx = i / ctx_num_per_q; + test_thrds_data[i].pool = pool[qidx]; + test_thrds_data[i].q = &q[qidx]; + test_thrds_data[i].thread_num = thread_num; + test_thrds_data[i].op_type = op_type; + test_thrds_data[i].cpu_id = _get_cpu_id(i, lcore_mask); + test_thrds_data[i].data_fmt = data_fmt; + + gettimeofday(&test_thrds_data[i].start_tval, NULL); + + ret = pthread_create(&system_test_thrds[i], NULL, + __sec_aead_sync_func_test, &test_thrds_data[i]); + if (ret) { + SEC_TST_PRT("Create %dth thread fail!\n", i); + return ret; + } + } + + for (i = 0; i < thread_num; i++) { + ret = pthread_join(system_test_thrds[i], NULL); + if (ret) { + SEC_TST_PRT("Join %dth thread fail!\n", i); + return ret; + } + } + + return 0; +} + +static void *_aead_async_poll_test_thread(void *data) +{ + struct test_sec_pthread_dt *pdata = data; + struct wd_queue *q = pdata->q; + int ret; + + while (1) { + ret = wcrypto_aead_poll(q, 1); + if (ret < 0) { + break; + } + + if (asyn_thread_exit) + break; + } + + return NULL; +} + +int sec_aead_async_func_test(void *data) +{ + int thread_id = (int)syscall(__NR_gettid); + struct test_sec_pthread_dt *pdata = data; + struct wcrypto_aead_ctx_setup setup; + struct wcrypto_aead_op_data *opdata = malloc(sizeof(struct wcrypto_aead_op_data)); + struct cipher_async_tag *tag = NULL; //async + struct wd_queue *q = pdata->q; + struct timeval cur_tval; + struct aead_testvec *tv; + float time_used, speed; + unsigned long Perf = 0; + char tmp[1024] = { 0 }; + int pid = getpid(); + void *ctx = NULL; + int auth_size; + int in_size; + int iv_len; + int i = 0; + int ret; + + memset(&setup, 0, sizeof(setup)); + memset(opdata, 0, sizeof(struct wcrypto_aead_op_data)); + + setup.calg = WCRYPTO_CIPHER_AES; + setup.cmode = WCRYPTO_CIPHER_CCM; + setup.cb = (void *)_cipher_cb; //call back functions of user + setup.data_fmt = pdata->data_fmt; + setup.br.usr = pdata->pool; + + if (pdata->data_fmt == WD_SGL_BUF) { // use no-sva sgl + setup.br.alloc = (void *)wd_alloc_sgl; + setup.br.free = (void *)wd_free_sgl; + setup.br.iova_map = (void *)wd_sgl_iova_map; + setup.br.iova_unmap = (void *)wd_sgl_iova_unmap; + } else { // use no-sva pbuffer + setup.br.alloc = (void *)wd_alloc_blk; + setup.br.free = (void *)wd_free_blk; + setup.br.iova_map = (void *)wd_blk_iova_map; + setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + setup.br.get_bufsize = (void *)wd_blksize; + } + + ret = get_aead_resource(&tv, (int *)&setup.calg, + (int *)&setup.cmode, (int *)&setup.dalg, (int *)&setup.dmode); + if (ret) + return -EINVAL; + + ctx = wcrypto_create_aead_ctx(q, &setup); + if (!ctx) { + SEC_TST_PRT("Proc-%d, %d-TD:create %s ctx fail!\n", + pid, thread_id, q->capa.alg); + ret = -EINVAL; + return ret; + } + + hexdump((char *)(void *)tv->key, tv->klen); + if (setup.cmode == WCRYPTO_CIPHER_CCM || + setup.cmode == WCRYPTO_CIPHER_GCM) { + ret = wcrypto_set_aead_ckey(ctx, (__u8*)(void *)tv->key, (__u16)tv->klen); + if (ret) { + SEC_TST_PRT("set key fail!\n"); + goto fail_release; + } + }else { + // AEAD template's cipher key is the tail data + ret = wcrypto_set_aead_ckey(ctx, (__u8*)tv->key + 0x28, 0x10); + if (ret) { + SEC_TST_PRT("set key fail!\n"); + goto fail_release; + } + // AEAD template's auth key is the mid data + ret = wcrypto_set_aead_akey(ctx, (__u8*)tv->key + 0x08, 0x20); + if (ret) { + SEC_TST_PRT("set auth key fail!\n"); + goto fail_release; + } + } + + auth_size = (__u16)(tv->clen - tv->plen); + ret = wcrypto_aead_setauthsize(ctx, auth_size); + if (ret) { + SEC_TST_PRT("set authsize fail!\n"); + goto fail_release; + } + + // test the auth size + ret = wcrypto_aead_getauthsize(ctx); + if (ret != auth_size) { + SEC_TST_PRT("get authsize fail!\n"); + goto fail_release; + } + ret = wcrypto_aead_get_maxauthsize(ctx); + if (ret < auth_size) { + SEC_TST_PRT("get max authsize fail!\n"); + goto fail_release; + } + SEC_TST_PRT("max authsize : %d!\n", ret); + + if (q->capa.priv.direction == 0) { + opdata->op_type = WCRYPTO_CIPHER_ENCRYPTION_DIGEST; + } else { + opdata->op_type = WCRYPTO_CIPHER_DECRYPTION_DIGEST; + } + + opdata->assoc_size = tv->alen; + + if (pdata->data_fmt == WD_SGL_BUF) { // use no-sva sgl + opdata->in = wd_alloc_sgl(pdata->pool, MAX_BLOCK_SZ); + if (!opdata->in) { + SEC_TST_PRT("alloc sgl in buffer fail!\n"); + goto fail_release; + } + + in_size = tv->alen + tv->plen + auth_size; + if (in_size > MAX_BLOCK_SZ) { + SEC_TST_PRT("alloc in buffer block size too small!\n"); + goto fail_release; + } + + // copy the assoc data in the front of in data + if (q->capa.priv.direction == 0) { + wd_sgl_cp_from_pbuf(opdata->in, 0, (void *)tv->assoc, tv->alen); + wd_sgl_cp_from_pbuf(opdata->in, tv->alen, (void *)tv->ptext, tv->plen); + opdata->in_bytes = tv->plen; + } else { + wd_sgl_cp_from_pbuf(opdata->in, 0, (void *)tv->assoc, tv->alen); + wd_sgl_cp_from_pbuf(opdata->in, tv->alen, (void *)tv->ctext, tv->clen); + opdata->in_bytes = tv->clen - auth_size; + } +#if DEBUG + SEC_TST_PRT("aead input len:%d\n", tv->alen + opdata->in_bytes); + wd_sgl_cp_to_pbuf(opdata->in, 0, tmp, tv->alen + opdata->in_bytes); + hexdump(tmp, tv->alen + opdata->in_bytes); + memset(tmp, 0, sizeof(tmp)); +#endif + opdata->priv = NULL; + opdata->out = wd_alloc_sgl(pdata->pool, MAX_BLOCK_SZ); + if (!opdata->out) { + SEC_TST_PRT("alloc sgl out buffer fail!\n"); + goto fail_release; + } + if (q->capa.priv.direction == 0) { + opdata->out_bytes = tv->alen + tv->clen; + } else { + opdata->out_bytes = tv->alen + tv->plen; + } + opdata->out_buf_bytes = MAX_BLOCK_SZ; + //set iv + opdata->iv = wd_alloc_sgl(pdata->pool, MAX_BLOCK_SZ); + if (!opdata->iv) { + SEC_TST_PRT("alloc sgl iv buffer fail!\n"); + goto fail_release; + } + + // if data is \0x00, the strlen will end and return + // iv_len = strlen(tv->iv); + if (setup.cmode == WCRYPTO_CIPHER_GCM) { + iv_len = 12; + } else { + iv_len = 16; + } + //memset(opdata->iv, 0, iv_len); + wd_sgl_cp_from_pbuf(opdata->iv, 0, (void *)tv->iv, iv_len); + opdata->iv_bytes = iv_len; + SEC_TST_PRT("dump set input IV! IV lenght:%d\n", iv_len); + //hexdump(opdata->iv, opdata->iv_bytes); + hexdump((void *)tv->iv, opdata->iv_bytes); + } else { // use no-sva pbuffer + opdata->in = wd_alloc_blk(pdata->pool); + if (!opdata->in) { + SEC_TST_PRT("alloc in buffer fail!\n"); + goto fail_release; + } + + in_size = tv->alen + tv->plen + auth_size; + if (in_size > MAX_BLOCK_SZ) { + SEC_TST_PRT("alloc in buffer block size too small!\n"); + goto fail_release; + } + + // copy the assoc data in the front of in data + memset(opdata->in, 0, in_size); + if (q->capa.priv.direction == 0) { + memcpy(opdata->in, (void *)tv->assoc, tv->alen); + memcpy((opdata->in + tv->alen), (void *)tv->ptext, tv->plen); + opdata->in_bytes = tv->plen; + } else { + memcpy(opdata->in, (void *)tv->assoc, tv->alen); + memcpy((opdata->in + tv->alen), (void *)tv->ctext, tv->clen); + opdata->in_bytes = tv->clen - auth_size; + } + + SEC_TST_PRT("aead input len:%d\n", tv->alen + opdata->in_bytes); + hexdump(opdata->in, tv->alen + opdata->in_bytes); + opdata->priv = NULL; + opdata->out = wd_alloc_blk(pdata->pool); + if (!opdata->out) { + SEC_TST_PRT("alloc out buffer fail!\n"); + goto fail_release; + } + if (q->capa.priv.direction == 0) { + opdata->out_bytes = tv->alen + tv->clen; + } else { + opdata->out_bytes = tv->alen + tv->plen; + } + opdata->out_buf_bytes = MAX_BLOCK_SZ; + //set iv + opdata->iv = wd_alloc_blk(pdata->pool); + if (!opdata->iv) { + SEC_TST_PRT("alloc iv buffer fail!\n"); + goto fail_release; + } + + // if data is \0x00, the strlen will end and return + // iv_len = strlen(tv->iv); + if (setup.cmode == WCRYPTO_CIPHER_GCM) { + iv_len = 12; + } else { + iv_len = 16; + } + memset(opdata->iv, 0, iv_len); + memcpy(opdata->iv, (void *)tv->iv, iv_len); + opdata->iv_bytes = iv_len; + SEC_TST_PRT("dump set input IV! IV lenght:%d\n", iv_len); + hexdump(opdata->iv, opdata->iv_bytes); + } + + do { + tag = malloc(sizeof(struct cipher_async_tag)); // set the user tag + if (!tag) + goto fail_release; + + tag->ctx = ctx; + tag->thread_id = thread_id; + tag->cnt = i; + tag->thread_info = pdata; + try_do_again: + ret = wcrypto_do_aead(ctx, opdata, tag); + if (ret == -WD_EBUSY) { + usleep(100); + SEC_TST_PRT("wcrypto_do_aead busy!\n"); + goto try_do_again; + } + pdata->send_task_num++; + i++; +#if DEBUG + usleep(10); + if (pdata->recv_task_num == 1) { + SEC_TST_PRT("aead async output!\n"); + if (pdata->data_fmt == WD_SGL_BUF) { // use no-sva sgl + wd_sgl_cp_to_pbuf(opdata->out, 0, tmp, opdata->out_bytes + auth_size); + hexdump(tmp, opdata->out_bytes + auth_size); + } else { + hexdump(opdata->out, opdata->out_bytes + auth_size); + } + } +#endif + } while(!is_exit(pdata)); + + gettimeofday(&cur_tval, NULL); + time_used = (float)((cur_tval.tv_sec - pdata->start_tval.tv_sec) * 1000000 + + cur_tval.tv_usec - pdata->start_tval.tv_usec); + SEC_TST_PRT("time_used:%0.0f us, send task num:%d\n", time_used, pdata->send_task_num++); + speed = pdata->send_task_num / time_used * 1000000; + Perf = speed * in_size / 1024; //B->KB + SEC_TST_PRT("Pro-%d, thread_id-%d, speed:%0.3f ops, Perf: %ld KB/s\n", pid, thread_id, + speed, Perf); + +fail_release: + if (pdata->data_fmt == WD_SGL_BUF) { // use no-sva sgl + if (opdata->in) + wd_free_sgl(pdata->pool, opdata->in); + if (opdata->iv) + wd_free_sgl(pdata->pool, opdata->iv); + if (opdata->out) + wd_free_sgl(pdata->pool, opdata->out); + } else { // use no-sva pbuffer + if (opdata->in) + wd_free_blk(pdata->pool, opdata->in); + if (opdata->iv) + wd_free_blk(pdata->pool, opdata->iv); + if (opdata->out) + wd_free_blk(pdata->pool, opdata->out); + } + if (ctx) + wcrypto_del_aead_ctx(ctx); + if (tag) + free(tag); + free(opdata); + + return ret; +} +void *__sec_aead_async_func_test(void *data) +{ + sec_aead_async_func_test(data); + + return NULL; +} + +static int sec_aead_async_test(int thd_num, __u64 lcore_mask, + __u64 hcore_mask, enum cipher_op_type op_type, + char *dev_path, unsigned int node_mask, __u16 data_fmt) +{ + struct wd_blkpool_setup setup; + struct wd_sglpool_setup sp; + int i, ret,cnt = 0; + struct wd_queue q; + void **pool; + + memset(&q, 0, sizeof(q)); + + q.capa.alg = "aead"; + if (op_type == ENCRYPTION) { + q.capa.priv.direction = 0; // 0 is ENC, 1 is DEC + } else { + q.capa.priv.direction = 1; + } + + ret = wd_request_queue(&q); + if (ret) { + SEC_TST_PRT("request queue fail!\n"); + return ret; + } + + if (data_fmt == WD_SGL_BUF) { // use no-sva sgl + memset(&sp, 0, sizeof(setup)); + /* set pool inv + key + in + out */ + sp.buf_size = MAX_BLOCK_SZ * 4; + sp.align_size = 64; + sp.sge_num_in_sgl = 2; + sp.buf_num_in_sgl = sp.sge_num_in_sgl - 1; + sp.sgl_num = MAX_BLOCK_NM; + sp.buf_num = sp.buf_num_in_sgl * sp.sgl_num + sp.sgl_num + 2; + + /* create pool for every queue */ + SEC_TST_PRT("%s, create pool memory: %u\n", __func__, MAX_BLOCK_NM * setup.block_size); + pool = wd_sglpool_create(&q, &sp); + } else { // use no-sva pbuffer + memset(&setup, 0, sizeof(setup)); + /* set pool inv + key + in + out */ + setup.block_size = MAX_BLOCK_SZ; + setup.block_num = MAX_BLOCK_NM; + setup.align_size = SQE_SIZE; + + /* create pool for every queue */ + SEC_TST_PRT("%s, create pool memory: %u\n", __func__, MAX_BLOCK_NM * setup.block_size); + pool = wd_blkpool_create(&q, &setup); + } + + if (!pool) { + SEC_TST_PRT("%s(): create pool fail!\n", __func__); + return -ENOMEM; + } + + /* frist create the async poll thread! */ + test_thrds_data[0].pool = pool; + test_thrds_data[0].q = &q; + test_thrds_data[0].thread_num = 1; + test_thrds_data[0].op_type = op_type; + test_thrds_data[0].cpu_id = 0; + test_thrds_data[0].data_fmt = data_fmt; + ret = pthread_create(&system_test_thrds[0], NULL, + _aead_async_poll_test_thread, &test_thrds_data[0]); + if (ret) { + SEC_TST_PRT("Create poll thread fail!\n"); + return ret; + } + + //Ïß³ÌÊý Óë°óºË + if (_get_one_bits(lcore_mask) == 0 && + _get_one_bits(hcore_mask) == 0) + cnt = thd_num; + else + cnt = 1; + printf("cnt:%d\n", cnt); + for (i = 1 ; i <= cnt; i++) { + test_thrds_data[i].pool = pool; + test_thrds_data[i].q = &q; + test_thrds_data[i].thread_num = thd_num; + test_thrds_data[i].op_type = op_type; + test_thrds_data[i].cpu_id = _get_cpu_id(i, lcore_mask); + test_thrds_data[i].data_fmt = data_fmt; + + gettimeofday(&test_thrds_data[i].start_tval, NULL); + + ret = pthread_create(&system_test_thrds[i], NULL, + __sec_aead_async_func_test, &test_thrds_data[i]); + if (ret) { + SEC_TST_PRT("Create %dth thread fail!\n", i); + return ret; + } + } + + for (i = 1; i <= thd_num; i++) { + ret = pthread_join(system_test_thrds[i], NULL); + if (ret) { + SEC_TST_PRT("Join %dth thread fail!\n", i); + return ret; + } + } + asyn_thread_exit = 1; + ret = pthread_join(system_test_thrds[0], NULL); + if (ret) { + SEC_TST_PRT("Join %dth thread fail!\n", i); + return ret; + } + + if (data_fmt == WD_SGL_BUF) // use no-sva sgl + wd_sglpool_destroy(pool); + else // use no-sva pbuffer + wd_blkpool_destroy(pool); + wd_release_queue(&q); + return 0; +} + + +int main(int argc, char *argv[]) +{ + __u64 lcore_mask = 0; + __u64 hcore_mask = 0; + int thread_num = 1; + unsigned int node_msk = 0; + int direction = 0; + int value, pktsize, keylen, ivlen; + __u16 data_fmt = 0; + + if (!strcmp(argv[1], "-cipher")) { + printf("cipher %d\n", wd_get_available_dev_num("cipher")); + g_testalg = strtoul((char*)argv[2], NULL, 10); + g_algclass = CIPHER_CLASS; + } else if (!strcmp(argv[1], "-digest")) { + printf("digest %d\n", wd_get_available_dev_num("digest")); + g_testalg = strtoul((char*)argv[2], NULL, 10); + g_algclass = DIGEST_CLASS; + } else if (!strcmp(argv[1], "-aead")) { + printf("aead %d\n", wd_get_available_dev_num("aead")); + g_testalg = strtoul((char*)argv[2], NULL, 10); + g_algclass = AEAD_CLASS; + } + + if (!strcmp(argv[3], "-t")) { + thread_num = strtoul((char*)argv[4], NULL, 10); + if (thread_num <= 0 || thread_num > TEST_MAX_THRD) { + SEC_TST_PRT("Invalid threads num:%d!\n", thread_num); + SEC_TST_PRT("Now set threads num as 2\n"); + thread_num = 2; + } + } + + q_num = (thread_num - 1) / ctx_num_per_q + 1; + if (!strcmp(argv[5], "-optype")) { + direction = strtoul((char*)argv[6], NULL, 10); + } + printf("dirction is: %d\n", direction); + if (direction == 0) { + alg_op_type = ENCRYPTION; + } else { + alg_op_type = DECRYPTION; + } + /* tools supports time and freq test currently. */ + if (!strcmp(argv[7], "-seconds") || !strcmp(argv[7], "-cycles")) { + value = strtoul((char*)argv[8], NULL, 10); + if (!strcmp(argv[7], "-seconds")) { + t_seconds = value; + } else if (!strcmp(argv[7], "-cycles")) { + t_times = value; + } else { + SEC_TST_PRT("pls use ./test_hisi_sec -help get details!\n"); + return -EINVAL; + } + } + printf("test seconds:%d\n", t_seconds); + if (!strcmp(argv[9], "-pktlen")) { + pktsize = strtoul((char*)argv[10], NULL, 10); + pktlen = pktsize; + } + if (!strcmp(argv[11], "-keylen")) { + keylen = strtoul((char*)argv[12], NULL, 10); + g_keylen = keylen; + } + if (!strcmp(argv[13], "-ivlen")) { + ivlen = strtoul((char*)argv[14], NULL, 10); + g_ivlen = ivlen; + } + + printf("test set: key len:%d, iv len:%d\n", g_keylen, g_ivlen); + + if (!strcmp(argv[16], "-f")) { + data_fmt = atoi(argv[17]); + if (data_fmt > 1) + printf("data_fmt error, data_fmt = %d.\n", data_fmt); + } + printf("data_fmt = %d\n", data_fmt); + + q_num = thread_num * ctx_num_per_q; + if (!strcmp(argv[15], "-sync")) { + printf("test type is sync\n"); + if (g_algclass == CIPHER_CLASS || g_algclass == DIGEST_CLASS) + sec_cipher_sync_test(thread_num, lcore_mask, hcore_mask, + alg_op_type, NULL, node_msk, data_fmt); + else if (g_algclass == AEAD_CLASS) + sec_aead_sync_test(thread_num, lcore_mask, hcore_mask, + alg_op_type, NULL, node_msk, data_fmt); + else + printf("test alg type not supported\n"); + } else if (!strcmp(argv[15], "-async")) { + printf("test type is async\n"); + if (g_algclass == CIPHER_CLASS || g_algclass == DIGEST_CLASS) + sec_cipher_async_test(thread_num, lcore_mask, hcore_mask, + alg_op_type, NULL, node_msk, data_fmt); + else if (g_algclass == AEAD_CLASS) + sec_aead_async_test(thread_num, lcore_mask, hcore_mask, + alg_op_type, NULL, node_msk, data_fmt); + else + printf("test alg type not supported\n"); + } else { + SEC_TST_PRT("Now Please set the cipher test type! -sync or -async.\n"); + } + + return 0; +} diff --git a/uadk/v1/test/hisi_sec_test_sgl/test_hisi_sec_sgl.h b/uadk/v1/test/hisi_sec_test_sgl/test_hisi_sec_sgl.h new file mode 100644 index 0000000..ba95e68 --- /dev/null +++ b/uadk/v1/test/hisi_sec_test_sgl/test_hisi_sec_sgl.h @@ -0,0 +1,1566 @@ +/* + * Copyright 2020 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#ifndef __HISI_TEST_SEC_H +#define __HISI_TEST_SEC_H + +enum alg_class { + CIPHER_CLASS, + AEAD_CLASS, + DIGEST_CLASS, +}; + +enum cipher_op_type { + ENCRYPTION, + DECRYPTION, +}; + +enum cipher_alg { + CIPHER_SM4, + CIPHER_AES, + CIPHER_DES, + CIPHER_3DES, +}; + +enum cipher_mode { + ECB, + CBC, + CTR, + XTS, + OFB +}; + +struct cipher_testvec { + const char *key; + int klen; + const char *iv; + int ivlen; + const char *iv_out; + const char *ptext; + const char *ctext; + int len; +}; + +enum sec_digest_state { + SEC_DIGEST_INIT = 0, + SEC_DIGEST_FIRST_UPDATING, + SEC_DIGEST_DOING, + SEC_DIGEST_FINAL +}; + +struct hash_testvec { + const char *key; + const char *plaintext; + const char *digest; + unsigned int psize; + unsigned short ksize; + unsigned int dsize; +}; + +struct aead_testvec { + const char *key; + const char *iv; + const char *ptext; + const char *assoc; + const char *ctext; + unsigned char novrfy; + unsigned char wk; + unsigned char klen; + unsigned int plen; + unsigned int clen; + unsigned int alen; + int setkey_error; + int setauthsize_error; + int crypt_error; +}; + +/* 192bit */ +struct cipher_testvec des3_ecb_tv_template_192[] = { + { + .key = "\x10\x46\x10\x34\x89\x98\x80\x20" + "\x91\x07\xd0\x15\x89\x19\x01\x01" + "\x19\x07\x92\x10\x98\x1a\x01\x01", + .klen = 24, + .ptext = "\x00\x00\x00\x00\x00\x00\x00\x00", + .ctext = "\xe1\xef\x62\xc3\x32\xfe\x82\x5b", + .len = 8, + } +}; + +/* 128bit */ +struct cipher_testvec des3_ecb_tv_template_128[] = { + { + .key = "\x10\x46\x10\x34\x89\x98\x80\x20" + "\x91\x07\xd0\x15\x89\x19\x01\x01", + .klen = 16, + .ptext = "\x00\x00\x00\x00\x00\x00\x00\x00", + .ctext = "\x8C\x78\x59\xEB\x1B\xD7\x4F\x0C", + .len = 8, + } +}; + +/* 192bit */ +struct cipher_testvec des3_cbc_tv_template_192[] = { + { + .key = "\xE9\xC0\xFF\x2E\x76\x0B\x64\x24" + "\x44\x4D\x99\x5A\x12\xD6\x40\xC0" + "\xEA\xC2\x84\xE8\x14\x95\xDB\xE8", + .klen = 24, + .iv = "\x7D\x33\x88\x93\x0F\x93\xB2\x42", + .iv_out = "\x6b\xfa\xb1\x91\x13\xb0\xd9\x19", + .ptext = "\x6f\x54\x20\x6f\x61\x4d\x79\x6e" + "\x53\x20\x63\x65\x65\x72\x73\x74" + "\x54\x20\x6f\x6f\x4d\x20\x6e\x61" + "\x20\x79\x65\x53\x72\x63\x74\x65" + "\x20\x73\x6f\x54\x20\x6f\x61\x4d" + "\x79\x6e\x53\x20\x63\x65\x65\x72" + "\x73\x74\x54\x20\x6f\x6f\x4d\x20" + "\x6e\x61\x20\x79\x65\x53\x72\x63" + "\x74\x65\x20\x73\x6f\x54\x20\x6f" + "\x61\x4d\x79\x6e\x53\x20\x63\x65" + "\x65\x72\x73\x74\x54\x20\x6f\x6f" + "\x4d\x20\x6e\x61\x20\x79\x65\x53" + "\x72\x63\x74\x65\x20\x73\x6f\x54" + "\x20\x6f\x61\x4d\x79\x6e\x53\x20" + "\x63\x65\x65\x72\x73\x74\x54\x20" + "\x6f\x6f\x4d\x20\x6e\x61\x0a\x79", + .ctext = "\x0e\x2d\xb6\x97\x3c\x56\x33\xf4" + "\x67\x17\x21\xc7\x6e\x8a\xd5\x49" + "\x74\xb3\x49\x05\xc5\x1c\xd0\xed" + "\x12\x56\x5c\x53\x96\xb6\x00\x7d" + "\x90\x48\xfc\xf5\x8d\x29\x39\xcc" + "\x8a\xd5\x35\x18\x36\x23\x4e\xd7" + "\x76\xd1\xda\x0c\x94\x67\xbb\x04" + "\x8b\xf2\x03\x6c\xa8\xcf\xb6\xea" + "\x22\x64\x47\xaa\x8f\x75\x13\xbf" + "\x9f\xc2\xc3\xf0\xc9\x56\xc5\x7a" + "\x71\x63\x2e\x89\x7b\x1e\x12\xca" + "\xe2\x5f\xaf\xd8\xa4\xf8\xc9\x7a" + "\xd6\xf9\x21\x31\x62\x44\x45\xa6" + "\xd6\xbc\x5a\xd3\x2d\x54\x43\xcc" + "\x9d\xde\xa5\x70\xe9\x42\x45\x8a" + "\x6b\xfa\xb1\x91\x13\xb0\xd9\x19", + .len = 128, + } +}; + +/* 128bit */ +struct cipher_testvec des3_cbc_tv_template_128[] = { + { + .key = "\xE9\xC0\xFF\x2E\x76\x0B\x64\x24" + "\x44\x4D\x99\x5A\x12\xD6\x40\xC0", + .klen = 16, + .iv = "\x7D\x33\x88\x93\x0F\x93\xB2\x42", + .iv_out = "\x6b\xfa\xb1\x91\x13\xb0\xd9\x19", + .ptext = "\x6f\x54\x20\x6f\x61\x4d\x79\x6e" + "\x53\x20\x63\x65\x65\x72\x73\x74" + "\x54\x20\x6f\x6f\x4d\x20\x6e\x61" + "\x20\x79\x65\x53\x72\x63\x74\x65" + "\x20\x73\x6f\x54\x20\x6f\x61\x4d" + "\x79\x6e\x53\x20\x63\x65\x65\x72" + "\x73\x74\x54\x20\x6f\x6f\x4d\x20" + "\x6e\x61\x20\x79\x65\x53\x72\x63" + "\x74\x65\x20\x73\x6f\x54\x20\x6f" + "\x61\x4d\x79\x6e\x53\x20\x63\x65" + "\x65\x72\x73\x74\x54\x20\x6f\x6f" + "\x4d\x20\x6e\x61\x20\x79\x65\x53" + "\x72\x63\x74\x65\x20\x73\x6f\x54" + "\x20\x6f\x61\x4d\x79\x6e\x53\x20" + "\x63\x65\x65\x72\x73\x74\x54\x20" + "\x6f\x6f\x4d\x20\x6e\x61\x0a\x79", + .ctext = "\xC2\x3D\x49\x51\x0B\x2E\xA7\x4C" + "\x8D\x71\x42\x0F\xDD\xFF\xA0\x2D" + "\x5A\xBD\x2F\x0A\xD5\xAF\xEA\xA3" + "\x25\x5A\x22\x99\x71\xB0\xE6\x66" + "\x51\xC2\x31\x79\x82\xEE\x23\xE7" + "\x98\xCD\xFE\x11\x47\x29\xE3\x01" + "\x3F\x8F\xCC\x87\x37\x90\xC3\xA9" + "\x86\xAC\x98\x5C\x2B\x97\xA4\x1E" + "\xE2\xFD\x51\xEA\xBC\x9F\x20\x4A" + "\x80\xFC\xA1\xE8\xDE\x93\x34\x01" + "\xB5\xBF\x6D\xDC\x81\x3E\x71\xB4" + "\x90\x16\x20\xF0\x4E\x4D\xBC\x95" + "\x62\xC1\x89\x91\x72\xEB\xF6\xF6" + "\x58\x4E\x7C\x5B\x73\x17\xD0\x96" + "\xAF\x15\x97\x0D\x6D\xAB\xD0\xFB" + "\x2E\xCD\x07\xF2\xF6\xE6\xB0\x75", + .len = 128, + } +}; + +/* 128bit */ +struct cipher_testvec aes_ecb_tv_template_128[] = { + { + .key = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .klen = 16, + .ptext = "\x00\x11\x22\x33\x44\x55\x66\x77" + "\x88\x99\xaa\xbb\xcc\xdd\xee\xff", + .ctext = "\x69\xc4\xe0\xd8\x6a\x7b\x04\x30" + "\xd8\xcd\xb7\x80\x70\xb4\xc5\x5a", + .len = 16, + } +}; + +/* 192bit */ +struct cipher_testvec aes_ecb_tv_template_192[] = { + { + .key = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17", + .klen = 24, + .ptext = "\x00\x11\x22\x33\x44\x55\x66\x77" + "\x88\x99\xaa\xbb\xcc\xdd\xee\xff", + .ctext = "\xdd\xa9\x7c\xa4\x86\x4c\xdf\xe0" + "\x6e\xaf\x70\xa0\xec\x0d\x71\x91", + .len = 16, + } +}; + +/* 128bit */ +struct cipher_testvec sm4_cbc_tv_template[] = { + { + .key = "\x01\x23\x45\x67\x89\xAB\xCD\xEF" + "\xFE\xDC\xBA\x98\x76\x54\x32\x10", + .klen = 16, + .ptext = "\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb" + "\xcc\xcc\xcc\xcc\xdd\xdd\xdd\xdd" + "\xee\xee\xee\xee\xff\xff\xff\xff" + "\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb", + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", + .iv_out = "\x4C\xB7\x01\x69\x51\x90\x92\x26" + "\x97\x9B\x0D\x15\xDC\x6A\x8F\x6D", + .ctext = "\x78\xEB\xB1\x1C\xC4\x0B\x0A\x48" + "\x31\x2A\xAE\xB2\x04\x02\x44\xCB" + "\x4C\xB7\x01\x69\x51\x90\x92\x26" + "\x97\x9B\x0D\x15\xDC\x6A\x8F\x6D", + .len = 32, + } +}; + +/* 256bit */ +struct cipher_testvec sm4_xts_tv_template[] = { + { + .key = "\x11\x11\x11\x11\x11\x11\x11\x11" + "\x11\x11\x11\x11\x11\x11\x11\x11" + "\x22\x22\x22\x22\x22\x22\x22\x22" + "\x22\x22\x22\x22\x22\x22\x22\x22", + .klen = 32, + .iv = "\x33\x33\x33\x33\x33\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00", + .ptext = "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44", + .ctext = "\xA7\x4D\x72\x6C\x11\x19\x6A\x32" + "\xBE\x04\xE0\x01\xFF\x29\xD0\xC7" + "\x93\x2F\x9F\x3E\xC2\x9B\xFC\xB6" + "\x4D\xD1\x7F\x63\xCB\xD3\xEA\x31", + .len = 32, + } +}; + +/* 256bit */ +struct cipher_testvec aes_ecb_tv_template_256[] = { + { + .key = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", + .klen = 32, + .ptext = "\x00\x11\x22\x33\x44\x55\x66\x77" + "\x88\x99\xaa\xbb\xcc\xdd\xee\xff", + .ctext = "\x8e\xa2\xb7\xca\x51\x67\x45\xbf" + "\xea\xfc\x49\x90\x4b\x49\x60\x89", + .len = 16, + } +}; + +/* 256bit */ +struct cipher_testvec aes_xts_tv_template_256[] = { + { + .key = "\x11\x11\x11\x11\x11\x11\x11\x11" + "\x11\x11\x11\x11\x11\x11\x11\x11" + "\x22\x22\x22\x22\x22\x22\x22\x22" + "\x22\x22\x22\x22\x22\x22\x22\x22", + .klen = 32, + .iv = "\x33\x33\x33\x33\x33\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00", + .ptext = "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44", + .ctext = "\xc4\x54\x18\x5e\x6a\x16\x93\x6e" + "\x39\x33\x40\x38\xac\xef\x83\x8b" + "\xfb\x18\x6f\xff\x74\x80\xad\xc4" + "\x28\x93\x82\xec\xd6\xd3\x94\xf0", + .len = 32, + } +}; + +/* 512bit */ +struct cipher_testvec aes_xts_tv_template_512[] = { + { + .key = "\x27\x18\x28\x18\x28\x45\x90\x45" + "\x23\x53\x60\x28\x74\x71\x35\x26" + "\x62\x49\x77\x57\x24\x70\x93\x69" + "\x99\x59\x57\x49\x66\x96\x76\x27" + "\x31\x41\x59\x26\x53\x58\x97\x93" + "\x23\x84\x62\x64\x33\x83\x27\x95" + "\x02\x88\x41\x97\x16\x93\x99\x37" + "\x51\x05\x82\x09\x74\x94\x45\x92", + .klen = 64, + .iv = "\xff\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00", + .ptext = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + "\x20\x21\x22\x23\x24\x25\x26\x27" + "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" + "\x30\x31\x32\x33\x34\x35\x36\x37" + "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" + "\x40\x41\x42\x43\x44\x45\x46\x47" + "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f" + "\x50\x51\x52\x53\x54\x55\x56\x57" + "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f" + "\x60\x61\x62\x63\x64\x65\x66\x67" + "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f" + "\x70\x71\x72\x73\x74\x75\x76\x77" + "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f" + "\x80\x81\x82\x83\x84\x85\x86\x87" + "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" + "\x90\x91\x92\x93\x94\x95\x96\x97" + "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" + "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7" + "\xa8\xa9\xaa\xab\xac\xad\xae\xaf" + "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7" + "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" + "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" + "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" + "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7" + "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" + "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7" + "\xe8\xe9\xea\xeb\xec\xed\xee\xef" + "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7" + "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff" + "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + "\x20\x21\x22\x23\x24\x25\x26\x27" + "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" + "\x30\x31\x32\x33\x34\x35\x36\x37" + "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" + "\x40\x41\x42\x43\x44\x45\x46\x47" + "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f" + "\x50\x51\x52\x53\x54\x55\x56\x57" + "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f" + "\x60\x61\x62\x63\x64\x65\x66\x67" + "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f" + "\x70\x71\x72\x73\x74\x75\x76\x77" + "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f" + "\x80\x81\x82\x83\x84\x85\x86\x87" + "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" + "\x90\x91\x92\x93\x94\x95\x96\x97" + "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" + "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7" + "\xa8\xa9\xaa\xab\xac\xad\xae\xaf" + "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7" + "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" + "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" + "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" + "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7" + "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" + "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7" + "\xe8\xe9\xea\xeb\xec\xed\xee\xef" + "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7" + "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff", + .ctext = "\x1c\x3b\x3a\x10\x2f\x77\x03\x86" + "\xe4\x83\x6c\x99\xe3\x70\xcf\x9b" + "\xea\x00\x80\x3f\x5e\x48\x23\x57" + "\xa4\xae\x12\xd4\x14\xa3\xe6\x3b" + "\x5d\x31\xe2\x76\xf8\xfe\x4a\x8d" + "\x66\xb3\x17\xf9\xac\x68\x3f\x44" + "\x68\x0a\x86\xac\x35\xad\xfc\x33" + "\x45\xbe\xfe\xcb\x4b\xb1\x88\xfd" + "\x57\x76\x92\x6c\x49\xa3\x09\x5e" + "\xb1\x08\xfd\x10\x98\xba\xec\x70" + "\xaa\xa6\x69\x99\xa7\x2a\x82\xf2" + "\x7d\x84\x8b\x21\xd4\xa7\x41\xb0" + "\xc5\xcd\x4d\x5f\xff\x9d\xac\x89" + "\xae\xba\x12\x29\x61\xd0\x3a\x75" + "\x71\x23\xe9\x87\x0f\x8a\xcf\x10" + "\x00\x02\x08\x87\x89\x14\x29\xca" + "\x2a\x3e\x7a\x7d\x7d\xf7\xb1\x03" + "\x55\x16\x5c\x8b\x9a\x6d\x0a\x7d" + "\xe8\xb0\x62\xc4\x50\x0d\xc4\xcd" + "\x12\x0c\x0f\x74\x18\xda\xe3\xd0" + "\xb5\x78\x1c\x34\x80\x3f\xa7\x54" + "\x21\xc7\x90\xdf\xe1\xde\x18\x34" + "\xf2\x80\xd7\x66\x7b\x32\x7f\x6c" + "\x8c\xd7\x55\x7e\x12\xac\x3a\x0f" + "\x93\xec\x05\xc5\x2e\x04\x93\xef" + "\x31\xa1\x2d\x3d\x92\x60\xf7\x9a" + "\x28\x9d\x6a\x37\x9b\xc7\x0c\x50" + "\x84\x14\x73\xd1\xa8\xcc\x81\xec" + "\x58\x3e\x96\x45\xe0\x7b\x8d\x96" + "\x70\x65\x5b\xa5\xbb\xcf\xec\xc6" + "\xdc\x39\x66\x38\x0a\xd8\xfe\xcb" + "\x17\xb6\xba\x02\x46\x9a\x02\x0a" + "\x84\xe1\x8e\x8f\x84\x25\x20\x70" + "\xc1\x3e\x9f\x1f\x28\x9b\xe5\x4f" + "\xbc\x48\x14\x57\x77\x8f\x61\x60" + "\x15\xe1\x32\x7a\x02\xb1\x40\xf1" + "\x50\x5e\xb3\x09\x32\x6d\x68\x37" + "\x8f\x83\x74\x59\x5c\x84\x9d\x84" + "\xf4\xc3\x33\xec\x44\x23\x88\x51" + "\x43\xcb\x47\xbd\x71\xc5\xed\xae" + "\x9b\xe6\x9a\x2f\xfe\xce\xb1\xbe" + "\xc9\xde\x24\x4f\xbe\x15\x99\x2b" + "\x11\xb7\x7c\x04\x0f\x12\xbd\x8f" + "\x6a\x97\x5a\x44\xa0\xf9\x0c\x29" + "\xa9\xab\xc3\xd4\xd8\x93\x92\x72" + "\x84\xc5\x87\x54\xcc\xe2\x94\x52" + "\x9f\x86\x14\xdc\xd2\xab\xa9\x91" + "\x92\x5f\xed\xc4\xae\x74\xff\xac" + "\x6e\x33\x3b\x93\xeb\x4a\xff\x04" + "\x79\xda\x9a\x41\x0e\x44\x50\xe0" + "\xdd\x7a\xe4\xc6\xe2\x91\x09\x00" + "\x57\x5d\xa4\x01\xfc\x07\x05\x9f" + "\x64\x5e\x8b\x7e\x9b\xfd\xef\x33" + "\x94\x30\x54\xff\x84\x01\x14\x93" + "\xc2\x7b\x34\x29\xea\xed\xb4\xed" + "\x53\x76\x44\x1a\x77\xed\x43\x85" + "\x1a\xd7\x7f\x16\xf5\x41\xdf\xd2" + "\x69\xd5\x0d\x6a\x5f\x14\xfb\x0a" + "\xab\x1c\xbb\x4c\x15\x50\xbe\x97" + "\xf7\xab\x40\x66\x19\x3c\x4c\xaa" + "\x77\x3d\xad\x38\x01\x4b\xd2\x09" + "\x2f\xa7\x55\xc8\x24\xbb\x5e\x54" + "\xc4\xf3\x6f\xfd\xa9\xfc\xea\x70" + "\xb9\xc6\xe6\x93\xe1\x48\xc1\x51", + .len = 512, + } +}; + +/* 128bit */ +struct cipher_testvec aes_cbc_tv_template_128[] = { + { + .key = "\x06\xa9\x21\x40\x36\xb8\xa1\x5b" + "\x51\x2e\x03\xd5\x34\x12\x00\x06", + .klen = 16, + .iv = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30" + "\xb4\x22\xda\x80\x2c\x9f\xac\x41", + .iv_out = "\xe3\x53\x77\x9c\x10\x79\xae\xb8" + "\x27\x08\x94\x2d\xbe\x77\x18\x1a", + .ptext = "Single block msg", + .ctext = "\xe3\x53\x77\x9c\x10\x79\xae\xb8" + "\x27\x08\x94\x2d\xbe\x77\x18\x1a", + .len = 16, + } +}; +/* 192bit */ +struct cipher_testvec aes_cbc_tv_template_192[] = { + /* From NIST SP800-38A */ + { + .key = "\x8e\x73\xb0\xf7\xda\x0e\x64\x52" + "\xc8\x10\xf3\x2b\x80\x90\x79\xe5" + "\x62\xf8\xea\xd2\x52\x2c\x6b\x7b", + .klen = 24, + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .iv_out = "\x08\xb0\xe2\x79\x88\x59\x88\x81" + "\xd9\x20\xa9\xe6\x4f\x56\x15\xcd", + .ptext = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" + "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" + "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" + "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" + "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" + "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + .ctext = "\x4f\x02\x1d\xb2\x43\xbc\x63\x3d" + "\x71\x78\x18\x3a\x9f\xa0\x71\xe8" + "\xb4\xd9\xad\xa9\xad\x7d\xed\xf4" + "\xe5\xe7\x38\x76\x3f\x69\x14\x5a" + "\x57\x1b\x24\x20\x12\xfb\x7a\xe0" + "\x7f\xa9\xba\xac\x3d\xf1\x02\xe0" + "\x08\xb0\xe2\x79\x88\x59\x88\x81" + "\xd9\x20\xa9\xe6\x4f\x56\x15\xcd", + .len = 64, + } +}; + +struct cipher_testvec aes_ctr_tv_template_128[] = { + { + .key = "\x2b\x7e\x15\x16\x28\xae\xd2\xa6" + "\xab\xf7\x15\x88\x09\xcf\x4f\x3c", + .klen = 16, + .iv = "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7" + "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff", + .iv_out = "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7" + "\xf8\xf9\xfa\xfb\xfc\xfd\xff\x03", + .ptext = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" + "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" + "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" + "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" + "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" + "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + .ctext = "\x87\x4d\x61\x91\xb6\x20\xe3\x26" + "\x1b\xef\x68\x64\x99\x0d\xb6\xce" + "\x98\x06\xf6\x6b\x79\x70\xfd\xff" + "\x86\x17\x18\x7b\xb9\xff\xfd\xff" + "\x5a\xe4\xdf\x3e\xdb\xd5\xd3\x5e" + "\x5b\x4f\x09\x02\x0d\xb0\x3e\xab" + "\x1e\x03\x1d\xda\x2f\xbe\x03\xd1" + "\x79\x21\x70\xa0\xf3\x00\x9c\xee", + .len = 64, + } +}; + +struct cipher_testvec aes_ctr_tv_template_192[] = { + { + .key = "\x8e\x73\xb0\xf7\xda\x0e\x64\x52" + "\xc8\x10\xf3\x2b\x80\x90\x79\xe5" + "\x62\xf8\xea\xd2\x52\x2c\x6b\x7b", + .klen = 24, + .iv = "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7" + "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff", + .iv_out = "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7" + "\xf8\xf9\xfa\xfb\xfc\xfd\xff\x03", + .ptext = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" + "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" + "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" + "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" + "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" + "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + .ctext = "\x1a\xbc\x93\x24\x17\x52\x1c\xa2" + "\x4f\x2b\x04\x59\xfe\x7e\x6e\x0b" + "\x09\x03\x39\xec\x0a\xa6\xfa\xef" + "\xd5\xcc\xc2\xc6\xf4\xce\x8e\x94" + "\x1e\x36\xb2\x6b\xd1\xeb\xc6\x70" + "\xd1\xbd\x1d\x66\x56\x20\xab\xf7" + "\x4f\x78\xa7\xf6\xd2\x98\x09\x58" + "\x5a\x97\xda\xec\x58\xc6\xb0\x50", + .len = 64, + } +}; + +struct cipher_testvec aes_ctr_tv_template_256[] = { + { + .key = "\x60\x3d\xeb\x10\x15\xca\x71\xbe" + "\x2b\x73\xae\xf0\x85\x7d\x77\x81" + "\x1f\x35\x2c\x07\x3b\x61\x08\xd7" + "\x2d\x98\x10\xa3\x09\x14\xdf\xf4", + .klen = 32, + .iv = "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7" + "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff", + .iv_out = "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7" + "\xf8\xf9\xfa\xfb\xfc\xfd\xff\x03", + .ptext = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" + "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" + "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" + "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" + "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" + "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + .ctext = "\x60\x1e\xc3\x13\x77\x57\x89\xa5" + "\xb7\xa7\xf5\x04\xbb\xf3\xd2\x28" + "\xf4\x43\xe3\xca\x4d\x62\xb5\x9a" + "\xca\x84\xe9\x90\xca\xca\xf5\xc5" + "\x2b\x09\x30\xda\xa2\x3d\xe9\x4c" + "\xe8\x70\x17\xba\x2d\x84\x98\x8d" + "\xdf\xc9\xc5\x8d\xb6\x7a\xad\xa6" + "\x13\xc2\xdd\x08\x45\x79\x41\xa6", + .len = 64, + } +}; + +/* 256bit */ +struct cipher_testvec aes_cbc_tv_template_256[] = { + { + .key = "\x60\x3d\xeb\x10\x15\xca\x71\xbe" + "\x2b\x73\xae\xf0\x85\x7d\x77\x81" + "\x1f\x35\x2c\x07\x3b\x61\x08\xd7" + "\x2d\x98\x10\xa3\x09\x14\xdf\xf4", + .klen = 32, + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .iv_out = "\xb2\xeb\x05\xe2\xc3\x9b\xe9\xfc" + "\xda\x6c\x19\x07\x8c\x6a\x9d\x1b", + .ptext = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" + "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" + "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" + "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" + "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" + "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + .ctext = "\xf5\x8c\x4c\x04\xd6\xe5\xf1\xba" + "\x77\x9e\xab\xfb\x5f\x7b\xfb\xd6" + "\x9c\xfc\x4e\x96\x7e\xdb\x80\x8d" + "\x67\x9f\x77\x7b\xc6\x70\x2c\x7d" + "\x39\xf2\x33\x69\xa9\xd9\xba\xcf" + "\xa5\x30\xe2\x63\x04\x23\x14\x61" + "\xb2\xeb\x05\xe2\xc3\x9b\xe9\xfc" + "\xda\x6c\x19\x07\x8c\x6a\x9d\x1b", + .len = 64, + } +}; + +struct cipher_testvec aes_ofb_tv_template_128[] = { + { + .key = "\x2b\x7e\x15\x16\x28\xae\xd2\xa6" + "\xab\xf7\x15\x88\x09\xcf\x4f\x3c", + .klen = 16, + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07\x08" + "\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .ptext = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" + "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" + "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" + "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" + "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" + "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + .ctext = "\x3b\x3f\xd9\x2e\xb7\x2d\xad\x20" + "\x33\x34\x49\xf8\xe8\x3c\xfb\x4a" + "\x77\x89\x50\x8d\x16\x91\x8f\x03" + "\xf5\x3c\x52\xda\xc5\x4e\xd8\x25" + "\x97\x40\x05\x1e\x9c\x5f\xec\xf6" + "\x43\x44\xf7\xa8\x22\x60\xed\xcc" + "\x30\x4c\x65\x28\xf6\x59\xc7\x78" + "\x66\xa5\x10\xd9\xc1\xd6\xae\x5e", + .len = 64, + } +}; + +//openssl create +struct cipher_testvec aes_ofb_tv_template_192[] = { + { + .key = "\x2b\x7e\x15\x16\x28\xae\xd2\xa6" + "\xab\xf7\x15\x88\x09\xcf\x4f\x3c" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .klen = 24, + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .ptext = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" + "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" + "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" + "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" + "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" + "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + .ctext = "\x6e\x29\x6a\xb1\x64\x8b\x7b\x81" + "\xfa\x62\x8f\xfa\xc6\x9f\x48\x6f" + "\x32\xe2\xaa\x04\x6a\x81\x04\xb8" + "\xc1\xe4\xe5\x1b\xb0\xc1\x89\xca" + "\x41\x6d\x43\xf1\x83\xf4\x9d\x90" + "\xbf\x68\xe6\xea\xd5\xed\x83\x1c" + "\xff\xf2\xf9\xfa\xf8\x3e\xba\x82" + "\x7e\xca\x94\x72\x64\x3f\x72\xdf", + .len = 64, + } +}; + +struct cipher_testvec aes_ofb_tv_template_256[] = { + { + .key = "\x2b\x7e\x15\x16\x28\xae\xd2\xa6" + "\xab\xf7\x15\x88\x09\xcf\x4f\x3c" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x00\x01\x02\x03\x04\x05\x06\x07", + .klen = 32, + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .ptext = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" + "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" + "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" + "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" + "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" + "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + .ctext = "\x36\x7d\xf9\x01\x2f\x31\xde\x8c" + "\x7f\xc1\x26\x1a\xbc\x8a\x35\xe5" + "\x00\x24\xad\xcb\x60\x5d\xb9\xea" + "\x12\xdd\x0b\xd2\x44\x2a\x24\x51" + "\x4f\x13\x1e\x7c\xa2\xad\xe9\x8c" + "\x55\x80\x75\xc6\x4d\xf2\x24\xde" + "\x30\xa0\xbb\xe7\x6d\xf8\xd1\x23" + "\x9d\x9f\xad\xd2\x9f\x87\x4f\x1c", + .len = 64, + } +}; + + +struct cipher_testvec aes_cfb_tv_template_128[] = { + { /* From NIST SP800-38A */ + .key = "\x2b\x7e\x15\x16\x28\xae\xd2\xa6" + "\xab\xf7\x15\x88\x09\xcf\x4f\x3c", + .klen = 16, + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .ptext = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" + "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" + "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" + "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" + "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" + "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + .ctext = "\x3b\x3f\xd9\x2e\xb7\x2d\xad\x20" + "\x33\x34\x49\xf8\xe8\x3c\xfb\x4a" + "\xc8\xa6\x45\x37\xa0\xb3\xa9\x3f" + "\xcd\xe3\xcd\xad\x9f\x1c\xe5\x8b" + "\x26\x75\x1f\x67\xa3\xcb\xb1\x40" + "\xb1\x80\x8c\xf1\x87\xa4\xf4\xdf" + "\xc0\x4b\x05\x35\x7c\x5d\x1c\x0e" + "\xea\xc4\xc6\x6f\x9f\xf7\xf2\xe6", + .len = 64, + } +}; + +struct cipher_testvec aes_cfb_tv_template_192[] = { + { + .key = "\x8e\x73\xb0\xf7\xda\x0e\x64\x52" + "\xc8\x10\xf3\x2b\x80\x90\x79\xe5" + "\x62\xf8\xea\xd2\x52\x2c\x6b\x7b", + .klen = 24, + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .ptext = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" + "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" + "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" + "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" + "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" + "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + .ctext = "\xcd\xc8\x0d\x6f\xdd\xf1\x8c\xab" + "\x34\xc2\x59\x09\xc9\x9a\x41\x74" + "\x67\xce\x7f\x7f\x81\x17\x36\x21" + "\x96\x1a\x2b\x70\x17\x1d\x3d\x7a" + "\x2e\x1e\x8a\x1d\xd5\x9b\x88\xb1" + "\xc8\xe6\x0f\xed\x1e\xfa\xc4\xc9" + "\xc0\x5f\x9f\x9c\xa9\x83\x4f\xa0" + "\x42\xae\x8f\xba\x58\x4b\x09\xff", + .len = 64, + } +}; + +struct cipher_testvec aes_cfb_tv_template_256[] = { + { + .key = "\x60\x3d\xeb\x10\x15\xca\x71\xbe" + "\x2b\x73\xae\xf0\x85\x7d\x77\x81" + "\x1f\x35\x2c\x07\x3b\x61\x08\xd7" + "\x2d\x98\x10\xa3\x09\x14\xdf\xf4", + .klen = 32, + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .ptext = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" + "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" + "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" + "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" + "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" + "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + .ctext = "\xdc\x7e\x84\xbf\xda\x79\x16\x4b" + "\x7e\xcd\x84\x86\x98\x5d\x38\x60" + "\x39\xff\xed\x14\x3b\x28\xb1\xc8" + "\x32\x11\x3c\x63\x31\xe5\x40\x7b" + "\xdf\x10\x13\x24\x15\xe5\x4b\x92" + "\xa1\x3e\xd0\xa8\x26\x7a\xe2\xf9" + "\x75\xa3\x85\x74\x1a\xb9\xce\xf8" + "\x20\x31\x62\x3d\x55\xb1\xe4\x71", + .len = 64, + } +}; + +struct cipher_testvec sm4_ctr_tv_template_128[] = { + { /* A.2.5.1 SM4-CTR Example 1 */ + .key = "\x01\x23\x45\x67\x89\xAB\xCD\xEF" + "\xFE\xDC\xBA\x98\x76\x54\x32\x10", + .klen = 16, + .ptext = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb" + "\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xee\xee\xee\xee\xee\xee\xee\xee" + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb", + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", + .iv_out = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0A\x0B\x0C\x0D\x0E\x13", + .ctext = "\xac\x32\x36\xcb\x97\x0c\xc2\x07" + "\x91\x36\x4c\x39\x5a\x13\x42\xd1" + "\xa3\xcb\xc1\x87\x8c\x6f\x30\xcd" + "\x07\x4c\xce\x38\x5c\xdd\x70\xc7" + "\xf2\x34\xbc\x0e\x24\xc1\x19\x80" + "\xfd\x12\x86\x31\x0c\xe3\x7b\x92" + "\x6e\x02\xfc\xd0\xfa\xa0\xba\xf3" + "\x8b\x29\x33\x85\x1d\x82\x45\x14", + .len = 64, + } +}; + +//openssl create sm4_ofb template +struct cipher_testvec sm4_ofb_tv_template_128[] = { + { /* From NIST SP800-38A */ + .key = "\x2b\x7e\x15\x16\x28\xae\xd2\xa6" + "\xab\xf7\x15\x88\x09\xcf\x4f\x3c", + .klen = 16, + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .ptext = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a", + .ctext = "\xbc\x71\x0d\x76\x2d\x07\x0b\x26" + "\x36\x1d\xa8\x2b\x54\x56\x5e\x46", + .len = 16, + } +}; +//openssl create sm4_cfb template +struct cipher_testvec sm4_cfb_tv_template_128[] = { + { /* From NIST SP800-38A */ + .key = "\x2b\x7e\x15\x16\x28\xae\xd2\xa6" + "\xab\xf7\x15\x88\x09\xcf\x4f\x3c", + .klen = 16, + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .ptext = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a", + .ctext = "\xbc\x71\x0d\x76\x2d\x07\x0b\x26" + "\x36\x1d\xa8\x2b\x54\x56\x5e\x46", + .len = 16, + } +}; + +/* 128bit */ +struct aead_testvec aes_ccm_tv_template_128[] = { + { + .key = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" + "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf", + .klen = 16, + .iv = "\x01\x00\x00\x00\x03\x02\x01\x00" + "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00", + .assoc = "\x00\x01\x02\x03\x04\x05\x06\x07", + .alen = 8, + .ptext = "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e", + .plen = 23, + .ctext = "\x58\x8c\x97\x9a\x61\xc6\x63\xd2" + "\xf0\x66\xd0\xc2\xc0\xf9\x89\x80" + "\x6d\x5f\x6b\x61\xda\xc3\x84\x17" + "\xe8\xd1\x2c\xfd\xf9\x26\xe0", + .clen = 31, + } +}; + +/* 192bit */ +struct aead_testvec aes_ccm_tv_template_192[] = { + { + .key = "\x56\xdf\x5c\x8f\x26\x3f\x0e\x42" + "\xef\x7a\xd3\xce\xfc\x84\x60\x62" + "\xca\xb4\x40\xaf\x5f\xc9\xc9\x01", + .klen = 24, + .iv = "\x03\xd6\x3c\x8c\x86\x84\xb6\xcd" + "\xef\x09\x2e\x94\x00\x00\x00\x00", + .assoc = "\x02\x65\x78\x3c\xe9\x21\x30\x91" + "\xb1\xb9\xda\x76\x9a\x78\x6d\x95" + "\xf2\x88\x32\xa3\xf2\x50\xcb\x4c" + "\xe3\x00\x73\x69\x84\x69\x87\x79", + .alen = 32, + .ptext = "\x9f\xd2\x02\x4b\x52\x49\x31\x3c" + "\x43\x69\x3a\x2d\x8e\x70\xad\x7e" + "\xe0\xe5\x46\x09\x80\x89\x13\xb2" + "\x8c\x8b\xd9\x3f\x86\xfb\xb5\x6b", + .plen = 32, + .ctext = "\x39\xdf\x7c\x3c\x5a\x29\xb9\x62" + "\x5d\x51\xc2\x16\xd8\xbd\x06\x9f" + "\x9b\x6a\x09\x70\xc1\x51\x83\xc2" + "\x66\x88\x1d\x4f\x9a\xda\xe0\x1e" + "\xc7\x79\x11\x58\xe5\x6b\x20\x40" + "\x7a\xea\x46\x42\x8b\xe4\x6f\xe1", + .clen = 48, + } +}; + +/* 256bit */ +struct aead_testvec aes_ccm_tv_template_256[] = { + { + .key = "\xe0\x8d\x99\x71\x60\xd7\x97\x1a" + "\xbd\x01\x99\xd5\x8a\xdf\x71\x3a" + "\xd3\xdf\x24\x4b\x5e\x3d\x4b\x4e" + "\x30\x7a\xb9\xd8\x53\x0a\x5e\x2b", + .klen = 32, + .iv = "\x03\x1e\x29\x91\xad\x8e\xc1\x53" + "\x0a\xcf\x2d\xbe\x00\x00\x00\x00", + .assoc = "\x19\xb6\x1f\x57\xc4\xf3\xf0\x8b" + "\x78\x2b\x94\x02\x29\x0f\x42\x27" + "\x6b\x75\xcb\x98\x34\x08\x7e\x79" + "\xe4\x3e\x49\x0d\x84\x8b\x22\x87", + .alen = 32, + .ptext = "\xe1\xd9\xd8\x13\xeb\x3a\x75\x3f" + "\x9d\xbd\x5f\x66\xbe\xdc\xbb\x66" + "\xbf\x17\x99\x62\x4a\x39\x27\x1f" + "\x1d\xdc\x24\xae\x19\x2f\x98\x4c", + .plen = 32, + .ctext = "\x19\xb8\x61\x33\x45\x2b\x43\x96" + "\x6f\x51\xd0\x20\x30\x7d\x9b\xc6" + "\x26\x3d\xf8\xc9\x65\x16\xa8\x9f" + "\xf0\x62\x17\x34\xf2\x1e\x8d\x75" + "\x4e\x13\xcc\xc0\xc3\x2a\x54\x2d", + .clen = 40, + } +}; + +/* 128bit */ +struct aead_testvec aes_gcm_tv_template_128[] = { + { + .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c" + "\x6d\x6a\x8f\x94\x67\x30\x83\x08", + .klen = 16, + .iv = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad" + "\xde\xca\xf8\x88", + .ptext = "\xd9\x31\x32\x25\xf8\x84\x06\xe5" + "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" + "\x86\xa7\xa9\x53\x15\x34\xf7\xda" + "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" + "\x1c\x3c\x0c\x95\x95\x68\x09\x53" + "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" + "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57" + "\xba\x63\x7b\x39\x1a\xaf\xd2\x55", + .plen = 64, + .ctext = "\x42\x83\x1e\xc2\x21\x77\x74\x24" + "\x4b\x72\x21\xb7\x84\xd0\xd4\x9c" + "\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0" + "\x35\xc1\x7e\x23\x29\xac\xa1\x2e" + "\x21\xd5\x14\xb2\x54\x66\x93\x1c" + "\x7d\x8f\x6a\x5a\xac\x84\xaa\x05" + "\x1b\xa3\x0b\x39\x6a\x0a\xac\x97" + "\x3d\x58\xe0\x91\x47\x3f\x59\x85" + "\x4d\x5c\x2a\xf3\x27\xcd\x64\xa6" + "\x2c\xf3\x5a\xbd\x2b\xa6\xfa\xb4", + .clen = 80, + } +}; + +/* 192bit */ +struct aead_testvec aes_gcm_tv_template_192[] = { + { + .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c" + "\x6d\x6a\x8f\x94\x67\x30\x83\x08" + "\xfe\xff\xe9\x92\x86\x65\x73\x1c", + .klen = 24, + .iv = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad" + "\xde\xca\xf8\x88", + .ptext = "\xd9\x31\x32\x25\xf8\x84\x06\xe5" + "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" + "\x86\xa7\xa9\x53\x15\x34\xf7\xda" + "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" + "\x1c\x3c\x0c\x95\x95\x68\x09\x53" + "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" + "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57" + "\xba\x63\x7b\x39\x1a\xaf\xd2\x55", + .plen = 64, + .ctext = "\x39\x80\xca\x0b\x3c\x00\xe8\x41" + "\xeb\x06\xfa\xc4\x87\x2a\x27\x57" + "\x85\x9e\x1c\xea\xa6\xef\xd9\x84" + "\x62\x85\x93\xb4\x0c\xa1\xe1\x9c" + "\x7d\x77\x3d\x00\xc1\x44\xc5\x25" + "\xac\x61\x9d\x18\xc8\x4a\x3f\x47" + "\x18\xe2\x44\x8b\x2f\xe3\x24\xd9" + "\xcc\xda\x27\x10\xac\xad\xe2\x56" + "\x99\x24\xa7\xc8\x58\x73\x36\xbf" + "\xb1\x18\x02\x4d\xb8\x67\x4a\x14", + .clen = 80, + } +}; + +/* 256bit */ +struct aead_testvec aes_gcm_tv_template_256[] = { + { + .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c" + "\x6d\x6a\x8f\x94\x67\x30\x83\x08" + "\xfe\xff\xe9\x92\x86\x65\x73\x1c" + "\x6d\x6a\x8f\x94\x67\x30\x83\x08", + .klen = 32, + .iv = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad" + "\xde\xca\xf8\x88", + .ptext = "\xd9\x31\x32\x25\xf8\x84\x06\xe5" + "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" + "\x86\xa7\xa9\x53\x15\x34\xf7\xda" + "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" + "\x1c\x3c\x0c\x95\x95\x68\x09\x53" + "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" + "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57" + "\xba\x63\x7b\x39", + .plen = 60, + .assoc = "\xfe\xed\xfa\xce\xde\xad\xbe\xef" + "\xfe\xed\xfa\xce\xde\xad\xbe\xef" + "\xab\xad\xda\xd2", + .alen = 20, + .ctext = "\x52\x2d\xc1\xf0\x99\x56\x7d\x07" + "\xf4\x7f\x37\xa3\x2a\x84\x42\x7d" + "\x64\x3a\x8c\xdc\xbf\xe5\xc0\xc9" + "\x75\x98\xa2\xbd\x25\x55\xd1\xaa" + "\x8c\xb0\x8e\x48\x59\x0d\xbb\x3d" + "\xa7\xb0\x8b\x10\x56\x82\x88\x38" + "\xc5\xf6\x1e\x63\x93\xba\x7a\x0a" + "\xbc\xc9\xf6\x62" + "\x76\xfc\x6e\xce\x0f\x4e\x17\x68" + "\xcd\xdf\x88\x53\xbb\x2d\x55\x1b", + .clen = 76, + } +}; + +struct aead_testvec hmac_sha256_aes_cbc_tv_temp[] = { + { +#ifdef __LITTLE_ENDIAN + .key = "\x08\x00" /* rta length */ + "\x01\x00" /* rta type */ +#else + .key = "\x00\x08" /* rta length */ + "\x00\x01" /* rta type */ +#endif + "\x00\x00\x00\x10" /* enc key length */ + "\x20\x21\x22\x23\x24\x25\x26\x27" + "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" + "\x30\x31\x32\x33\x34\x35\x36\x37" + "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" + "\xc2\x86\x69\x6d\x88\x7c\x9a\xa0" + "\x61\x1b\xbb\x3e\x20\x25\xa4\x5a", + .klen = 8 + 32 + 16, + .iv = "\x56\x2e\x17\x99\x6d\x09\x3d\x28" + "\xdd\xb3\xba\x69\x5a\x2e\x6f\x58", + .assoc = "\x56\x2e\x17\x99\x6d\x09\x3d\x28" + "\xdd\xb3\xba\x69\x5a\x2e\x6f\x58", + .alen = 16, + .ptext = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", + .plen = 32, + .ctext = "\xd2\x96\xcd\x94\xc2\xcc\xcf\x8a" + "\x3a\x86\x30\x28\xb5\xe1\xdc\x0a" + "\x75\x86\x60\x2d\x25\x3c\xff\xf9" + "\x1b\x82\x66\xbe\xa6\xd6\x1a\xb1" + "\xf5\x33\x53\xf3\x68\x85\x2a\x99" + "\x0e\x06\x58\x8f\xba\xf6\x06\xda" + "\x49\x69\x0d\x5b\xd4\x36\x06\x62" + "\x35\x5e\x54\x58\x53\x4d\xdf\xbf", + .clen = 32 + 32, + } +}; + +/* 128bit */ +struct aead_testvec sm4_ccm_tv_template_128[] = { + { + .key = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" + "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf", + .klen = 16, + .iv = "\x01\x00\x00\x00\x03\x02\x01\x00" + "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00", + .assoc = "\x00\x01\x02\x03\x04\x05\x06\x07", + .alen = 8, + .ptext = "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e", + .plen = 23, + .ctext = "\x7B\xFF\x4A\x15\xF5\x73\xCE\x82" + "\x6E\xC2\x31\x1D\xE2\x53\x02\xAC" + "\xA4\x48\xF9\xE4\xF5\x1F\x81\x70" + "\x18\xBC\xB6\x84\x01\xB8\xAE", + .clen = 31, + } +}; + +/* 128bit */ +struct aead_testvec sm4_gcm_tv_template_128[] = { + { + .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c" + "\x6d\x6a\x8f\x94\x67\x30\x83\x08", + .klen = 16, + .iv = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad" + "\xde\xca\xf8\x88", + .ptext = "\xd9\x31\x32\x25\xf8\x84\x06\xe5" + "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" + "\x86\xa7\xa9\x53\x15\x34\xf7\xda" + "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" + "\x1c\x3c\x0c\x95\x95\x68\x09\x53" + "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" + "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57" + "\xba\x63\x7b\x39\x1a\xaf\xd2\x55", + .plen = 64, + .ctext = "\xe4\x11\x0f\xf1\xc1\x41\x97\xe6" + "\x76\x21\x6a\x33\x83\x10\x41\xeb" + "\x09\x58\x00\x11\x7b\xdc\x3f\x75" + "\x1a\x49\x6e\xfc\xf2\xbb\xdf\xdb" + "\x3a\x2e\x13\xfd\xc5\xc1\x9d\x07" + "\x1a\xe5\x48\x3f\xed\xde\x98\x5d" + "\x3f\x2d\x5b\x4e\xee\x0b\xb6\xdf" + "\xe3\x63\x36\x83\x23\xf7\x5b\x80" + "\x7d\xfe\x77\xef\x71\xb1\x5e\xc9" + "\x52\x6b\x09\xab\x84\x28\x4b\x8a", + .clen = 80, + } +}; + +struct hash_testvec sm3_tv_template[] = { +/* { + .plaintext = "abc", + .psize = 3, + .digest = "\x66\xC7\xF0\xF4\x62\xEE\xED\xD9" + "\xD1\xF2\xD4\x6B\xDC\x10\xE4\xE2" + "\x41\x67\xC4\x87\x5C\xF2\xF7\xA2" + "\x29\x7D\xA0\x2B\x8F\x4B\xA8\xE0", + }*/ + { + .plaintext = "abcdefghijklmnopqrstuvwxyz", + .psize = 26, + .digest = "\xB8\x0F\xE9\x7A\x4D\xA2\x4A\xFC" + "\x27\x75\x64\xF6\x6A\x35\x9E\xF4" + "\x40\x46\x2A\xD2\x8D\xCC\x6D\x63" + "\xAD\xB2\x4D\x5C\x20\xA6\x15\x95", + } +}; + +struct hash_testvec hmac_sm3_tv_template[] = { + { + .key = "Jefe", + .ksize = 4, + .plaintext = "what do ya want for nothing?", + .psize = 28, + .digest = "\x2e\x87\xf1\xd1\x68\x62\xe6\xd9" + "\x64\xb5\x0a\x52\x00\xbf\x2b\x10" + "\xb7\x64\xfa\xa9\x68\x0a\x29\x6a" + "\x24\x05\xf2\x4b\xec\x39\xf8\x82", + }, +}; + +struct hash_testvec md5_tv_template[] = { + { + .plaintext = "abcdefghijklmnopqrstuvwxyz", + .psize = 26, + .digest = "\xc3\xfc\xd3\xd7\x61\x92\xe4\x00" + "\x7d\xfb\x49\x6c\xca\x67\xe1\x3b", + } +}; + +struct hash_testvec hmac_md5_tv_template[] = +{ + { + .key = "Jefe", + .ksize = 4, + .plaintext = "what do ya want for nothing?", + .psize = 28, + .digest = "\x75\x0C\x78\x3E\x6A\xB0\xB5\x03" + "\xEA\xA8\x6E\x31\x0A\x5D\xB7\x38" + }, +}; + +struct hash_testvec sha1_tv_template[] = { + { + .plaintext = "abc", + .psize = 3, + .digest = "\xa9\x99\x3e\x36\x47\x06\x81\x6a\xba\x3e" + "\x25\x71\x78\x50\xc2\x6c\x9c\xd0\xd8\x9d", + } +}; + +struct hash_testvec hmac_sha1_tv_template[] = { + { + .key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", + .ksize = 20, + .plaintext = "Hi There", + .psize = 8, + .digest = "\xb6\x17\x31\x86\x55\x05\x72\x64" + "\xe2\x8b\xc0\xb6\xfb\x37\x8c\x8e\xf1" + "\x46\xbe", + } +}; + +struct hash_testvec sha256_tv_template[] = { + { + .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-", + .psize = 64, + .digest = "\xb5\xfe\xad\x56\x7d\xff\xcb\xa4" + "\x2c\x32\x29\x32\x19\xbb\xfb\xfa" + "\xd6\xff\x94\xa3\x72\x91\x85\x66" + "\x3b\xa7\x87\x77\x58\xa3\x40\x3a", + } +}; + +struct hash_testvec hmac_sha256_tv_template[] = { + { + .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa", + .ksize = 32, + .plaintext = "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd", + .psize = 50, + .digest = "\xcd\xcb\x12\x20\xd1\xec\xcc\xea" + "\x91\xe5\x3a\xba\x30\x92\xf9\x62" + "\xe5\x49\xfe\x6c\xe9\xed\x7f\xdc" + "\x43\x19\x1f\xbd\xe4\x5c\x30\xb0", + } +}; + +struct hash_testvec sha224_tv_template[] = { + { + .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-", + .psize = 64, + .digest = "\xc4\xdb\x2b\x3a\x58\xc3\x99\x01" + "\x42\xfd\x10\x92\xaa\x4e\x04\x08" + "\x58\xbb\xbb\xe8\xf8\x14\xa7\x0c" + "\xef\x3b\xcb\x0e", + } +}; + +struct hash_testvec hmac_sha224_tv_template[] = { + { + .key = "Jefe", + .ksize = 4, + /* ("what do ya want for nothing?") */ + .plaintext = "\x77\x68\x61\x74\x20\x64\x6f\x20" + "\x79\x61\x20\x77\x61\x6e\x74\x20" + "\x66\x6f\x72\x20\x6e\x6f\x74\x68" + "\x69\x6e\x67\x3f", + .psize = 28, + .digest = "\xa3\x0e\x01\x09\x8b\xc6\xdb\xbf" + "\x45\x69\x0f\x3a\x7e\x9e\x6d\x0f" + "\x8b\xbe\xa2\xa3\x9e\x61\x48\x00" + "\x8f\xd0\x5e\x44", + } +}; + +struct hash_testvec sha384_tv_template[] = { + { + .plaintext = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" + "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + .psize = 112, + .digest = "\x09\x33\x0c\x33\xf7\x11\x47\xe8" + "\x3d\x19\x2f\xc7\x82\xcd\x1b\x47" + "\x53\x11\x1b\x17\x3b\x3b\x05\xd2" + "\x2f\xa0\x80\x86\xe3\xb0\xf7\x12" + "\xfc\xc7\xc7\x1a\x55\x7e\x2d\xb9" + "\x66\xc3\xe9\xfa\x91\x74\x60\x39", + } +}; + +struct hash_testvec hmac_sha384_tv_template[] = { + { + .key = "Jefe", + .ksize = 4, + .plaintext = "what do ya want for nothing?", + .psize = 28, + .digest = "\xaf\x45\xd2\xe3\x76\x48\x40\x31" + "\x61\x7f\x78\xd2\xb5\x8a\x6b\x1b" + "\x9c\x7e\xf4\x64\xf5\xa0\x1b\x47" + "\xe4\x2e\xc3\x73\x63\x22\x44\x5e" + "\x8e\x22\x40\xca\x5e\x69\xe2\xc7" + "\x8b\x32\x39\xec\xfa\xb2\x16\x49", + } +}; + +struct hash_testvec sha512_tv_template[] = { + { + .plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + .psize = 56, + .digest = "\x20\x4a\x8f\xc6\xdd\xa8\x2f\x0a" + "\x0c\xed\x7b\xeb\x8e\x08\xa4\x16" + "\x57\xc1\x6e\xf4\x68\xb2\x28\xa8" + "\x27\x9b\xe3\x31\xa7\x03\xc3\x35" + "\x96\xfd\x15\xc1\x3b\x1b\x07\xf9" + "\xaa\x1d\x3b\xea\x57\x78\x9c\xa0" + "\x31\xad\x85\xc7\xa7\x1d\xd7\x03" + "\x54\xec\x63\x12\x38\xca\x34\x45", + } +}; + +struct hash_testvec hmac_sha512_tv_template[] = { + { + .key = "Jefe", + .ksize = 4, + .plaintext = "what do ya want for nothing?", + .psize = 28, + .digest = "\x16\x4b\x7a\x7b\xfc\xf8\x19\xe2" + "\xe3\x95\xfb\xe7\x3b\x56\xe0\xa3" + "\x87\xbd\x64\x22\x2e\x83\x1f\xd6" + "\x10\x27\x0c\xd7\xea\x25\x05\x54" + "\x97\x58\xbf\x75\xc0\x5a\x99\x4a" + "\x6d\x03\x4f\x65\xf8\xf0\xe6\xfd" + "\xca\xea\xb1\xa3\x4d\x4a\x6b\x4b" + "\x63\x6e\x07\x0a\x38\xbc\xe7\x37", + } +}; + +struct hash_testvec sha512_224_tv_template[] = { + { + .plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + .psize = 56, + .digest = "\xe5\x30\x2d\x6d\x54\xbb\x24\x22" + "\x75\xd1\xe7\x62\x2d\x68\xdf\x6e" + "\xb0\x2d\xed\xd1\x3f\x56\x4c\x13" + "\xdb\xda\x21\x74", + } +}; + +struct hash_testvec hmac_sha512_224_tv_template[] = { + { + .key = "Jefe", + .ksize = 4, + .plaintext = "what do ya want for nothing?", + .psize = 28, + .digest = "\x4a\x53\x0b\x31\xa7\x9e\xbc\xce" + "\x36\x91\x65\x46\x31\x7c\x45\xf2" + "\x47\xd8\x32\x41\xdf\xb8\x18\xfd" + "\x37\x25\x4b\xde", + }, +}; + +struct hash_testvec sha512_256_tv_template[] = { + { + .plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + .psize = 56, + .digest = "\xbd\xe8\xe1\xf9\xf1\x9b\xb9\xfd" + "\x34\x06\xc9\x0e\xc6\xbc\x47\xbd" + "\x36\xd8\xad\xa9\xf1\x18\x80\xdb" + "\xc8\xa2\x2a\x70\x78\xb6\xa4\x61", + } +}; + +struct hash_testvec hmac_sha512_256_tv_template[] = { + { + .key = "Jefe", + .ksize = 4, + .plaintext = "what do ya want for nothing?", + .psize = 28, + .digest = "\x6d\xf7\xb2\x46\x30\xd5\xcc\xb2" + "\xee\x33\x54\x07\x08\x1a\x87\x18" + "\x8c\x22\x14\x89\x76\x8f\xa2\x02" + "\x05\x13\xb2\xd5\x93\x35\x94\x56", + }, +}; + +struct hash_testvec long_hash_tv_template[] = { + { +/* +md5 (stdin)= A89D2C8730E3BB304EDA507035928B86 +sha1 (stdin)= D2E8068B6B648B8793B7DA8D575AE57FA208FD66 +sha256 (stdin)= 1CEA48E3960EE3675BD5663C5F423325110000D26DE11C9B11B0293386C030C0 +sha224 (stdin)= ADBEC39512DCA87CCFD155BB635F519E7B46796C722CC650233BF106 +sha384 (stdin)= 18AB6F0018884BBF7CE7015168B691FEC8A2E15892689E4D632099162 + 54A2A6B527D2DFC0144D5CEECC339857B968308 + */ + .key = "Huawei12", + .ksize = 8, + .plaintext = "\x09\x9f\x13\xaa\x41\x68\x4c\xe3" + "\x5a\x11\x85\xac\xb3\x27\xbe\x55" + "\xec\x60\xf7\x8d\x02\x99\x30\xc7" + "\x4b\xd2\x69\x23\x74\x0b\xa2\x16" + "\xad\x44\xdb\x4f\xe6\x7d\x14\x88" + "\x2f\xb6\x2a\xc1\x58\xef\x63\xfa" + "\x71\x05\x9c\x33\xca\x3e\xd5\x6c" + "\x23\x77\x0e\xa5\x19\xb0\x47\xde" + "\x52\x65\x80\x17\x8b\x22\xb9\x2d" + "\xc4\x5b\xf2\x66\xfd\x94\x08\x9f" + "\x36\xcd\x41\xd8\x6f\x06\x7a\x11" + "\xa8\x1c\xb3\x4a\xe1\x55\xec\x83" + "\x1a\x8e\x25\xbc\x70\xc7\x5e\xf5" + "\x69\x00\x97\x0b\xa2\x39\xd0\x44" + "\xdb\x72\x09\x7d\x14\xab\x1f\xb6" + "\x4d\x87\x58\xef\x86\x1d\x91\x28" + "\xbf\x33\xca\x61\xf8\x6c\x03\x9a" + "\x0e\xa5\x3c\xd3\x49\xde\x75\x0c" + "\x80\x17\xae\x22\xb9\x50\xe7\x5b" + "\xf2\x90\x20\x67\x2b\xc2\x36\xcd" + "\x64\xfb\x6f\x06\x9d\x11\xa8\x3f" + "\xd6\x4a\xe1\x78\x0f\x83\x1a\xb1" + "\x25\xbc\x53\xea\x5e\xf5\x8c\x00" + "\x97\x45\xc5\x39\xd0\x67\xfe\x72" + "\x09\xa0\x14\xab\x02\xd9\x4d\xe4" + "\x0e\xa5\x3c\xd3\x49\xde\x75\x0c" + "\xed\x61\xf8\x8f\x03\x9a\x31\xc8" + "\x3c\xd3\x67\x01\x75\x0c\xa3\x17" + "\xae\x45\xdc\x50\xe7\x7e\x15\x89" + "\x20\xb7\x2b\xc2\x59\xf0\x64\xfb" + "\x92\x06\x9d\x33\xca\x3e\xd5\x6c" + "\x04\x78\x0f\xa6\x1a\xb1\x48\xdf" + "\x53\xea\x81\x18\x8c\x23\xba\x2e" + "\xc5\x5c\xf3\x67\xfe\x95\x09\xa0" + "\x37\xce\x42\xd9\x70\x07\x7b\x12" + "\xa9\x1d\xb4\x4b\xe2\x56\xed\x84" + "\x1b\x8f\x26\xbd\x31\xc8\x5f\xf6" + "\x6a\x01\x98\x0c\xa3\x3a\xd1\x45" + "\xdc\x73\x0a\x7e\x15\xac\x20\xb7" + "\xd6\x4a\xe1\x78\x0f\x83\x1a\xb1" + "\xc0\x34\xcb\x62\xf9\x6d\x04\x9b" + "\x0f\xa6\x3d\xd4\x48\xdf\x76\x0d" + "\x81\x18\xaf\x23\xba\x51\xe8\x5c" + "\xf3\x8a\x21\x95\x2c\xc3\x37\xce" + "\x65\xfc\x70\x07\x9e\x12\xa9\x40" + "\xd7\x4b\xe2\x79\x10\x84\x1b\xb2" + "\x26\xbd\x54\xbd\x31\xc8\x5f\xf6" + "\x98\x2f\xc6\x3a\xd1\x68\xff\x73" + "\x0a\xa1\x15\xac\x43\xda\x4e\xe5" + "\x7c\x13\x87\x1e\xb5\x29\xc0\x57" + "\xee\x62\xf9\x90\x04\x9b\x32\xc9" + "\x3d\xd4\x6b\x02\x76\x0d\xa4\x18" + "\xaf\x46\xdd\x51\xe8\x7f\x16\x8a" + "\x21\xb8\x2c\xc3\x5a\xf1\x65\xfc" + "\x93\x07\x9e\x35\xcc\x40\xd7\x6e" + "\x05\x79\x10\xa7\x1b\xb2\x49\xe0" + "\x20\xb7\x2b\xc2\x59\xf0\x64\xfb" + "\x92\x06\x9d\x33\xca\x3e\xd5\x6c" + "\x04\x78\x0f\xa6\x1a\xb1\x48\xdf" + "\xaa\x1e\xb5\x4c\xe3\x57\xee\x85" + "\x1c\x90\x27\xbe\x32\xc9\x60\xf7" + "\x6b\x02\x99\x0d\xa4\x3b\xd2\x46" + "\xdd\x74\x0b\x7f\x16\xad\x21\xb8" + "\xd7\x4b\xe2\x79\x10\x84\x1b\xb2" + "\x26\xbd\x54\xbd\x31\xc8\x5f\xf6" + "\x10\xa7\x3e\xd5\x49\xe0\x77\x0e" + "\x82\x19\xb0\x24\xbb\x52\xe9\x5d" + "\xf4\x8b\x22\x96\x2d\xc4\x38\xcf" + "\x66\xfd\x71\x98\x9f\x13\xaa\x41" + "\xd8\x4c\xe3\x7a\x11\x85\x1c\xb3" + "\x27\xbe\x55\xec\x60\xf7\x8e\x02" + "\x99\x30\xc7\x3b\xd2\x69\x00\x74" + "\x0b\xa2\x16\xad\x44\xdb\x4f\xe6" + "\x7d\x14\x88\x1f\xb6\x2a\xc1\x58" + "\xef\x78\xfa\x91\x05\x9c\x33\xca" + "\x3e\xd5\x6c\x03\x77\x0e\xa5\x19" + "\xb0\x47\xde\x52\xe9\x80\x17\x8b" + "\x22\xb9\x2d\xc4\x5b\xf2\x66\xfd" + "\x94\x08\x9f\x36\xcd\x41\xd8\x6f" + "\x06\x7a\x11\xa8\x56\xb3\x4a\xe1" + "\x55\xec\x83\x1a\x8e\x25\xbc\x30" + "\xc7\x5e\xf5\x69\x00\x97\x0b\xa2" + "\x05\x79\x10\xa7\x1b\x09\x7d\x14" + "\xab\x1f\xb6\x4d\xe4\x58\xef\x86" + "\x1d\x91\x28\xbf\x33\xca\x61\xf8" + "\x6c\x03\x9a\x0e\xa5\x3c\xd3\x47" + "\xde\x75\x0c\x80\x17\xae\x22\xb9" + "\x50\xe7\x5b\xf2\x89\x20\x94\x2b" + "\xc2\x36\xcd\x64\xfb\x6f\x06\x9d" + "\x11\xa8\x3f\xd6\x4a\xe1\x78\x0f" + "\x83\x1a\xb1\x25\xbc\x53\xea\x5e" + "\xf5\x8c\x00\x97\x2e\xc5\x39\xd0" + "\x67\xfe\x72\x09\xa0\x14\xab\x42" + "\x0d\xa4\x18\xaf\x46\xdd\x51\xe8" + "\x28\xbf\x56\xed\x61\xf8\x8f\x03" + "\x9a\x31\xc8\x3c\xd3\x6a\x01\x75" + "\x0c\xec\x83\x1a\x8e\x25\xbc\x30" + "\x7e\x15\x89\x20\xb7\x2b\xc2\x59" + "\xf0\x64\xfb\x92\x06\x9d\x34\xcb" + "\x3f\xd6\x6d\x04\x78\x0f\xa6\x1a" + "\xb1\x48\xff\x53\xea\x81\x18\x8c" + "\x23\xba\x2e\xc5\x5c\xf3\x67\xfe" + "\x95\x09\x34\x37\xce\x42\xd9\x70" + "\x07\x7b\x12\xa9\x1d\xb4\x4b\xe2" + "\x56\xed\x84\x1b\x8f\x26\xbd\x31" + "\x45\x5f\xf6\x6a\x01\x98\x0c\xa3" + "\x3a\xd1\x45\xdc\x73\x0a\x7e\x15" + "\xac\x20\xb7\x4e\xe5\x59\xf0\x87" + "\x1e\x92\x29\xc0\x25\xcb\x62\xf9" + "\x6d\x04\x9b\x0f\xa6\x3d\xd4\x48" + "\xdf\x76\x0d\x81\x18\xaf\x23\xba" + "\x51\xe8\x5c\x1a\x8e\x25\xbc\x30" + "\xc3\x37\xce\x65\xfc\x70\x07\x9e" + "\x12\xa9\x40\xd7\x4b\xe2\x79\x10" + "\x84\x1b\xb2\x26\xbd\x54\xeb\x5f" + "\xf6\x8d\x01\x98\x2f\xc6\x3a\xd1" + "\x68\xff\x73\x0a\xa1\x15\xac\x43" + "\xda\x4e\xe5\x7c\x13\x87\x1e\xb5" + "\x29\xc0\x57\xee\x62\xf9\x90\x04" + "\x9b\x32\xc9\x3d\xd4\x6b\x02\x76" + "\x0d\xa4\x18\xaf\x46\xdd\x51\xe8" + "\x7f\x16\x8a\x21\xb8\x2c\xc3\x5a" + "\xf1\x65\xfc\x93\x07\x9e\x35\xcc" + "\xd9\x4d\xe4\x7b\x12\x86\x1d\xb4" + "\xb2\x49\xe0\x54\xeb\x82\x19\x8d" + "\x24\xbb\x2f\xc6\x5d\xf4\x68\xff" + "\x96\x0a\x45\x38\xcf\x43\xda\x71" + "\x08\x7c\x13\xaa\x1e\x76\x4c", + .psize = 1023, + } +}; + +struct hash_testvec hmac_abnormal1024_tv_template[] = { + { + .key = "\xab\xfc\x93\x07\x9e\xaa\xbc\x0f" + "\x68\xff\x73\x0a\xa1\x15\xac\x43" + "\xda\x4e\xe5\x7c\x13\x87\x1e\xb5" + "\x29\xc0\x57\xee\x62\xf9\x90\x04" + "\x9b\x32\xc9\x3d\xd4\x6b\x02\x76" + "\x0d\xa4\x18\xaf\x46\xdd\x51\xe8" + "\x7f\x16\x8a\x21\xb8\x2c\xc3\x5a" + "\xf1\x65\xfc\x93\x07\x9e\x35\xcc" + "\x07\xd0\x15\x89\x19\x01\x01\xa2" + "\x54\x18\x5e\x6a\x16\x93\x6e\x56" + "\x43\x19\x1f\xbd\xe4\x5c\x30\xb0" + "\x67\x17\x21\xc7\x6e\x8a\xd5\x49" + "\xac\x20\xb7\x4e\xe5\x59\xf0\x87" + "\x97\x9b\x0f\x15\x56\x6a\x8f\x6d" + "\x21\x2f\x2c\x02\xa4\xe0\x78\x65" + "\xbc\x53\xea\x5e\xf5\x8c\x00\xa3" + "\xab\xca\x0f\x0e", + .ksize = 132, + .plaintext = "Test Using Texts" + "r Than BlockSize" + "e aKey Hash Keys" + " First", + .psize = 54, + } +}; + +struct hash_testvec hmac_abnormal512_tv_template[] = { + { + .key = "\x07\xd0\x15\x89\x19\x01\x01\xa2" + "\x54\x18\x5e\x6a\x16\x93\x6e\x56" + "\x43\x19\x1f\xbd\xe4\x5c\x30\xb0" + "\x67\x17\x21\xc7\x6e\x8a\xd5\x49" + "\xac\x20\xb7\x4e\xe5\x59\xf0\x87" + "\x97\x9b\x0f\x15\x56\x6a\x8f\x6d" + "\x21\x2f\x2c\x02\xa4\xe0\x78\x65" + "\xbc\x53\xea\x5e\xf5\x8c\x00\xa3" + "\xab\xca\x0f\x68", + .ksize = 68, + .plaintext = "Test Using Texts" + "r Than BlockSize" + "e aKey Hash Keys" + " First", + .psize = 54, + } +}; + + +#endif diff --git a/uadk/v1/test/hisi_trng_test/Makefile.am b/uadk/v1/test/hisi_trng_test/Makefile.am new file mode 100644 index 0000000..fe75651 --- /dev/null +++ b/uadk/v1/test/hisi_trng_test/Makefile.am @@ -0,0 +1,20 @@ +AM_CFLAGS=-Wall -Werror -O0 -fno-strict-aliasing -I$(top_srcdir)/include -I$(srcdir) -pthread + +if WITH_OPENSSL_DIR +bin_PROGRAMS=test_hisi_trngu test_hisi_trngk test_hisi_trngp + +test_hisi_trngu_SOURCES=test_hisi_trngu.c +test_hisi_trngk_SOURCES=test_hisi_trngk.c +test_hisi_trngp_SOURCES=test_hisi_trngp.c + +if WD_STATIC_DRV +test_hisi_trngu_LDADD=../../../.libs/libwd.la +test_hisi_trngk_LDADD=../../../.libs/libwd.la +test_hisi_trngp_LDADD=../../../.libs/libwd.la +else +test_hisi_trngu_LDADD=../../../.libs/libwd.so +test_hisi_trngk_LDADD=../../../.libs/libwd.so +test_hisi_trngp_LDADD=../../../.libs/libwd.so +endif + +endif diff --git a/uadk/v1/test/hisi_trng_test/test_hisi_trngk.c b/uadk/v1/test/hisi_trng_test/test_hisi_trngk.c new file mode 100644 index 0000000..ae719e5 --- /dev/null +++ b/uadk/v1/test/hisi_trng_test/test_hisi_trngk.c @@ -0,0 +1,155 @@ +#include +#include +#include +#include +#define __USE_GNU +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +struct thread_info +{ + pthread_t thread_id; + unsigned int size; + unsigned int num; + int addr; + +}; + +void *trng_thread(void *args) +{ + + int fd = -1; + int fd_w = -1; + int ret; + unsigned int input; + struct thread_info *tinfo = args; + input = tinfo->size; + unsigned int *data = (unsigned int*)malloc(sizeof(unsigned int) * input); + + if(!data) + return NULL; + + if (tinfo->addr == 0){ + +// printf("Now try to get %d bytes random number from /dev/hwrng.\n", input * 4); + fd = open ("/dev/hwrng", O_RDONLY); + } + else if (tinfo->addr == 1){ +// printf("Now try to get %d bytes random number from /dev/random.\n", input * 4); + fd = open ("/dev/random", O_RDONLY); + } + + if (fd <0 ) { + printf("can not open\n"); + return NULL; + } + + fd_w = open ("/root/trng_file", O_WRONLY|O_CREAT|O_APPEND,0777); + if (fd_w <0 ) { + printf("can not open trng_file\n"); + return NULL; + } + memset(data, 0, sizeof(int) * input); + ret = read(fd, data, input); + if (ret < 0) { + printf("read error %d\n", ret); + return NULL; + } + ret =write(fd_w,data,input); + if (ret < 0) { + printf("write error %d\n", ret); + return NULL; + } + + close(fd); + close(fd_w); + + return NULL; +} + + +void trng_test(int addr,int num,unsigned int si,int thread_num) +{ + + int i; + void *ret = NULL; + struct thread_info *tinfo; + tinfo = calloc(thread_num, sizeof(struct thread_info)); + + if (tinfo == NULL) + { + printf("calloc fail...\n"); + return; + } + + for (i = 0; i +#include +#include +#include +#include +#include +#include +#include +#include + +static int input; +static int thread_num; +struct thread_info +{ + pthread_t thread_id; + unsigned int size; + int num; +}; + +void *trng_thread(void *args) +{ + int j; + int fd = -1; + int data; + int ret; + struct thread_info *tinfo = args; + int si; + int num; + int size; + int fd_w = -1; + si = tinfo->size; + num = tinfo->num; + size=si/num; + printf("Now try to get bytes random number from /dev/random.\n"); + fd = open("/dev/random", O_RDONLY); + if (fd <0 ) { + printf("can not open\n"); + return NULL; + } + for (j = 0; j< size; j++) { + ret = read(fd, &data, 1); + if (ret < 0) { + printf("read error %d\n", ret); + return NULL; + } +// else if (ret < 1) +// goto rd_ag; +// if (!data) { +// printf("read data error!\n"); +// return data; +// } + printf("the read num:%x\n",data); + } + fd_w = open ("/root/trng_file", O_RDWR | O_CREAT |O_APPEND , 0777); + if (fd_w <0 ) { + printf("can not open trng_file\n"); + return NULL; + } + ret = write(fd_w,&data,size); + if (ret < 0) { + printf("write error %d\n", ret); + return NULL; + } + close(fd); + close(fd_w); + return NULL; +} + +void trng_test(int input,int thread_num) +{ + int i; + void *ret = NULL; + struct thread_info *tinfo; + tinfo = calloc(thread_num, sizeof(struct thread_info)); + if(tinfo == NULL) + { + printf("calloc fail...\n"); + return; + } + for(i = 0; i 128) { + printf("Invalid threads num:%d!\n",thread_num); + printf("Now set threads num as 2\n"); + thread_num = 2; + } + gettimeofday(&start_tval, NULL); + trng_test(input,thread_num); + gettimeofday(&end_tval, NULL); + time = (float)((end_tval.tv_sec - start_tval.tv_sec) * 1000000 + + (end_tval.tv_usec - start_tval.tv_usec)); + speed = input/(time / 1000000); + printf("read random speed: %0.0f time\n", time); + printf("read random speed: %0.0f bytes/s\n", speed); + close(fd_f); + return 0; +} diff --git a/uadk/v1/test/hisi_trng_test/test_hisi_trngu.c b/uadk/v1/test/hisi_trng_test/test_hisi_trngu.c new file mode 100644 index 0000000..86aa8a9 --- /dev/null +++ b/uadk/v1/test/hisi_trng_test/test_hisi_trngu.c @@ -0,0 +1,624 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#include +#include +#include +#define __USE_GNU +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../../wd.h" +#include "../../wd_rng.h" + +#define RNG_TST_PRT printf +#define BN_ULONG unsigned long +#define TEST_MAX_THRD 128 +#define MAX_TRY_TIMES 10000 +#define LOG_INTVL_NUM 8 +#define TEST_CNT 10 + +static int q_num = 1; +static int ctx_num_per_q = 1; + +enum alg_op_type { + TRNG_GEN, + TRNG_AGEN, +}; + +struct trng_user_tag_info { + int pid; + int thread_id; +}; + +struct test_trng_pthread_dt { + int cpu_id; + int thread_num; + void *q; +}; + +static struct test_trng_pthread_dt test_thrds_data[TEST_MAX_THRD]; +static pthread_t system_test_thrds[TEST_MAX_THRD]; +static unsigned int g_input; + + +static inline int _get_cpu_id(int thr, __u64 core_mask) +{ + __u64 i; + int cnt = 0; + + for (i = 1; i < 64; i++) { + if (core_mask & (0x1ull << i)) { + if (thr == cnt) + return i; + cnt++; + } + } + + return 0; +} + +static inline int _get_one_bits(__u64 val) +{ + int count = 0; + + while (val) { + if (val % 2 == 1) + count++; + val = val / 2; + } + + return count; +} + +void *_trng_sys_test_thread(void *data) +{ + int ret, cpuid, i = 0; + struct test_trng_pthread_dt *pdata = data; + struct wcrypto_rng_ctx_setup setup; + struct wcrypto_rng_op_data opdata; + int pid = getpid(); + int thread_id = (int)syscall(__NR_gettid); + struct wd_queue *q; + int *out_data; + void *ctx = NULL; + void *tag = NULL; + + cpu_set_t mask; + CPU_ZERO(&mask); + cpuid = pdata->cpu_id; + q = pdata->q; + CPU_SET(cpuid, &mask); + + if (cpuid) { + ret = pthread_setaffinity_np(pthread_self(), + sizeof(mask), &mask); + if (ret < 0) { + RNG_TST_PRT("Proc-%d, thrd-%d:set affinity fail!\n", + pid, thread_id); + return NULL; + } + RNG_TST_PRT("Proc-%d, thrd-%d bind to cpu-%d!\n", + pid, thread_id, cpuid); + } + + memset(&setup, 0, sizeof(setup)); + memset(&opdata, 0, sizeof(opdata)); + ctx = wcrypto_create_rng_ctx(q, &setup); + if (!ctx) { + RNG_TST_PRT("Proc-%d, %d-TD:create %s ctx fail!\n", + pid, thread_id, q->capa.alg); + ret = -EINVAL; + goto fail_release; + } + + out_data = malloc(g_input); + if(!out_data) { + RNG_TST_PRT("malloc out_data memory fail!\n"); + } + RNG_TST_PRT("request queue fail5!\n"); + + while (1) { + opdata.in_bytes = g_input; + opdata.out = out_data; + ret = wcrypto_do_rng(ctx, &opdata, tag); + if (ret < 0) { + RNG_TST_PRT("Proc-%d, T-%d:trng %d fail!\n", pid, thread_id, i); + goto fail_release; + } + RNG_TST_PRT("the read data size %d!\n", opdata.out_bytes); + i++; + } +fail_release: + if (opdata.out) + free(opdata.out); + if (ctx) + wcrypto_del_rng_ctx(ctx); + return NULL; +} + + +static int trng_sys_test(int thread_num, __u64 lcore_mask, + __u64 hcore_mask) +{ + int i, ret, cnt = 0, j; + struct wd_queue *q; + int h_cpuid, qidx; + + q = malloc(q_num * sizeof(struct wd_queue)); + if (!q) { + RNG_TST_PRT("malloc q memory fail!\n"); + return -ENOMEM; + } + memset(q, 0, q_num * sizeof(struct wd_queue)); + + for (j = 0; j < q_num; j++) { + q[j].capa.alg = "trng"; + ret = wd_request_queue(&q[j]); + if (ret) { + RNG_TST_PRT("request queue %d fail!\n", j); + return ret; + } + } + RNG_TST_PRT("request queue fail!\n"); + if (_get_one_bits(lcore_mask) > 0) + cnt = _get_one_bits(lcore_mask); + else if (_get_one_bits(lcore_mask) == 0 && + _get_one_bits(hcore_mask) == 0) + cnt = thread_num; + + for (i = 0; i < cnt; i++) { + qidx = i / ctx_num_per_q; + test_thrds_data[i].q = &q[qidx]; + test_thrds_data[i].thread_num = thread_num; + test_thrds_data[i].cpu_id = _get_cpu_id(i, lcore_mask); + ret = pthread_create(&system_test_thrds[i], NULL, + _trng_sys_test_thread, &test_thrds_data[i]); + if (ret) { + RNG_TST_PRT("Create %dth thread fail!\n", i); + return ret; + } + } + RNG_TST_PRT("request queue fail2!\n"); + for (i = 0; i < thread_num - cnt; i++) { + h_cpuid = _get_cpu_id(i, hcore_mask); + if (h_cpuid > 0) + h_cpuid += 64; + + qidx = (i + cnt) / ctx_num_per_q; + test_thrds_data[i + cnt].q = &q[qidx]; + test_thrds_data[i + cnt].thread_num = thread_num; + test_thrds_data[i + cnt].cpu_id = h_cpuid; + ret = pthread_create(&system_test_thrds[i + cnt], NULL, + _trng_sys_test_thread, &test_thrds_data[i + cnt]); + if (ret) { + RNG_TST_PRT("Create %dth thread fail!\n", i); + return ret; + } + } + RNG_TST_PRT("request queue fail3!\n"); + for (i = 0; i < thread_num; i++) { + ret = pthread_join(system_test_thrds[i], NULL); + if (ret) { + RNG_TST_PRT("Join %dth thread fail!\n", i); + return ret; + } + } + free(q); + return 0; +} + + +static void _trng_cb(const void *message, void *tag) +{ + const struct wcrypto_rng_msg *msg = message; + struct trng_user_tag_info* pSwData = (struct trng_user_tag_info*)tag; + struct wcrypto_rng_op_data opdata; + int pid, threadId; + + if (NULL == pSwData) { + RNG_TST_PRT("pSwData NULL!\n"); + return; + } + memset(&opdata, 0, sizeof(opdata)); + + opdata.out = (void *)msg->out; + opdata.out_bytes = msg->out_bytes; + pid = pSwData->pid; + threadId = pSwData->thread_id; + RNG_TST_PRT("Proc-%d, %d-TD trng\n", pid, threadId); + RNG_TST_PRT("the random number size :%d\n", opdata.out_bytes); + + if (opdata.out) + free(opdata.out); + + if (pSwData) + free(pSwData); +} + +static void *_trng_asys_test_thread(void *data) +{ + int ret, cpuid; + struct test_trng_pthread_dt *pdata = data; + struct wd_queue *q = NULL; + cpu_set_t mask; + struct wcrypto_rng_ctx_setup setup; + struct wcrypto_rng_ctx *ctx = NULL; + struct trng_user_tag_info *tag = NULL; + struct wcrypto_rng_op_data opdata; + int pid = getpid(); + int thread_id = (int)syscall(__NR_gettid); + int *out_data; + int i = 0; + + CPU_ZERO(&mask); + cpuid = pdata->cpu_id; + q = (struct wd_queue *)pdata->q; + CPU_SET(cpuid, &mask); + + if (!q) { + RNG_TST_PRT("q null!\n"); + return NULL; + } + if (cpuid) { + ret = pthread_setaffinity_np(pthread_self(), + sizeof(mask), &mask); + if (ret < 0) { + RNG_TST_PRT("Proc-%d, thrd-%d:set affinity fail!\n", + pid, thread_id); + return NULL; + } + RNG_TST_PRT("Proc-%d, thrd-%d bind to cpu-%d!\n", + pid, thread_id, cpuid); + } + + q->capa.alg = "trng"; + memset(&setup, 0, sizeof(setup)); + memset(&opdata, 0, sizeof(opdata)); + setup.cb = _trng_cb; + ctx = wcrypto_create_rng_ctx(q, &setup); + if (!ctx) { + RNG_TST_PRT("Proc-%d, %d-TD:create %s ctx fail!\n", + pid, thread_id, q->capa.alg); + goto fail_release; + } + + while(1) { + tag = malloc(sizeof(struct trng_user_tag_info)); + if (!tag) { + RNG_TST_PRT("malloc tag fail!\n"); + goto fail_release; + } + + tag->pid = pid; + tag->thread_id = thread_id; + + out_data = malloc(g_input); + if(!out_data) { + RNG_TST_PRT("malloc fail\n"); + return 0; + } + + opdata.in_bytes = g_input; + opdata.out = out_data; + try_again: + ret = wcrypto_do_rng(ctx, &opdata, tag); + if (ret == -WD_EBUSY) { + usleep(100); + goto try_again; + } else if(ret) { + RNG_TST_PRT("Proc-%d, T-%d:trng %d fail!\n", pid, thread_id, i); + goto fail_release; + } + i++; + } +fail_release: + wcrypto_del_rng_ctx(ctx); + return NULL; +} + +static void* _trng_async_poll_test_thread(void *data) +{ + struct test_trng_pthread_dt *pdata = data; + struct wd_queue *q = pdata->q; + int ret, cpuid; + int pid = getpid(); + cpu_set_t mask; + int thread_id = (int)syscall(__NR_gettid); + + CPU_ZERO(&mask); + cpuid = pdata->cpu_id; + CPU_SET(cpuid, &mask); + if (cpuid) { + ret = pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask); + if (ret < 0) { + RNG_TST_PRT("Proc-%d, thrd-%d:set affinity fail!\n", + pid, thread_id); + return NULL; + } + RNG_TST_PRT("Proc-%d, poll thrd-%d bind to cpu-%d!\n", + pid, thread_id, cpuid); + } + + while (1) { + ret = wcrypto_rng_poll(q, 1); + if (ret < 0) { + break; + } + } + + return NULL; +} + +static int trng_asys_test(int thread_num, __u64 lcore_mask, __u64 hcore_mask) +{ + int i, ret, cnt = 0; + struct wd_queue q; + int h_cpuid; + + memset(&q, 0, sizeof(q)); + + q.capa.alg = "trng"; + ret = wd_request_queue(&q); + if (ret) { + RNG_TST_PRT("request queue fail!\n"); + return ret; + } + + if (_get_one_bits(lcore_mask) > 0) + cnt = _get_one_bits(lcore_mask); + else if (_get_one_bits(lcore_mask) == 0 && + _get_one_bits(hcore_mask) == 0) + cnt = thread_num; + + test_thrds_data[0].q= &q; + test_thrds_data[0].thread_num = 1; + test_thrds_data[0].cpu_id = _get_cpu_id(0, lcore_mask); + ret = pthread_create(&system_test_thrds[0], NULL, + _trng_async_poll_test_thread, &test_thrds_data[0]); + if (ret) { + RNG_TST_PRT("Create poll thread fail!\n"); + return ret; + } + + for (i = 1; i <= cnt; i++) { + test_thrds_data[i].q = &q; + test_thrds_data[i].thread_num = thread_num; + test_thrds_data[i].cpu_id = _get_cpu_id(i, lcore_mask); + ret = pthread_create(&system_test_thrds[i], NULL, + _trng_asys_test_thread, &test_thrds_data[i]); + if (ret) { + RNG_TST_PRT("Create %dth thread fail!\n", i); + return ret; + } + } + + for (i = 1; i <= thread_num - cnt; i++) { + h_cpuid = _get_cpu_id(i, hcore_mask); + if (h_cpuid > 0) + h_cpuid += 64; + test_thrds_data[i + cnt].q = &q; + test_thrds_data[i + cnt].thread_num = thread_num; + test_thrds_data[i + cnt].cpu_id = h_cpuid; + ret = pthread_create(&system_test_thrds[i + cnt], NULL, + _trng_asys_test_thread, &test_thrds_data[i + cnt]); + if (ret) { + RNG_TST_PRT("Create %dth thread fail!\n", i); + return ret; + } + } + + for (i = 0; i < thread_num; i++) { + ret = pthread_join(system_test_thrds[i], NULL); + if (ret) { + RNG_TST_PRT("Join %dth thread fail!\n", i); + return ret; + } + } + + wd_release_queue(&q); + return 0; + +} +int main(int argc, char *argv[]) +{ + struct wcrypto_rng_ctx *ctx; + struct wcrypto_rng_op_data opdata; + struct wcrypto_rng_ctx_setup setup; + enum alg_op_type alg_op_type = TRNG_GEN; + int thread_num, bits; + __u64 core_mask[2]; + struct wd_queue q; + void *tag = NULL; + int *data; + int ret; + int fd = -1; + int fd_w = -1; + if (!argv[1]) { + RNG_TST_PRT("pls printf the size of the random data!\n"); + return -WD_EINVAL; + } + g_input = (unsigned int)strtoul(argv[1], NULL, 10); + printf("g_input:%d\n",g_input); + //if (g_input <= 0){ + // printf("input error!\n"); + // return -WD_EINVAL; + //} + if (argv[2]) { + if(!strcmp(argv[2], "-system-gen")) { + alg_op_type = TRNG_GEN; + RNG_TST_PRT("Now doing system random number gen test!\n"); + } else if(!strcmp(argv[2], "-system-agen")) { + alg_op_type = TRNG_AGEN; + RNG_TST_PRT("Now doing system random number agen test!\n"); + } + + thread_num = strtoul((char *)argv[3], NULL, 10); + if (thread_num <= 0 || thread_num > TEST_MAX_THRD) { + RNG_TST_PRT("Invalid threads num:%d!\n", + thread_num); + RNG_TST_PRT("Now set threads num as 2\n"); + thread_num = 2; + } + + if (strcmp(argv[4], "-c")) { + RNG_TST_PRT("./test_hisi_trng --help get details\n"); + return -EINVAL; + } + if (argv[5][0] != '0' || argv[5][1] != 'x') { + RNG_TST_PRT("Err:coremask should be hex!\n"); + return -EINVAL; + } + + if (strlen(argv[5]) > 34) { + RNG_TST_PRT("Warning: coremask is cut!\n"); + argv[5][34] = 0; + } + + if (strlen(argv[5]) <= 18) { + core_mask[0] = strtoull(argv[5], NULL, 16); + if (core_mask[0] & 0x1) { + RNG_TST_PRT("Warn:cannot bind to core 0,\n"); + RNG_TST_PRT("now run without binding\n"); + core_mask[0] = 0x0; /* no binding */ + } + core_mask[1] = 0; + } else { + int offset = 0; + char *temp; + + offset = strlen(argv[5]) - 16; + core_mask[0] = strtoull(&argv[5][offset], NULL, 16); + if (core_mask[0] & 0x1) { + RNG_TST_PRT("Warn:cannot bind to core 0,\n"); + RNG_TST_PRT("now run without binding\n"); + core_mask[0] = 0x0; /* no binding */ + } + temp = malloc(64); + strcpy(temp, argv[5]); + temp[offset] = 0; + core_mask[1] = strtoull(temp, NULL, 16); + free(temp); + } + + bits = _get_one_bits(core_mask[0]); + bits += _get_one_bits(core_mask[1]); + if (thread_num > bits) { + RNG_TST_PRT("Coremask not covers all thrds,\n"); + RNG_TST_PRT("Bind first %d thrds!\n", bits); + } else if (thread_num < bits) { + RNG_TST_PRT("Coremask overflow,\n"); + RNG_TST_PRT("Just try to bind all thrds!\n"); + } + + if (argv[6]) { + ctx_num_per_q = strtoul(argv[6], NULL, 10); + if (ctx_num_per_q <= 0) { + RNG_TST_PRT("Invalid ctx num per queue:%s!\n", + argv[6]); + RNG_TST_PRT("Now ctx num per queue is set as 1!\n"); + ctx_num_per_q = 1; + } + } else { + RNG_TST_PRT("Now ctx num per queue is set as 1!\n"); + ctx_num_per_q = 1; + } + + q_num = (thread_num - 1) / ctx_num_per_q + 1; + + RNG_TST_PRT("Proc-%d: starts %d threads bind to %s\n", + getpid(), thread_num, argv[5]); + RNG_TST_PRT(" lcoremask=0x%llx, hcoremask=0x%llx\n", + core_mask[0], core_mask[1]); + if(alg_op_type == TRNG_GEN) + return trng_sys_test(thread_num, core_mask[0], + core_mask[1]); + + return trng_asys_test(thread_num, core_mask[0], + core_mask[1]); + } + + RNG_TST_PRT("Now try to get %d bytes random number.\n", g_input); + + data = malloc(g_input); + if (!data) { + RNG_TST_PRT("malloc data failed.\n"); + return -1; + } + + memset((void *)&q, 0, sizeof(q)); + memset(&setup, 0, sizeof(setup)); + memset(&opdata, 0, sizeof(opdata)); + + q.capa.alg = "trng"; + ret = wd_request_queue(&q); + if (ret) { + RNG_TST_PRT("request queue fail!\n"); + return ret; + } + ctx = wcrypto_create_rng_ctx(&q, &setup); + if (!ctx) { + ret = -ENOMEM; + RNG_TST_PRT("create trng ctx fail!\n"); + goto release_q; + } + + opdata.in_bytes = g_input; + opdata.out = data; + ret = wcrypto_do_rng(ctx, &opdata, tag); + if (ret != 1) { + RNG_TST_PRT("a wd_do_trng fail!\n"); + goto del_ctx; + } + + RNG_TST_PRT("random_data size= %d.\n", opdata.out_bytes); + fd_w = open ("/root/trng_file", O_RDWR|O_CREAT|O_TRUNC,0777); + if (fd_w <0 ) { + printf("can not open trng_file\n"); + return fd_w; + } + /*fd = open ("/dev/random", O_RDONLY); + if (fd <0 ) { + printf("can not open\n"); + return fd; + }*/ + /*ret = read(fd, data, g_input); + if (ret < 0) { + printf("read error %d\n", ret); + return ret; + }*/ + ret = write(fd_w,opdata.out,opdata.out_bytes); + if (ret < 0) { + printf("write error %d\n", ret); + return ret; + } + close(fd); + close(fd_w); +del_ctx: + wcrypto_del_rng_ctx(ctx); + +release_q: + wd_release_queue(&q); + free(data); + return ret; +} diff --git a/uadk/v1/test/hisi_zip_test/Makefile.am b/uadk/v1/test/hisi_zip_test/Makefile.am new file mode 100644 index 0000000..dae3c59 --- /dev/null +++ b/uadk/v1/test/hisi_zip_test/Makefile.am @@ -0,0 +1,38 @@ +AM_CFLAGS=-Wall -O0 -fno-strict-aliasing -I$(top_srcdir)/v1 -I$(srcdir)/v1/test -I$(top_srcdir) -pthread +AUTOMAKE_OPTIONS = subdir-objects +bin_PROGRAMS=test_hisi_zip test_hisi_zlib wd_zip_test wd_zip_test_1630 test_hisi_zip_perf + +test_hisi_zip_SOURCES=test_hisi_zip.c ../wd_sched.c ../smm.c +if WD_STATIC_DRV +test_hisi_zip_LDADD=../../../.libs/libwd.a +else +test_hisi_zip_LDADD=../../../.libs/libwd.so -lnuma +endif # WD_STATIC_DRV + +test_hisi_zlib_SOURCES=test_hisi_zlib.c zip_alg.c ../wd_sched.c ../smm.c +if WD_STATIC_DRV +test_hisi_zlib_LDADD=../../../.libs/libwd.a +else +test_hisi_zlib_LDADD=../../../.libs/libwd.so -lnuma +endif # WD_STATIC_DRV + +wd_zip_test_SOURCES=wd_zip_test.c zip_alg.c ../wd_sched.c ../smm.c +if WD_STATIC_DRV +wd_zip_test_LDADD=../../../.libs/libwd.a -lz +else +wd_zip_test_LDADD=../../../.libs/libwd.so -lz -lnuma +endif # WD_STATIC_DRV + +wd_zip_test_1630_SOURCES=wd_zip_test_1630.c +if WD_STATIC_DRV +wd_zip_test_1630_LDADD=../../../.libs/libwd.a -lz +else +wd_zip_test_1630_LDADD=../../../.libs/libwd.so -lz -lnuma +endif # WD_STATIC_DRV + +test_hisi_zip_perf_SOURCES=test_hisi_zip_perf.c zip_alg.c ../wd_sched.c ../smm.c +if WD_STATIC_DRV +test_hisi_zip_perf_LDADD=../../../.libs/libwd.a +else +test_hisi_zip_perf_LDADD=../../../.libs/libwd.so -lz -lnuma +endif # WD_STATIC_DRV diff --git a/uadk/v1/test/hisi_zip_test/test_hisi_zip.c b/uadk/v1/test/hisi_zip_test/test_hisi_zip.c new file mode 100644 index 0000000..69ba590 --- /dev/null +++ b/uadk/v1/test/hisi_zip_test/test_hisi_zip.c @@ -0,0 +1,350 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include "v1/wd.h" +#include "v1/wd_util.h" +#include "v1/test/wd_sched.h" +#include "v1/drv/hisi_qm_udrv.h" +#define __USE_GNU +#include +#include +#include "v1/wd_comp.h" + +#define SYS_ERR_COND(cond, msg, ...) \ +do { \ + if (cond) { \ + if (errno) \ + perror(msg); \ + else \ + fprintf(stderr, msg, ##__VA_ARGS__); \ + exit(EXIT_FAILURE); \ + } \ +} while (0) + +#define ZLIB 0 +#define GZIP 1 + +#define DEFLATE 0 +#define INFLATE 1 + +#define ZLIB_HEADER "\x78\x9c" +#define ZLIB_HEADER_SZ 2 + +/* + * We use a extra field for gzip block length. So the fourth byte is \x04. + * This is necessary because our software don't know the size of block when + * using an hardware decompresser (It is known by hardware). This help our + * decompresser to work and helpfully, compatible with gzip. + */ +#define GZIP_HEADER "\x1f\x8b\x08\x04\x00\x00\x00\x00\x00\x03" +#define GZIP_HEADER_SZ 10 +#define GZIP_EXTRA_SZ 10 +#define GZIP_TAIL_SZ 8 + +/* bytes of data for a request */ +static int block_size = 1024 * 1024; +static int req_cache_num = 4; +static int q_num = 1; + +static struct hizip_priv { + int alg_type; + int op_type; + int dw9; + int total_len; + struct wcrypto_comp_msg *msgs; + FILE *sfile, *dfile; +} hizip_priv; + +static struct wd_scheduler sched = { + .priv = &hizip_priv, +}; + +static void hizip_wd_sched_init_cache(struct wd_scheduler *sched, int i) +{ + struct wd_msg *wd_msg = &sched->msgs[i]; + struct wcrypto_comp_msg *msg; + struct hizip_priv *priv = sched->priv; + + msg = wd_msg->msg = &priv->msgs[i]; + msg->alg_type = priv->alg_type; + msg->avail_out = sched->msg_data_size; + + msg->src = wd_msg->data_in; + msg->dst = wd_msg->data_out; + + dbg("init sched cache %d: %p, %p\n", i, wd_msg, msg); +} + +static int hizip_wd_sched_input(struct wd_msg *msg, void *priv) +{ + size_t ilen, templen, real_len, sz; + struct wcrypto_comp_msg *m = msg->msg; + + ilen = hizip_priv.total_len > block_size ? + block_size : hizip_priv.total_len; + templen = ilen; + hizip_priv.total_len -= ilen; + if (hizip_priv.op_type == INFLATE) { + if (hizip_priv.alg_type == ZLIB) { + sz = fread(msg->data_in, 1, ZLIB_HEADER_SZ, + hizip_priv.sfile); + SYS_ERR_COND(sz != ZLIB_HEADER_SZ, "read"); + ilen -= ZLIB_HEADER_SZ; + } else { + sz = fread(msg->data_in, 1, GZIP_HEADER_SZ, + hizip_priv.sfile); + SYS_ERR_COND(sz != GZIP_HEADER_SZ, "read"); + ilen -= GZIP_HEADER_SZ; + if (*((char *)msg->data_in + 3) == 0x04) { + sz = fread(msg->data_in, 1, GZIP_EXTRA_SZ, + hizip_priv.sfile); + memcpy(&ilen, msg->data_in + 6, 4); + dbg("gzip iuput len %ld\n", ilen); + SYS_ERR_COND(ilen > block_size * 2, + "gzip protocol_len(%ld) > dmabuf_size(%d)\n", + ilen, block_size); + real_len = GZIP_HEADER_SZ + + GZIP_EXTRA_SZ + ilen; + hizip_priv.total_len = hizip_priv.total_len + + templen - real_len; + } + } + } + + sz = fread(msg->data_in, 1, ilen, hizip_priv.sfile); + SYS_ERR_COND(sz != ilen, "read"); + + m->in_size = ilen; + dbg("zip input ilen= %lu, block_size= %d, total_len= %d\n", + ilen, block_size, hizip_priv.total_len); + + dbg("zip input(%p, %p): %p, %p, %d, %d\n", + msg, m, + m->src, m->dst, + m->avail_out, m->in_size); + + return 0; +} + +static int hizip_wd_sched_output(struct wd_msg *msg, void *priv) +{ + size_t sz; + struct wcrypto_comp_msg *m = msg->msg; + char gzip_extra[GZIP_EXTRA_SZ] = {0x08, 0x00, 0x48, 0x69, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00}; + + dbg("%s()(%p, %p): %p, %p, inlen=%d, outlen=%d, coms=%d, out=%d\n", + __func__, msg, m, m->src, m->dst, + m->in_size, m->avail_out, m->in_cons, m->produced); + + if (hizip_priv.op_type == DEFLATE) { + + if (hizip_priv.alg_type == ZLIB) { + sz = fwrite(ZLIB_HEADER, 1, ZLIB_HEADER_SZ, + hizip_priv.dfile); + SYS_ERR_COND(sz != ZLIB_HEADER_SZ, "write"); + } else { + sz = fwrite(GZIP_HEADER, 1, GZIP_HEADER_SZ, + hizip_priv.dfile); + SYS_ERR_COND(sz != GZIP_HEADER_SZ, "write"); + memcpy(gzip_extra + 6, &m->produced, 4); + sz = fwrite(gzip_extra, 1, GZIP_EXTRA_SZ, + hizip_priv.dfile); + SYS_ERR_COND(sz != GZIP_EXTRA_SZ, "write"); + } + } + sz = fwrite(msg->data_out, 1, m->produced, hizip_priv.dfile); + SYS_ERR_COND(sz != m->produced, "write"); + return 0; +} + +int hizip_init(int alg_type, int op_type) +{ + int ret = -ENOMEM, i; + char *alg; + struct wcrypto_paras *priv; + + sched.q_num = q_num; + sched.ss_region_size = 0; /* let system make decision */ + sched.msg_cache_num = req_cache_num; + /* use twice size of the input data, hope it is engouth for output */ + sched.msg_data_size = block_size * 2; + sched.init_cache = hizip_wd_sched_init_cache; + sched.input = hizip_wd_sched_input; + sched.output = hizip_wd_sched_output; + + sched.qs = calloc(q_num, sizeof(*sched.qs)); + if (!sched.qs) + return -ENOMEM; + + hizip_priv.msgs = calloc(req_cache_num, sizeof(*hizip_priv.msgs)); + if (!hizip_priv.msgs) + goto err_with_qs; + + + hizip_priv.alg_type = alg_type; + hizip_priv.op_type = op_type; + if (alg_type == ZLIB) { + alg = "zlib"; + hizip_priv.dw9 = 2; + } else { + alg = "gzip"; + hizip_priv.dw9 = 3; + } + + for (i = 0; i < q_num; i++) { + sched.qs[i].capa.alg = alg; + priv = &sched.qs[i].capa.priv; + priv->direction = hizip_priv.op_type; + } + ret = wd_sched_init(&sched); + if (ret) + goto err_with_msgs; + + return 0; + +err_with_msgs: + free(hizip_priv.msgs); +err_with_qs: + free(sched.qs); + return ret; +} + +void hizip_fini(void) +{ + wd_sched_fini(&sched); + free(hizip_priv.msgs); + free(sched.qs); +} + +void hizip_deflate(FILE *source, FILE *dest) +{ + int fd; + struct stat s; + int ret; + + fd = fileno(source); + SYS_ERR_COND(fstat(fd, &s) < 0, "fstat"); + hizip_priv.total_len = s.st_size; + SYS_ERR_COND(!hizip_priv.total_len, "input file length zero"); + hizip_priv.sfile = source; + hizip_priv.dfile = dest; + + /* ZLIB engine can do only one time with buffer less than 16M */ + if (hizip_priv.alg_type == ZLIB) { + SYS_ERR_COND(hizip_priv.total_len > block_size, + "zip total_len(%d) > block_size(%d)\n", + hizip_priv.total_len, block_size); + SYS_ERR_COND(block_size > 16 * 1024 * 1024, + "block_size (%d) > 16MB hw limit!\n", + hizip_priv.total_len); + } + + while (hizip_priv.total_len || !wd_sched_empty(&sched)) { + dbg("request loop: total_len=%d\n", hizip_priv.total_len); + ret = wd_sched_work(&sched, hizip_priv.total_len); + SYS_ERR_COND(ret < 0, "wd_sched_work"); + } + + fclose(dest); +} + +void hizip_def(FILE *source, FILE *dest, int alg_type, int op_type) +{ + int ret; + + ret = hizip_init(alg_type, op_type); + SYS_ERR_COND(ret, "hizip init fail\n"); + + hizip_deflate(stdin, stdout); + + hizip_fini(); +} + +int main(int argc, char *argv[]) +{ + int alg_type = GZIP; + int op_type = DEFLATE; + int opt; + int show_help = 0; + cpu_set_t mask; + int cpuid = 0; + + CPU_ZERO(&mask); + while ((opt = getopt(argc, argv, "zghq:b:dc:o:")) != -1) { + switch (opt) { + case 'z': + alg_type = ZLIB; + break; + case 'g': + alg_type = GZIP; + break; + case 'q': + q_num = atoi(optarg); + if (q_num <= 0) + show_help = 1; + break; + case 'b': + block_size = atoi(optarg); + if (block_size <= 0) + show_help = 1; + break; + case 'c': + req_cache_num = atoi(optarg); + if (req_cache_num <= 0) + show_help = 1; + break; + case 'd': + op_type = INFLATE; + break; + case 'o': + cpuid = atoi(optarg); + break; + default: + show_help = 1; + break; + } + } + + if (cpuid) { + if (cpuid <= 0 || cpuid > 128) { + fputs("set cpu no affinity!\n", stderr); + goto no_affinity; + } + CPU_SET(cpuid, &mask); + if (sched_setaffinity(0, sizeof(mask), &mask) < 0) { + perror("sched_setaffinityfail!"); + return -1; + } + } + +no_affinity: + + SYS_ERR_COND(show_help || optind > argc, + "test_hisi_zip -[g|z] [-q q_num] < in > out"); + + hizip_def(stdin, stdout, alg_type, op_type); + + return EXIT_SUCCESS; +} diff --git a/uadk/v1/test/hisi_zip_test/test_hisi_zip_perf.c b/uadk/v1/test/hisi_zip_test/test_hisi_zip_perf.c new file mode 100644 index 0000000..4d0144f --- /dev/null +++ b/uadk/v1/test/hisi_zip_test/test_hisi_zip_perf.c @@ -0,0 +1,950 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ +#define DEBUG_LOG + +#include +#include +#include +#define __USE_GNU +#include +#include +#include +#include +#include + +#include "v1/drv/hisi_qm_udrv.h" +#include "zlib.h" +#include "v1/test/smm.h" +#include "zip_alg.h" +#include "v1/wd_comp.h" +#include "v1/wd.h" +#include "v1/wd_util.h" + +static inline int _get_cpu_id(int thr, __u64 core_mask) +{ + __u64 i; + int cnt = 0; + + + for (i = 1; i < 64; i ++) { + if (core_mask & (0x1ull << i)) { + if (thr == cnt) + return i; + cnt++; + } + } + + return 0; +} + +static inline int _get_one_bits(__u64 val) +{ + int count = 0; + while (val) { + if (val % 2 == 1) + count++; + val = val / 2; + } + return count; +} + +static void get_core_mask(char *coremask, __u64* core_mask) +{ + if (strlen(coremask) <= 18) { + core_mask[0] = strtoull(coremask, NULL, 16); + if (core_mask[0] & 0x1) { + core_mask[0] = 0x0; /* no binding */ + } + core_mask[1] = 0; + } else { + int offset = 0; + char *temp; + offset = strlen(coremask) - 16; + core_mask[0] = strtoull(&coremask[offset], NULL, 16); + if (core_mask[0] & 0x1) { + core_mask[0] = 0x0; /* no binding */ + } + temp = malloc(64); + strcpy(temp, coremask); + temp[offset] = 0; + core_mask[1] = strtoull(temp, NULL, 16); + free(temp); + } + + +} + +enum mode { + BLOCK, + STREAM, + ASYNC, +}; + +struct test_zip_pthread_dt { + int cpu_id; + int op_type; + int hw_flag; + int blksize; + int alg_type; + int iteration; + int thread_num; + void *src; + void *dst; + ulong src_len; + ulong dst_len; + float com_time; + float decom_time; + struct wcrypto_comp_ctx *ctx; + struct wcrypto_comp_op_data *opdata; + struct wcrypto_comp_ctx_setup *ctx_setup; +}; + +struct user_comp_tag_info { + pid_t tid; + int cpu_id; + int alg_type; +}; + +#define TEST_MAX_THRD 2048 +#define MAX_CORES 128 +#define Q_MAX_CTX 1 +#define CTX_NUM(a, b) (((a / Q_MAX_CTX) >= (b + 1)) \ + ? Q_MAX_CTX : (a % Q_MAX_CTX)) + +static struct test_zip_pthread_dt test_thrds_data[TEST_MAX_THRD]; +static struct wd_queue q[TEST_MAX_THRD / Q_MAX_CTX]; +static pthread_t system_test_thrds[TEST_MAX_THRD]; + +/* bytes of data for a request */ +static int block_size = 512000; +static int q_num = 1; + +pid_t gettid(void) +{ + return syscall(__NR_gettid); +} + +void zip_callback(const void *msg, void *tag) +{ + const struct wcrypto_comp_msg *respmsg = msg; + const struct user_comp_tag_info *utag = tag; + int i = utag->cpu_id; + + test_thrds_data[i].dst_len = respmsg->produced; + memcpy(test_thrds_data[i].dst, + test_thrds_data[i].opdata->out, + test_thrds_data[i].dst_len); + //dbg("%s %dth thrds produced %d!\n", __func__, i, respmsg->produced); +} + +void *zip_sys_async_poll_thread(void *args) +{ + int *cnt = calloc(1, sizeof(int) * q_num); + struct test_zip_pthread_dt *pdata = args; + int thread_num = pdata->thread_num; + int iter = pdata->iteration; + int workq_num = q_num; + int ret, i; + + //pid_t tid = gettid(); + //dbg("%s poll thread_id=%d\n", __func__, (int)tid); + + for (i = 0; i < q_num; i++) + cnt[i] = iter * CTX_NUM(thread_num, i); + + do { + i = 0; + for ( ; i < q_num; i++) { + if (!cnt[i]) + continue; + ret = wcrypto_comp_poll(&q[i], cnt[i]); + if (ret < 0) { + WD_ERR("poll fail! thread_id=%d, ret:%d\n", + pdata->cpu_id, ret); + break; + } + cnt[i] -= ret; + if (!cnt[i]) + workq_num--; + } + } while (workq_num); + + return NULL; +} + +void *zip_sys_async_comp_thread(void *args) +{ + struct test_zip_pthread_dt *pdata = args; + struct user_comp_tag_info *utag; + int i = pdata->iteration; + pid_t tid = gettid(); + int ret; + int cpu_id = pdata->cpu_id; + cpu_set_t mask; + CPU_ZERO(&mask); + if (cpu_id) { + if (cpu_id <= 0 || cpu_id > MAX_CORES) { + dbg("set cpu no affinity!\n"); + goto therad_no_affinity; + } + CPU_SET(cpu_id, &mask); + if (pthread_setaffinity_np(pthread_self(), + sizeof(mask), &mask) < 0) { + perror("pthread_setaffinity fail!\n"); + return NULL; + } + } + +therad_no_affinity: + utag = calloc(1, sizeof(struct user_comp_tag_info)); + utag->alg_type = pdata->alg_type; + utag->cpu_id = pdata->cpu_id; + utag->tid = tid; + + //dbg("%s entry thread_id=%d\n", __func__, (int)tid); + do { + ret = wcrypto_do_comp(pdata->ctx, pdata->opdata, utag); + if (ret == -WD_EBUSY) { + //WD_ERR("%s(): asynctest no cache!\n", __func__); + i++; + } + } while (--i); + //dbg("thread_id=%d do_comp is ok\n", (int)tid); + + return NULL; +} + +int zip_sys_async_init(int thread_num, + int alg_type, int op_type) +{ + size_t ss_region_size = 4096 + DMEMSIZE * 2 + HW_CTX_SIZE; + struct test_zip_pthread_dt *pdata; + struct wcrypto_paras *priv; + void **ss_buf; + int i, j, ret; + + q_num = (thread_num % Q_MAX_CTX > 0) ? + (thread_num / Q_MAX_CTX + 1) : + (thread_num / Q_MAX_CTX); + + ss_buf = calloc(1, sizeof(void *) * q_num); + for (i = 0; i < q_num; i++) { + switch (alg_type) { + case 0: + q[i].capa.alg = "zlib"; + break; + case 1: + q[i].capa.alg = "gzip"; + break; + default: + q[i].capa.alg = "zlib"; + break; + } + q[i].capa.latency = 0; + q[i].capa.throughput = 0; + priv = &q[i].capa.priv; + priv->direction = op_type; + ret = wd_request_queue(&q[i]); + if (ret) { + WD_ERR("request %dth q fail, ret =%d\n", i, ret); + goto err_q_release; + + } +#ifdef CONFIG_IOMMU_SVA + ss_buf[i] = calloc(1, ss_region_size * Q_MAX_CTX); +#else + ss_buf[i] = wd_reserve_memory(&q[i], + ss_region_size * Q_MAX_CTX); +#endif + if (!ss_buf[i]) { + WD_ERR("reserve %dth buf fail, ret =%d\n", i, ret); + ret = -ENOMEM; + goto err_q_release; + } + smm_init(ss_buf[i], ss_region_size * Q_MAX_CTX, 0xF); + if (ret) + goto err_q_release; + } + + for (i = 0; i < thread_num; i++) { + pdata = &test_thrds_data[i]; + pdata->ctx_setup = calloc(1, + sizeof(struct wcrypto_comp_ctx_setup)); + if (!pdata->ctx_setup) { + ret = -ENOMEM; + WD_ERR("alloc %dth ctx_setup fail, ret = %d\n", i, ret); + goto err_ctx_setup_free; + } + pdata->ctx_setup->stream_mode = WCRYPTO_COMP_STATELESS; + pdata->ctx_setup->cb = zip_callback; + pdata->ctx = wcrypto_create_comp_ctx( + &q[i / Q_MAX_CTX], pdata->ctx_setup); + if (!pdata->ctx) + goto err_ctx_del; + + pdata->opdata = calloc(1, sizeof(struct wcrypto_comp_op_data)); + if (!pdata->opdata) { + ret = -ENOMEM; + WD_ERR("alloc %dth opdata fail, ret = %d\n", i, ret); + goto err_opdata_free; + } + pdata->opdata->stream_pos = WCRYPTO_COMP_STREAM_NEW; + pdata->opdata->avail_out = DMEMSIZE; + pdata->opdata->in = smm_alloc(ss_buf[i / Q_MAX_CTX], DMEMSIZE); + pdata->opdata->out = smm_alloc(ss_buf[i / Q_MAX_CTX], DMEMSIZE); + if (pdata->opdata->in == NULL || pdata->opdata->out == NULL) { + ret = -ENOMEM; + WD_ERR("not enough data ss_region memory for cache (bs=%d)\n", + DMEMSIZE); + goto err_opdata_free; + } + pdata->opdata->in_len = pdata->src_len; + memcpy(pdata->opdata->in, pdata->src, pdata->src_len); + } + + return 0; + +err_opdata_free: + wcrypto_del_comp_ctx(test_thrds_data[i].ctx); +err_ctx_del: + free(test_thrds_data[i].ctx_setup); +err_ctx_setup_free: + for (j = 0; j < i; j++) { + wcrypto_del_comp_ctx(test_thrds_data[j].ctx); + free(test_thrds_data[j].ctx_setup); + free(test_thrds_data[j].opdata); + } + i = q_num; +err_q_release: + for (j = 0; j < i; j++) + wd_release_queue(&q[j]); + + return ret; +} + +void *zip_sys_stream_thread(void *args) +{ + struct test_zip_pthread_dt *pdata = args; + int i = pdata->iteration; + //pid_t tid = gettid(); + int ret; + int cpu_id = pdata->cpu_id; + cpu_set_t mask; + CPU_ZERO(&mask); + if (cpu_id) { + if (cpu_id <= 0 || cpu_id > MAX_CORES) { + dbg("set cpu no affinity!\n"); + goto therad_no_affinity; + } + CPU_SET(cpu_id, &mask); + if (pthread_setaffinity_np(pthread_self(), + sizeof(mask), &mask) < 0) { + perror("pthread_setaffinity fail!\n"); + return NULL; + } + } + + struct timeval start_tval, end_tval; + +therad_no_affinity: + gettimeofday(&start_tval, NULL); + //dbg("%s entry thread_id=%d\n", __func__, (int)tid); + do { + ret = wcrypto_do_comp(pdata->ctx, pdata->opdata, NULL); + if (ret == -WD_EBUSY) + i++; + + pdata->dst_len = pdata->opdata->produced; + } while (--i); + //dbg("thread_id=%d do_comp is ok\n", (int)tid); + gettimeofday(&end_tval, NULL); + + //float tc = (float)((end_tval.tv_sec-start_tval.tv_sec) * 1000000 + + // end_tval.tv_usec - start_tval.tv_usec); + //dbg("%s end, time = %f\n", __func__, tc); + + return NULL; +} + +void *zip_sys_block_thread(void *args) +{ + struct test_zip_pthread_dt *pdata = args; + int i = pdata->iteration; + //pid_t tid = gettid(); + int ret; + int cpu_id = pdata->cpu_id; + cpu_set_t mask; + CPU_ZERO(&mask); + if (cpu_id) { + if (cpu_id <= 0 || cpu_id > MAX_CORES) { + dbg("set cpu no affinity!\n"); + goto therad_no_affinity; + } + CPU_SET(cpu_id, &mask); + if (pthread_setaffinity_np(pthread_self(), + sizeof(mask), &mask) < 0) { + perror("pthread_setaffinity fail!\n"); + return NULL; + } + } + + + struct timeval start_tval, end_tval; +therad_no_affinity: + + gettimeofday(&start_tval, NULL); + //dbg("%s entry thread_id=%d\n", __func__, (int)tid); + do { + ret = wcrypto_do_comp(pdata->ctx, pdata->opdata, NULL); + if (ret == -WD_EBUSY) + i++; + + pdata->dst_len = pdata->opdata->produced; + } while (--i); + //dbg("thread_id=%d do_comp is ok\n", (int)tid); + gettimeofday(&end_tval, NULL); + + //float tc = (float)((end_tval.tv_sec-start_tval.tv_sec) * 1000000 + + // end_tval.tv_usec - start_tval.tv_usec); + //dbg("%s end, time = %f\n", __func__, tc); + + return NULL; +} + +int zip_sys_stream_init(int thread_num, + int alg_type, int op_type) +{ + struct test_zip_pthread_dt *pdata; + struct wcrypto_paras *priv; + size_t ss_region_size = 4096 + DMEMSIZE * 2 + HW_CTX_SIZE; + void **ss_buf; + int i, j, ret; + + q_num = (thread_num % Q_MAX_CTX > 0) ? + (thread_num / Q_MAX_CTX + 1) : (thread_num / Q_MAX_CTX); + + ss_buf = calloc(1, sizeof(void *) * q_num); + for (i = 0; i < q_num; i++) { + switch (alg_type) { + case 0: + q[i].capa.alg = "zlib"; + break; + case 1: + q[i].capa.alg = "gzip"; + break; + default: + q[i].capa.alg = "zlib"; + break; + } + q[i].capa.latency = 0; + q[i].capa.throughput = 0; + priv = &q[i].capa.priv; + priv->direction = op_type; + ret = wd_request_queue(&q[i]); + if (ret) { + WD_ERR("request %dth q fail, ret =%d\n", i, ret); + goto err_q_release; + + } +#ifdef CONFIG_IOMMU_SVA + ss_buf[i] = calloc(1, ss_region_size * Q_MAX_CTX); +#else + ss_buf[i] = wd_reserve_memory(&q[i], + ss_region_size * Q_MAX_CTX); +#endif + if (!ss_buf[i]) { + WD_ERR("reserve %dth buf fail, ret =%d\n", i, ret); + ret = -ENOMEM; + goto err_q_release; + } + smm_init(ss_buf[i], ss_region_size * Q_MAX_CTX, 0xF); + if (ret) + goto err_q_release; + } + + for (i = 0; i < thread_num; i++) { + pdata = &test_thrds_data[i]; + pdata->ctx_setup = calloc(1, + sizeof(struct wcrypto_comp_ctx_setup)); + if (!pdata->ctx_setup) { + ret = -ENOMEM; + WD_ERR("alloc %dth ctx_setup fail, ret = %d\n", i, ret); + goto err_ctx_setup_free; + } + pdata->ctx_setup->stream_mode = WCRYPTO_COMP_STATEFUL; + pdata->ctx_setup->br.alloc = smm_alloc; + pdata->ctx_setup->br.free = smm_free; + pdata->ctx_setup->br.usr = ss_buf[i]; + pdata->ctx = wcrypto_create_comp_ctx(&q[i / Q_MAX_CTX], + pdata->ctx_setup); + if (!pdata->ctx) + goto err_ctx_del; + + pdata->opdata = calloc(1, sizeof(struct wcrypto_comp_op_data)); + if (!pdata->opdata) { + ret = -ENOMEM; + WD_ERR("alloc %dth opdata fail, ret = %d\n", i, ret); + goto err_opdata_free; + } + pdata->opdata->stream_pos = WCRYPTO_COMP_STREAM_NEW; + pdata->opdata->avail_out = DMEMSIZE; + pdata->opdata->in = smm_alloc(ss_buf[i / Q_MAX_CTX], DMEMSIZE); + pdata->opdata->out = smm_alloc(ss_buf[i / Q_MAX_CTX], DMEMSIZE); + if (pdata->opdata->in == NULL || + pdata->opdata->out == NULL) { + ret = -ENOMEM; + WD_ERR("not enough data ss_region memory for cache (bs=%d)\n", + DMEMSIZE); + goto err_opdata_free; + } + pdata->opdata->in_len = pdata->src_len; + memcpy(pdata->opdata->in, pdata->src, pdata->src_len); + } + + return 0; + +err_opdata_free: + wcrypto_del_comp_ctx(test_thrds_data[i].ctx); +err_ctx_del: + free(test_thrds_data[i].ctx_setup); +err_ctx_setup_free: + for (j = 0; j < i; j++) { + wcrypto_del_comp_ctx(test_thrds_data[j].ctx); + free(test_thrds_data[j].ctx_setup); + free(test_thrds_data[j].opdata); + } + i = q_num; +err_q_release: + for (j = 0; j < i; j++) + wd_release_queue(&q[j]); + + return ret; +} + +int zip_sys_block_init(int thread_num, + int alg_type, int op_type) +{ +struct test_zip_pthread_dt *pdata; + struct wcrypto_paras *priv; + size_t ss_region_size = 4096 + DMEMSIZE * 2 + HW_CTX_SIZE; + void **ss_buf; + int i, j, ret; + + q_num = (thread_num % Q_MAX_CTX > 0) ? + (thread_num / Q_MAX_CTX + 1) : (thread_num / Q_MAX_CTX); + + //dbg("%s init start\n", __func__); + + ss_buf = calloc(1, sizeof(void *) * q_num); + for (i = 0; i < q_num; i++) { + switch (alg_type) { + case 0: + q[i].capa.alg = "zlib"; + break; + case 1: + q[i].capa.alg = "gzip"; + break; + default: + q[i].capa.alg = "zlib"; + break; + } + q[i].capa.latency = 0; + q[i].capa.throughput = 0; + priv = &q[i].capa.priv; + priv->direction = op_type; + ret = wd_request_queue(&q[i]); + if (ret) { + WD_ERR("request %dth q fail, ret =%d\n", i, ret); + goto err_q_release; + + } +#ifdef CONFIG_IOMMU_SVA + ss_buf[i] = calloc(1, ss_region_size * Q_MAX_CTX); +#else + ss_buf[i] = wd_reserve_memory(&q[i], + ss_region_size * Q_MAX_CTX); +#endif + if (!ss_buf[i]) { + WD_ERR("reserve %dth buf fail, ret =%d\n", i, ret); + ret = -ENOMEM; + goto err_q_release; + } + smm_init(ss_buf[i], ss_region_size * Q_MAX_CTX, 0xF); + if (ret) + goto err_q_release; + } + + for (i = 0; i < thread_num; i++) { + pdata = &test_thrds_data[i]; + pdata->ctx_setup = calloc(1, + sizeof(struct wcrypto_comp_ctx_setup)); + if (!pdata->ctx_setup) { + ret = -ENOMEM; + WD_ERR("alloc %dth ctx_setup fail, ret = %d\n", i, ret); + goto err_ctx_setup_free; + } + pdata->ctx_setup->stream_mode = WCRYPTO_COMP_STATELESS; + pdata->ctx_setup->br.alloc = smm_alloc; + pdata->ctx_setup->br.free = smm_free; + pdata->ctx_setup->br.usr = ss_buf[i]; + pdata->ctx = wcrypto_create_comp_ctx( + &q[i / Q_MAX_CTX], pdata->ctx_setup); + if (!pdata->ctx) + goto err_ctx_del; + + pdata->opdata = calloc(1, sizeof(struct wcrypto_comp_op_data)); + if (!pdata->opdata) { + ret = -ENOMEM; + WD_ERR("alloc %dth opdata fail, ret = %d\n", i, ret); + goto err_opdata_free; + } + pdata->opdata->stream_pos = WCRYPTO_COMP_STREAM_NEW; + pdata->opdata->avail_out = DMEMSIZE; + pdata->opdata->in = + smm_alloc(ss_buf[i / Q_MAX_CTX], DMEMSIZE); + pdata->opdata->out = + smm_alloc(ss_buf[i / Q_MAX_CTX], DMEMSIZE); + if (pdata->opdata->in == NULL || + pdata->opdata->out == NULL) { + ret = -ENOMEM; + WD_ERR("not enough data ss_region memory for cache (bs=%d)\n", + DMEMSIZE); + goto err_opdata_free; + } + pdata->opdata->in_len = pdata->src_len; + memcpy(pdata->opdata->in, pdata->src, pdata->src_len); + } + //dbg("%s init end\n", __func__); + + return 0; + +err_opdata_free: + wcrypto_del_comp_ctx(test_thrds_data[i].ctx); +err_ctx_del: + free(test_thrds_data[i].ctx_setup); +err_ctx_setup_free: + for (j = 0; j < i; j++) { + wcrypto_del_comp_ctx(test_thrds_data[j].ctx); + free(test_thrds_data[j].ctx_setup); + free(test_thrds_data[j].opdata); + } + i = q_num; +err_q_release: + for (j = 0; j < i; j++) + wd_release_queue(&q[j]); + + return ret; +} + +void zip_sys_test_uninit(int thread_num) +{ + int i; + + for (i = 0; i < thread_num; i++) { + wcrypto_del_comp_ctx(test_thrds_data[i].ctx); + free(test_thrds_data[i].ctx_setup); + free(test_thrds_data[i].opdata); + } + + for (i = 0; i < q_num; i++) + wd_release_queue(&q[i]); +} + +static int hizip_thread_test(FILE *source, FILE *dest, + int thread_num, int alg_type, int op_type, + int mode, int hw_flag, int iteration, __u64 lcore_mask, + __u64 hcore_mask) +{ + int in_len, sz, fd, count, i, j, ret; + struct timeval start_tval, end_tval, poll_tval; + float total_out = 0; + float total_in = 0; + float tc, speed; + void *file_buf; + struct stat s; + + fd = fileno(source); + SYS_ERR_COND(fstat(fd, &s) < 0, "fstat"); + in_len = s.st_size; + SYS_ERR_COND(!in_len, "input file length zero"); + + file_buf = calloc(1, in_len); + + sz = fread(file_buf, 1, in_len, source); + if (sz != in_len) + WD_ERR("read file sz != in_len!\n"); + count = in_len/block_size; + + if (!count) + count = 1; + + //dbg("%s entry blocksize=%d, count=%d, threadnum= %d, in_len=%d\n", + // __func__, block_size, count, thread_num, in_len); + int cnt = 0; + if (_get_one_bits(lcore_mask) > 0) + cnt = _get_one_bits(lcore_mask); + else if (_get_one_bits(lcore_mask) == 0 && + _get_one_bits(hcore_mask) == 0) + cnt = thread_num; + + for (i = 0; i < thread_num; i++) { + test_thrds_data[i].thread_num = thread_num; + test_thrds_data[i].iteration = iteration; + test_thrds_data[i].blksize = block_size; + test_thrds_data[i].alg_type = alg_type; + test_thrds_data[i].op_type = op_type; + test_thrds_data[i].hw_flag = hw_flag; + //test_thrds_data[i].cpu_id = i; + test_thrds_data[i].cpu_id = _get_cpu_id(i, lcore_mask); + test_thrds_data[i].src_len = MIN(in_len, block_size); + test_thrds_data[i].dst_len = test_thrds_data[i].src_len * 10; + test_thrds_data[i].src = calloc(1, test_thrds_data[i].src_len); + if (test_thrds_data[i].src == NULL) + goto err_buf_free; + memcpy(test_thrds_data[i].src, file_buf, test_thrds_data[i].src_len); + test_thrds_data[i].dst = calloc(1, test_thrds_data[i].dst_len); + if (test_thrds_data[i].dst == NULL) + goto err_src_buf_free; + } + int h_cpuid; + for (i = 0; i < thread_num - cnt; i++) { + h_cpuid = _get_cpu_id(i, hcore_mask); + if (h_cpuid > 0) + h_cpuid += 64; + test_thrds_data[i].thread_num = thread_num; + test_thrds_data[i].iteration = iteration; + test_thrds_data[i].blksize = block_size; + test_thrds_data[i].alg_type = alg_type; + test_thrds_data[i].op_type = op_type; + test_thrds_data[i].hw_flag = hw_flag; + //test_thrds_data[i].cpu_id = i; + test_thrds_data[i].cpu_id = h_cpuid; + test_thrds_data[i].src_len = MIN(in_len, block_size); + test_thrds_data[i].dst_len = test_thrds_data[i].src_len * 10; + test_thrds_data[i].src = calloc(1, test_thrds_data[i].src_len); + if (test_thrds_data[i].src == NULL) + goto err_buf_free; + memcpy(test_thrds_data[i].src, file_buf, test_thrds_data[i].src_len); + test_thrds_data[i].dst = calloc(1, test_thrds_data[i].dst_len); + if (test_thrds_data[i].dst == NULL) + goto err_src_buf_free; + } + + + if (mode == ASYNC) { + ret = zip_sys_async_init(thread_num, alg_type, op_type); + if (ret) { + WD_ERR("Init async fail!\n"); + goto err_src_buf_free; + } + ret = pthread_create(&system_test_thrds[thread_num], NULL, + zip_sys_async_poll_thread, + &test_thrds_data[0]); + if (ret) { + WD_ERR("Create poll thread fail!\n"); + goto err_src_buf_free; + } + } else if (mode == STREAM) { + ret = zip_sys_stream_init(thread_num, alg_type, op_type); + } else if (mode == BLOCK) { + ret = zip_sys_block_init(thread_num, alg_type, op_type); + } + + gettimeofday(&start_tval, NULL); + for (i = 0; i < thread_num; i++) { + if (mode == STREAM ) + ret = pthread_create(&system_test_thrds[i], NULL, + zip_sys_stream_thread, + &test_thrds_data[i]); + else if (mode == ASYNC) + ret = pthread_create(&system_test_thrds[i], NULL, + zip_sys_async_comp_thread, + &test_thrds_data[i]); + else if (mode == BLOCK ) + ret = pthread_create(&system_test_thrds[i], NULL, + zip_sys_block_thread, + &test_thrds_data[i]); + else + ret = 0; + if (ret) { + WD_ERR("Create %dth thread fail!\n", i); + return ret; + } + } + + for (i = 0; i < thread_num; i++) { + ret = pthread_join(system_test_thrds[i], NULL); + if (ret) { + WD_ERR("Join %dth thread fail!\n", i); + return ret; + } + } + + gettimeofday(&poll_tval, NULL); + if (mode == ASYNC) { + ret = pthread_join(system_test_thrds[thread_num], NULL); + if (ret) { + WD_ERR("Join %dth thread fail!\n", thread_num); + return ret; + } + } + gettimeofday(&end_tval, NULL); + + //float poll_time = (float)((end_tval.tv_sec-poll_tval.tv_sec) * 1000000 + + // end_tval.tv_usec - poll_tval.tv_usec); + tc = (float)((end_tval.tv_sec-start_tval.tv_sec) * 1000000 + + end_tval.tv_usec - start_tval.tv_usec); + //dbg("%s end threadnum = %d,time = %f, poll time = %f\n", + // __func__, thread_num, tc, poll_time); + + sz = fwrite(test_thrds_data[0].opdata->out, 1, + test_thrds_data[0].dst_len, dest); + + for (i = 0; i < thread_num; i++) { + total_in += test_thrds_data[i].src_len; + total_out += test_thrds_data[i].dst_len; + } + if (op_type == WCRYPTO_DEFLATE) { + speed = total_in / tc / + 1024 / 1024 * 1000 * 1000 * iteration, + fprintf(stderr, + "Compress bz=%d, threadnum= %d, qnum=%d, speed=%0.3f MB/s, timedelay=%0.1f us\n", + block_size, thread_num, q_num, speed, + tc / thread_num / count / iteration); + } else { + speed = total_out / tc / + 1024 / 1024 * 1000 * 1000 * iteration, + fprintf(stderr, + "Decompress bz=%d, threadnum= %d, qnum=%d, speed=%0.3f MB/s, timedelay=%0.1f us\n", + block_size, thread_num, q_num, speed, + tc / thread_num / count / iteration); + } + + zip_sys_test_uninit(thread_num); + + for (i = 0; i < thread_num; i++) { + free(test_thrds_data[i].src); + free(test_thrds_data[i].dst); + } + + free(file_buf); + + return 0; + +err_src_buf_free: + free(test_thrds_data[i].src); + +err_buf_free: + for (j = 0; j < i; j++) { + free(test_thrds_data[j].src); + free(test_thrds_data[j].dst); + } + + free(file_buf); + + WD_ERR("thread malloc fail!ENOMEM!\n"); + + return -ENOMEM; +} + + +int main(int argc, char *argv[]) +{ + int op_type = WCRYPTO_DEFLATE; + int alg_type = WCRYPTO_GZIP; + int thread_num = 1; + int iteration = 1; + int show_help = 0; + int hw_flag = 1; + int mode = 0; + __u64 core_mask[2] = {0}; + //int small; + int cpu_mask_c = 0; + int opt; + + while ((opt = getopt(argc, argv, "mkazgdb:p:q:i:c:vh")) != -1) { + switch (opt) { + case 'm': + mode = STREAM; + break; + case 'k': + mode = BLOCK; + break; + case 'a': + mode = ASYNC; + break; + case 'z': + alg_type = WCRYPTO_ZLIB; + break; + case 'g': + alg_type = WCRYPTO_GZIP; + break; + case 'd': + op_type = WCRYPTO_INFLATE; + break; + case 'b': + block_size = atoi(optarg); + if (block_size <= 0) + show_help = 1; + else if (block_size > 1024 * 1024) + SYS_ERR_COND(1, "blocksize > 1M!\n"); + break; + case 'p': + thread_num = atoi(optarg); + if (thread_num > TEST_MAX_THRD) + SYS_ERR_COND(1, "thread_num > 2048!\n"); + break; + case 'q': + q_num = atoi(optarg); + if (q_num <= 0) + show_help = 1; + break; + case 'i': + iteration = atoi(optarg); + if (iteration <= 0) + show_help = 1; + break; + case 'c': + if (!(optarg[0] == '0' && optarg[1] == 'x')) + show_help = 1; + if (strcmp(optarg, "0x0")) { + get_core_mask(optarg,core_mask); + cpu_mask_c += _get_one_bits(core_mask[0]); + cpu_mask_c += _get_one_bits(core_mask[1]); + dbg(" lcoremask=0x%llx, hcoremask=0x%llx\n", core_mask[0], core_mask[1]); + if(thread_num!=cpu_mask_c) + dbg("kthread:%d != cpu_mask:%d at %s", thread_num, cpu_mask_c, __func__); + + + } + + break; + default: + show_help = 1; + break; + } + } + + SYS_ERR_COND(show_help || optind > argc, + "version 2.00:test_hisi_zip_perf -[k/m/a] -[g|z] -d [-b block] [-p thread_num] [-i iteration] [-c 0xcoremask] < in > out"); + + (void)hizip_thread_test(stdin, stdout, thread_num, alg_type, + op_type, mode, hw_flag, iteration, core_mask[0], + core_mask[1]); + + return EXIT_SUCCESS; +} + diff --git a/uadk/v1/test/hisi_zip_test/test_hisi_zlib.c b/uadk/v1/test/hisi_zip_test/test_hisi_zlib.c new file mode 100644 index 0000000..dc73a19 --- /dev/null +++ b/uadk/v1/test/hisi_zip_test/test_hisi_zlib.c @@ -0,0 +1,76 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include "zip_alg.h" +#include "v1/wd_comp.h" + +int main(int argc, char *argv[]) +{ + int ret; + int alg_type = WCRYPTO_GZIP; + int op_type = WCRYPTO_DEFLATE; + int opt; + int show_help = 0; + + if (!argv[1]) { + fputs("<>\n", stderr); + goto EXIT; + } + + while ((opt = getopt(argc, argv, "zgdh")) != -1) { + switch (opt) { + case 'z': + alg_type = WCRYPTO_ZLIB; + break; + case 'g': + alg_type = WCRYPTO_GZIP; + break; + case 'd': + op_type = WCRYPTO_INFLATE; + SYS_ERR_COND(0, "decompress function to be added\n"); + break; + default: + show_help = 1; + break; + } + } + + SYS_ERR_COND(show_help || optind > argc, + "test_hisi_zlib -[g|z] [-d] < in > out\n"); + + switch (op_type) { + case WCRYPTO_DEFLATE: + ret = hw_stream_def(stdin, stdout, alg_type); + if (ret) + fputs("hw_stream_deflate error!\n", stderr); + break; + case WCRYPTO_INFLATE: + ret = hw_stream_inf(stdin, stdout, alg_type); + if (ret) + fputs("hw_stream_inflate error!\n", stderr); + break; + default: + fputs("default cmd!\n", stderr); + } +EXIT: + return EXIT_SUCCESS; +} diff --git a/uadk/v1/test/hisi_zip_test/wd_zip_test.c b/uadk/v1/test/hisi_zip_test/wd_zip_test.c new file mode 100644 index 0000000..43a3bb0 --- /dev/null +++ b/uadk/v1/test/hisi_zip_test/wd_zip_test.c @@ -0,0 +1,617 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#define __USE_GNU +#include +#include +#include +#include + +#include "v1/wd.h" +#include "zip_alg.h" +#include "v1/wd_util.h" +#include "v1/wd_comp.h" +#include "v1/drv/hisi_qm_udrv.h" +#include "v1/wd_bmm.h" +enum mode { + MODE_BLOCK, + MODE_STREAM, + ASYNC, +}; + +struct test_zip_pthread_dt { + int cpu_id; + int thread_num; + int alg_type; + int op_type; + int hw_flag; + int blksize; + int iteration; + void *src; + void *dst; + ulong src_len; + ulong dst_len; + float com_time; + float decom_time; + void *pool; +}; + +struct user_comp_tag_info { + int cpu_id; + pid_t tid; + int alg_type; +}; + +#define TEST_MAX_THRD 2048 +#define MAX_CORES 128 +#define WD_WAIT_MS 1000 +#define MAX_DMEMSIZE 8 * 1024 * 1024 /* 8M */ + +static pthread_t system_test_thrds[TEST_MAX_THRD]; +static struct test_zip_pthread_dt test_thrds_data[TEST_MAX_THRD]; + +/* bytes of data for a request */ +static int block_size = 512000; +static int req_cache_num = 4; +static int q_num = 1; +static int verify; + +pid_t gettid(void) +{ + return syscall(__NR_gettid); +} + +/* stream mode test thread */ +void *zlib_sys_stream_test_thread(void *args) +{ + int cpu_id, ret; + pid_t tid; + cpu_set_t mask; + struct test_zip_pthread_dt *pdata = args; + int i = pdata->iteration; + + cpu_id = pdata->cpu_id; + tid = gettid(); + + CPU_ZERO(&mask); + if (cpu_id) { + if (cpu_id <= 0 || cpu_id > MAX_CORES) { + dbg("set cpu no affinity!\n"); + goto therad_no_affinity; + } + CPU_SET(cpu_id, &mask); + if (pthread_setaffinity_np(pthread_self(), + sizeof(mask), &mask) < 0) { + perror("pthread_setaffinity fail!\n"); + return NULL; + } + } + +therad_no_affinity: + + dbg("%s entry thread_id=%d\n", __func__, (int)tid); + do { + if (pdata->op_type == WCRYPTO_DEFLATE) { + if (pdata->hw_flag) { + ret = hw_stream_compress(pdata->alg_type, + pdata->blksize, + pdata->dst, + &pdata->dst_len, + pdata->src, + pdata->src_len); + if (ret < 0) + WD_ERR("comp fail! id=%d tid=%d ret=%d\n", + cpu_id, (int)tid, ret); + } + } else if (pdata->op_type == WCRYPTO_INFLATE) { + if (pdata->hw_flag) { + ret = hw_stream_decompress(pdata->alg_type, + pdata->blksize, + pdata->dst, + &pdata->dst_len, + pdata->src, + pdata->src_len); + if (ret < 0) + WD_ERR("decomp fail! id=%d tid=%d ret=%d\n", + cpu_id, (int)tid, ret); + } + } + + if (verify) { + ret = hw_stream_decompress(pdata->alg_type, + pdata->blksize, + pdata->src, + &pdata->src_len, + pdata->dst, + pdata->dst_len); + if (ret < 0) + WD_ERR("loop verify fail! ret=%d, id=%d\n", + ret, cpu_id); + else + dbg("loop verify success! id=%d\n", cpu_id); + } + + } while (--i); + dbg("%s end thread_id=%d\n", __func__, (int)tid); + + return NULL; + +} + +static int out_len; + +void zip_callback(const void *msg, void *tag) +{ + const struct wcrypto_comp_msg *respmsg = msg; + + out_len = respmsg->produced; + + dbg("[%s], cpu_id =%d consume=%d, produce=%d\n", + __func__, ((struct user_comp_tag_info *)tag)->cpu_id, + respmsg->in_cons, respmsg->produced); + +} + +void *zip_sys_async_test_thread(void *args) +{ + int cpu_id, ret; + cpu_set_t mask; + pid_t tid; + struct test_zip_pthread_dt *pdata = args; + struct user_comp_tag_info u_tag; + int i = pdata->iteration; + struct wcrypto_paras *priv; + struct wd_queue *q; + void *zip_ctx; + struct wcrypto_comp_ctx_setup ctx_setup; + struct wd_blkpool_setup blk_setup = { 0 }; + struct wcrypto_comp_op_data *opdata; + int loop; + + cpu_id = pdata->cpu_id; + tid = gettid(); + + CPU_ZERO(&mask); + if (cpu_id) { + if (cpu_id <= 0 || cpu_id > MAX_CORES) { + dbg("set cpu no affinity!\n"); + goto therad_no_affinity; + } + CPU_SET(cpu_id, &mask); + if (pthread_setaffinity_np(pthread_self(), + sizeof(mask), &mask) < 0) { + perror("pthread_setaffinity fail!\n"); + return NULL; + } + } + +therad_no_affinity: + + q = calloc(1, sizeof(struct wd_queue)); + if (!q) { + ret = -ENOMEM; + fprintf(stderr, "alloc q fail, ret =%d\n", ret); + goto hw_q_free; + } + memset(&ctx_setup, 0, sizeof(ctx_setup)); + + switch (pdata->alg_type) { + case 0: + ctx_setup.alg_type = WCRYPTO_ZLIB; + q->capa.alg = "zlib"; + break; + case 1: + ctx_setup.alg_type = WCRYPTO_GZIP; + q->capa.alg = "gzip"; + break; + default: + ctx_setup.alg_type = WCRYPTO_ZLIB; + q->capa.alg = "zlib"; + } + q->capa.latency = 0; + q->capa.throughput = 0; + priv = &q->capa.priv; + priv->direction = pdata->op_type; + priv->is_poll = 1; + ret = wd_request_queue(q); + if (ret) { + fprintf(stderr, "wd_request_queue fail, ret =%d\n", ret); + goto hw_q_free; + } + SYS_ERR_COND(ret, "wd_request_queue"); + + blk_setup.block_size = MAX_DMEMSIZE; + blk_setup.block_num = 3; + blk_setup.align_size = 128; + pdata->pool = wd_blkpool_create(q, &blk_setup); + if (!pdata->pool) { + ret = -ENOMEM; + WD_ERR("%s create pool fail!, ret =%d\n", __func__, ret); + goto release_q; + } + + ctx_setup.br.alloc = (void *)wd_alloc_blk; + ctx_setup.br.free = (void *)wd_free_blk; + ctx_setup.br.iova_map = (void *)wd_blk_iova_map; + ctx_setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + ctx_setup.br.get_bufsize = (void *)wd_blksize; + ctx_setup.win_size = WCRYPTO_COMP_WS_8K; + ctx_setup.br.usr = pdata->pool; + ctx_setup.cb = zip_callback; + ctx_setup.stream_mode = WCRYPTO_COMP_STATELESS; + zip_ctx = wcrypto_create_comp_ctx(q, &ctx_setup); + if (!zip_ctx) { + ret = -ENOMEM; + fprintf(stderr, "zip_alloc_comp_ctx fail, ret =%d\n", ret); + goto blkpool_free; + } + + opdata = calloc(1, sizeof(struct wcrypto_comp_op_data)); + if (!opdata) { + ret = -ENOMEM; + fprintf(stderr, "alloc opdata fail, ret =%d\n", ret); + goto comp_ctx_free; + } + opdata->in = wd_alloc_blk(pdata->pool); + opdata->out = wd_alloc_blk(pdata->pool); + if (!opdata->in || !opdata->out) { + ret = -ENOMEM; + WD_ERR("%s not enough data memory for cache (bs=%d), ret =%d\n", + __func__, block_size, ret); + goto buf_free; + } + opdata->stream_pos = WCRYPTO_COMP_STREAM_NEW; + + memcpy(opdata->in, pdata->src, pdata->src_len); + + opdata->in_len = pdata->src_len; + opdata->avail_out = MAX_DMEMSIZE; + + u_tag.alg_type = ctx_setup.alg_type; + u_tag.cpu_id = cpu_id; + u_tag.tid = tid; + loop = 10; + dbg("%s entry thread_id=%d\n", __func__, (int)tid); + do { + i = pdata->iteration; + do { + ret = wcrypto_do_comp(zip_ctx, opdata, &u_tag); + if (ret == -WD_EBUSY) { + WD_ERR("%s(): asynctest no cache!\n", __func__); + break; + } + + } while (--i); + + ret = wd_wait(q, WD_WAIT_MS); + if(likely(ret > 0)) { + ret = wcrypto_comp_poll(q, pdata->iteration); + if (ret < 0) + WD_ERR("poll fail! thread_id=%d, tid=%d. ret:%d\n", + cpu_id, (int)tid, ret); + } + + } while (--loop); + + opdata->produced = out_len; + dbg("%s(): test !,produce=%d\n", __func__, opdata->produced); + + memcpy(pdata->dst, opdata->out, opdata->produced); + pdata->dst_len = opdata->produced; + + dbg("%s end thread_id=%d\n", __func__, pdata->cpu_id); + + wd_free_blk(pdata->pool, opdata->in); + wd_free_blk(pdata->pool, opdata->out); + free(opdata); + wcrypto_del_comp_ctx(zip_ctx); + wd_blkpool_destroy(pdata->pool); + wd_release_queue(q); + free(q); + + return NULL; + +comp_ctx_free: + wcrypto_del_comp_ctx(zip_ctx); +buf_free: + free(opdata); +blkpool_free: + wd_blkpool_destroy(pdata->pool); +release_q: + wd_release_queue(q); +hw_q_free: + free(q); + + return NULL; +} + +void *zip_sys_block_test_thread(void *args) +{ + int cpu_id, ret; + cpu_set_t mask; + pid_t tid; + struct test_zip_pthread_dt *pdata = args; + int i = pdata->iteration; + + cpu_id = pdata->cpu_id; + tid = gettid(); + + CPU_ZERO(&mask); + if (cpu_id) { + if (cpu_id <= 0 || cpu_id > MAX_CORES) { + dbg("set cpu no affinity!\n"); + goto therad_no_affinity; + } + CPU_SET(cpu_id, &mask); + if (pthread_setaffinity_np(pthread_self(), + sizeof(mask), &mask) < 0) { + perror("pthread_setaffinity fail!\n"); + return NULL; + } + } + +therad_no_affinity: + + dbg("%s entry thread_id=%d\n", __func__, (int)tid); + do { + if (pdata->op_type == WCRYPTO_DEFLATE) { + ret = hw_blk_compress(pdata->alg_type, pdata->blksize, + pdata->dst, &pdata->dst_len, + pdata->src, pdata->src_len); + if (ret < 0) + WD_ERR("comp fail! thread_id=%d, tid=%d\n", + cpu_id, (int)tid); + } else if (pdata->op_type == WCRYPTO_INFLATE) { + ret = hw_blk_decompress(pdata->alg_type, pdata->blksize, + pdata->dst, &pdata->dst_len, + pdata->src, pdata->src_len); + if (ret < 0) + WD_ERR("decomp fail! thread_id=%d, tid=%d\n", + cpu_id, (int)tid); + } + if (verify) { + ret = hw_blk_decompress(pdata->alg_type, pdata->blksize, + pdata->src, &pdata->src_len, + pdata->dst, pdata->dst_len); + if (ret < 0) + WD_ERR("loop verify fail! ret=%d, id=%d\n", + ret, cpu_id); + else + dbg("loop verify success! id=%d\n", cpu_id); + } + } while (--i); + dbg("%s end thread_id=%d\n", __func__, pdata->cpu_id); + + return NULL; +} + +static int hizip_thread_test(FILE *source, FILE *dest, + int thread_num, int alg_type, int op_type, + int mode, int hw_flag, int iteration) +{ + int fd; + struct stat s; + int i, j, ret; + int cnt = 0; + void *file_buf; + int in_len, sz; + float tc = 0; + float speed; + float total_in = 0; + float total_out = 0; + int count = 0; + struct timeval start_tval, end_tval; + + fd = fileno(source); + SYS_ERR_COND(fstat(fd, &s) < 0, "fstat"); + in_len = s.st_size; + SYS_ERR_COND(!in_len, "input file length zero"); + + file_buf = calloc(1, in_len); + + sz = fread(file_buf, 1, in_len, source); + if (sz != in_len) + WD_ERR("read file sz != in_len!\n"); + count = in_len/block_size; + + if (!count) + count = 1; + + dbg("%s entry blocksize=%d, count=%d, threadnum= %d, in_len=%d\n", + __func__, block_size, count, thread_num, in_len); + + cnt = thread_num; + for (i = 0; i < cnt; i++) { + test_thrds_data[i].thread_num = thread_num; + test_thrds_data[i].cpu_id = i; + test_thrds_data[i].alg_type = alg_type; + test_thrds_data[i].op_type = op_type; + test_thrds_data[i].hw_flag = hw_flag; + test_thrds_data[i].blksize = block_size; + test_thrds_data[i].iteration = iteration; + test_thrds_data[i].src = file_buf; + test_thrds_data[i].src_len = in_len; + test_thrds_data[i].dst_len = test_thrds_data[i].src_len * 8; + test_thrds_data[i].src = calloc(1, test_thrds_data[i].src_len); + if (test_thrds_data[i].src == NULL) + goto buf_free; + memcpy(test_thrds_data[i].src, file_buf, in_len); + test_thrds_data[i].dst = calloc(1, test_thrds_data[i].dst_len); + if (test_thrds_data[i].dst == NULL) + goto src_buf_free; + } + + gettimeofday(&start_tval, NULL); + for (i = 0; i < cnt; i++) { + if (mode == MODE_STREAM || hw_flag == 0) + ret = pthread_create(&system_test_thrds[i], NULL, + zlib_sys_stream_test_thread, + &test_thrds_data[i]); + else if (mode == ASYNC) + ret = pthread_create(&system_test_thrds[i], NULL, + zip_sys_async_test_thread, + &test_thrds_data[i]); + else + ret = pthread_create(&system_test_thrds[i], NULL, + zip_sys_block_test_thread, + &test_thrds_data[i]); + if (ret) { + WD_ERR("Create %dth thread fail!\n", i); + return ret; + } + } + + for (i = 0; i < thread_num; i++) { + ret = pthread_join(system_test_thrds[i], NULL); + if (ret) { + WD_ERR("Join %dth thread fail!\n", i); + return ret; + } + } + gettimeofday(&end_tval, NULL); + for (i = 0; i < thread_num; i++) { + total_in += test_thrds_data[i].src_len; + total_out += test_thrds_data[i].dst_len; + } + tc = (float)((end_tval.tv_sec-start_tval.tv_sec) * 1000000 + + end_tval.tv_usec - start_tval.tv_usec); + dbg("%s end threadnum= %d, out_len=%ld\n", + __func__, thread_num, test_thrds_data[thread_num-1].dst_len); + sz = fwrite(test_thrds_data[thread_num-1].dst, 1, + test_thrds_data[thread_num-1].dst_len, dest); + + for (i = 0; i < thread_num; i++) { + free(test_thrds_data[i].src); + free(test_thrds_data[i].dst); + } + if (op_type == WCRYPTO_DEFLATE) { + speed = total_in / tc / + 1024 / 1024 * 1000 * 1000 * iteration, + fprintf(stderr, + "Compress bz=%d, threadnum= %d, speed=%0.3f MB/s, timedelay=%0.1f us\n", + block_size, thread_num, speed, + tc / thread_num / count / iteration); + } else { + speed = total_out / tc / + 1024 / 1024 * 1000 * 1000 * iteration, + fprintf(stderr, + "Decompress bz=%d, threadnum= %d, speed=%0.3f MB/s, timedelay=%0.1f us\n", + block_size, thread_num, speed, + tc / thread_num / count / iteration); + } + + free(file_buf); + + return 0; + +src_buf_free: + free(test_thrds_data[i].src); + +buf_free: + for (j = 0; j < i; j++) { + free(test_thrds_data[i].src); + free(test_thrds_data[i].dst); + } + + free(file_buf); + + WD_ERR("thread malloc fail!ENOMEM!\n"); + + return -ENOMEM; +} + +int main(int argc, char *argv[]) +{ + int alg_type = WCRYPTO_GZIP; + int op_type = WCRYPTO_DEFLATE; + int opt; + int show_help = 0; + int thread_num = 1; + int mode = 0; + int hw_flag = 1; + int iteration = 1; + + while ((opt = getopt(argc, argv, "zghq:ab:dvc:kmsp:i:")) != -1) { + switch (opt) { + case 'z': + alg_type = WCRYPTO_ZLIB; + break; + case 'g': + alg_type = WCRYPTO_GZIP; + break; + case 'q': + q_num = atoi(optarg); + if (q_num <= 0) + show_help = 1; + break; + case 'b': + block_size = atoi(optarg); + if (block_size <= 0) + show_help = 1; + else if (block_size > 1024 * 1024) + SYS_ERR_COND(1, "blocksize > 1M!\n"); + break; + case 'c': + req_cache_num = atoi(optarg); + if (req_cache_num <= 0) + show_help = 1; + break; + case 'd': + op_type = WCRYPTO_INFLATE; + break; + case 'k': + mode = MODE_BLOCK; + break; + case 'm': + mode = MODE_STREAM; + break; + case 'a': + mode = ASYNC; + break; + case 'p': + thread_num = atoi(optarg); + if (thread_num > TEST_MAX_THRD) + SYS_ERR_COND(1, "thread_num > 2048!\n"); + break; + case 's': + hw_flag = 0; + break; + case 'v': + verify = 1; + break; + case 'i': + iteration = atoi(optarg); + if (iteration <= 0) + show_help = 1; + break; + default: + show_help = 1; + break; + } + } + + SYS_ERR_COND(show_help || optind > argc, + "version 1.00:wd_test_zip -[k/m/s] -[g|z] -d [-b block][-p thread_num] [-i iteration] < in > out"); + + (void)hizip_thread_test(stdin, stdout, thread_num, alg_type, + op_type, mode, hw_flag, iteration); + + return EXIT_SUCCESS; +} diff --git a/uadk/v1/test/hisi_zip_test/wd_zip_test_1630.c b/uadk/v1/test/hisi_zip_test/wd_zip_test_1630.c new file mode 100644 index 0000000..ee06362 --- /dev/null +++ b/uadk/v1/test/hisi_zip_test/wd_zip_test_1630.c @@ -0,0 +1,1106 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ +#include +#include +#include +#define __USE_GNU +#include +#include +#include +#include +#include +#include + +#include "v1/drv/hisi_qm_udrv.h" +#include "v1/wd.h" +#include "v1/wd_bmm.h" +#include "v1/wd_comp.h" +#include "v1/wd_util.h" + +typedef unsigned int u32; +typedef unsigned char u8; + +enum mode { + MODE_BLOCK, + MODE_STREAM, + MODE_ASYNC, +}; + +struct zip_test_pthread_dt { + int thread_id; + int thread_num; + int alg_type; + int op_type; + int data_fmt; + int iteration; + void *src; + void *dst; + ulong src_len; + ulong dst_len; + float com_time; + float decom_time; + void *pool; + struct wcrypto_comp_ctx *ctx; + struct wcrypto_comp_op_data *opdata; +}; + +struct user_comp_tag_info { + int alg_type; + int op_type; + int tag; +}; + +struct seq_def { + __u32 offset; + __u16 litlen; + __u16 matlen; +}; + + +struct zip_test_config { + int window_sz; + int block_sz; + int thread_num; + int cylcls; + + char alg_mode[10]; /* zlib/gzip/deflate/lz77 */ + char op[10]; /* deflate/inflate */ + char mode[10]; /* block/stream/async */ + char data_fmt[10]; /* pbuffer/sgl */ +}; + +#define HZIP_ZLIB_HEAD_SIZE 2 +#define HZIP_GZIP_HEAD_SIZE 10 + +#define TEST_MAX_THRD 2048UL +#define MAX_CORES 128 +#define DMEMSIZE (1024 * 4) /* 4K */ + +#define MAX(a, b) ((a) > (b) ? (a) : (b)) + +#define SYS_ERR_COND(cond, msg, ...) \ +do { \ + if (cond) { \ + if (errno) \ + perror(msg); \ + else \ + fprintf(stderr, msg, ##__VA_ARGS__); \ + exit(EXIT_FAILURE); \ + } \ +} while (0) + +static struct zip_test_pthread_dt test_thrds_data[TEST_MAX_THRD]; +static pthread_t system_test_thrds[TEST_MAX_THRD]; +static struct wd_queue q[TEST_MAX_THRD]; + +/* bytes of data for a request */ +static int block_size = 1024 * 1024; +static int thread_num = 1; +static int q_num = 1; + +static const unsigned char zlib_head[HZIP_ZLIB_HEAD_SIZE] = {0x78, 0x9c}; +static const unsigned char gzip_head[HZIP_GZIP_HEAD_SIZE] = { + 0x1f, 0x8b, 0x08, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x03 +}; + +#define TO_HEAD_SIZE(req_type) \ + (((req_type) == WCRYPTO_ZLIB) ? sizeof(zlib_head) : \ + ((req_type) == WCRYPTO_GZIP) ? sizeof(gzip_head) : 0) + +#define TO_HEAD(req_type) \ + (((req_type) == WCRYPTO_ZLIB) ? zlib_head : \ + ((req_type) == WCRYPTO_GZIP) ? gzip_head : NULL) + +static void zip_test_callback(const void *msg, void *tag) +{ + const struct wcrypto_comp_msg *respmsg = msg; + const struct user_comp_tag_info *utag = tag; + int i = utag->tag; + struct zip_test_pthread_dt *pdata = &test_thrds_data[i]; + const u8 *head = TO_HEAD(pdata->alg_type); + struct wcrypto_zstd_out *zstd_out; + int head_size = 0; + + + dbg("%s start!\n", __func__); + + pdata->dst_len = respmsg->produced; + + if (pdata->op_type == WCRYPTO_DEFLATE) { + head_size = TO_HEAD_SIZE(pdata->alg_type); + memcpy(pdata->dst, head, head_size); + pdata->dst_len += head_size; + } + if (pdata->data_fmt == WD_FLAT_BUF) { + memcpy(pdata->dst + head_size, pdata->opdata->out, respmsg->produced); + } else { + if (pdata->alg_type == WCRYPTO_LZ77_ZSTD) { + zstd_out = (void *)pdata->opdata->out; + + wd_sgl_cp_to_pbuf((struct wd_sgl *)zstd_out->sequence, 0, + pdata->dst + head_size, respmsg->produced); + } else { + wd_sgl_cp_to_pbuf((struct wd_sgl *)pdata->opdata->out, 0, + pdata->dst + head_size, respmsg->produced); + } + } + + dbg("%s succeed!\n", __func__); +} + +static void *zip_test_async_poll_thread(void *args) +{ + int *cnt = calloc(1, sizeof(int) * q_num); + struct zip_test_pthread_dt *pdata = args; + int iter = pdata->iteration; + int workq_num = q_num; + int ret, i; + + dbg("%s start!\n", __func__); + + for (i = 0; i < q_num; i++) + cnt[i] = iter; + + do { + for (i = 0; i < q_num; i++) { + if (!cnt[i]) + continue; + ret = wcrypto_comp_poll(&q[i], cnt[i]); + if (ret < 0) { + WD_ERR("poll fail! thread_id=%d, ret:%d\n", + pdata->thread_id, ret); + break; + } + cnt[i] -= ret; + if (!cnt[i]) + workq_num--; + } + } while (workq_num); + + dbg("%s succeed!\n", __func__); + + return NULL; +} + +static void *zip_test_async_thread(void *args) +{ + struct zip_test_pthread_dt *pdata = args; + struct user_comp_tag_info *utag; + int i = pdata->iteration; + int ret; + + dbg("%s start!\n", __func__); + + utag = calloc(1, sizeof(struct user_comp_tag_info)); + utag->alg_type = pdata->alg_type; + utag->op_type = pdata->op_type; + utag->tag = pdata->thread_id; + + if (pdata->data_fmt == WD_FLAT_BUF) { + memcpy(pdata->opdata->in, pdata->src, pdata->src_len); + pdata->opdata->avail_out = block_size; + } else { + wd_sgl_cp_from_pbuf((struct wd_sgl *)pdata->opdata->in, 0, + pdata->src, pdata->src_len); + pdata->opdata->avail_out = pdata->dst_len; + } + + pdata->opdata->in_len = pdata->src_len; + + do { + ret = wcrypto_do_comp(pdata->ctx, pdata->opdata, utag); + if (ret == -WD_EBUSY) + i++; + else if (ret != 0) + return NULL; + } while (--i); + + dbg("%s succeed!\n", __func__); + + return NULL; +} + +static void *zip_test_stream_thread(void *args) +{ + struct zip_test_pthread_dt *pdata = args; + struct wcrypto_comp_op_data *opdata = pdata->opdata; + unsigned char *src = pdata->src; + unsigned char *dst = pdata->dst; + unsigned char *ori = opdata->in; + int alg_type = pdata->alg_type; + const u8 *head = TO_HEAD(alg_type); + int srclen = pdata->src_len; + int head_size = 0; + int ret, have; + + dbg("%s start!\n", __func__); + + pdata->dst_len = 0; + + if (pdata->op_type == WCRYPTO_DEFLATE) { + head_size = TO_HEAD_SIZE(alg_type); + memcpy(dst, head, head_size); + pdata->dst_len += head_size; + dst += head_size; + } + + do { + opdata->in = ori; + if (srclen > block_size) { + memcpy(pdata->opdata->in, src, block_size); + opdata->in_len = block_size; + src += block_size; + srclen -= block_size; + } else { + memcpy(pdata->opdata->in, src, srclen); + opdata->in_len = srclen; + srclen = 0; + } + opdata->flush = srclen ? WCRYPTO_SYNC_FLUSH : WCRYPTO_FINISH; + do { + opdata->avail_out = block_size; + ret = wcrypto_do_comp(pdata->ctx, opdata, NULL); + if (ret) { + WD_ERR("%s failed to do request! ret = %d\n", + __func__, ret); + return NULL; + } + + opdata->stream_pos = WCRYPTO_COMP_STREAM_OLD; + have = opdata->produced; + memcpy(dst, opdata->out, have); + dst += have; + pdata->dst_len += have; + opdata->in_len -= opdata->consumed; + if (opdata->in_len) { + dbg("%s avail out no enough!\n", __func__); + opdata->in += opdata->consumed; + } + } while (opdata->in_len > 0); + } while (srclen); + + dbg("%s succeed!\n", __func__); + + return NULL; +} + +static void *zip_test_block_thread(void *args) +{ + struct zip_test_pthread_dt *pdata = args; + int alg_type = pdata->alg_type; + const u8 *head = TO_HEAD(alg_type); + struct wcrypto_zstd_out *zstd_out; + int i = pdata->iteration; + int head_size = 0; + int ret; + + dbg("%s start!\n", __func__); + + if (pdata->data_fmt == WD_FLAT_BUF) { + memcpy(pdata->opdata->in, pdata->src, pdata->src_len); + pdata->opdata->avail_out = block_size; + } else { + wd_sgl_cp_from_pbuf((struct wd_sgl *)pdata->opdata->in, 0, + pdata->src, pdata->src_len); + pdata->opdata->avail_out = pdata->dst_len; + } + + pdata->opdata->in_len = pdata->src_len; + + do { + ret = wcrypto_do_comp(pdata->ctx, pdata->opdata, NULL); + if (ret) { + WD_ERR("%s failed to do request! ret = %d\n", + __func__, ret); + return NULL; + } + + pdata->dst_len = pdata->opdata->produced; + + if (pdata->op_type == WCRYPTO_DEFLATE) { + head_size = TO_HEAD_SIZE(alg_type); + memcpy(pdata->dst, head, head_size); + pdata->dst_len += head_size; + } + if (pdata->data_fmt == WD_FLAT_BUF) { + memcpy(pdata->dst + head_size, pdata->opdata->out, pdata->opdata->produced); + } else { + if (pdata->alg_type == WCRYPTO_LZ77_ZSTD) { + zstd_out = (void *)pdata->opdata->out; + + wd_sgl_cp_to_pbuf((struct wd_sgl *)zstd_out->sequence, 0, + pdata->dst + head_size, pdata->opdata->produced); + } else { + wd_sgl_cp_to_pbuf((struct wd_sgl *)pdata->opdata->out, 0, + pdata->dst + head_size, pdata->opdata->produced); + } + + } + + } while (--i); + + dbg("%s succeed!\n", __func__); + + return NULL; +} + +static void zip_test_release_q(int n) +{ + int i; + + dbg("%s start!\n", __func__); + + for (i = 0; i < n; i++) + wd_release_queue(&q[i]); + + dbg("%s succeed!\n", __func__); +} + +static int zip_test_request_q(int alg_type, int op_type) +{ + struct wcrypto_paras *priv; + int ret = 0; + int i; + + dbg("%s start!\n", __func__); + + q_num = thread_num; + + for (i = 0; i < q_num; i++) { + switch (alg_type) { + case WCRYPTO_ZLIB: + q[i].capa.alg = "zlib"; + break; + case WCRYPTO_GZIP: + q[i].capa.alg = "gzip"; + break; + case WCRYPTO_RAW_DEFLATE: + q[i].capa.alg = "deflate"; + break; + case WCRYPTO_LZ77_ZSTD: + q[i].capa.alg = "lz77_zstd"; + break; + default: + q[i].capa.alg = "zlib"; + break; + } + q[i].capa.latency = 0; + q[i].capa.throughput = 0; + priv = &q[i].capa.priv; + priv->direction = op_type; + ret = wd_request_queue(&q[i]); + if (ret) { + WD_ERR("%s request %dth q fail, ret =%d\n", + __func__, i, ret); + zip_test_release_q(i); + } + } + + dbg("%s succeed!\n", __func__); + + return ret; +} + +#define SGL_BUF_SZ_MIN 2048 +#define SGL_ALIGN_SZ 64 +#define SGE_NUM_IN_SGL 40 +#define SGL_NUM 6 +static int zip_test_create_ctx(int alg_type, int window_size, + int op_type, int mode) +{ + struct wcrypto_comp_ctx_setup ctx_setup = { 0 }; + struct wd_blkpool_setup blk_setup = { 0 }; + struct wd_sglpool_setup sp = { 0 }; + struct zip_test_pthread_dt *pdata = &test_thrds_data[0]; + struct wcrypto_zstd_out zstd_out = { 0 }; + int i, j, ret, data_fmt; + + dbg("%s start!\n", __func__); + + data_fmt = pdata->data_fmt; + + ctx_setup.alg_type = alg_type; + ctx_setup.op_type = op_type; + ctx_setup.stream_mode = (mode == MODE_STREAM) ? + WCRYPTO_COMP_STATEFUL : + WCRYPTO_COMP_STATELESS; + ctx_setup.cb = (mode == MODE_ASYNC) ? zip_test_callback : NULL; + ctx_setup.win_size = window_size; + + if (data_fmt == WD_SGL_BUF) { + ctx_setup.data_fmt = WD_SGL_BUF; + + sp.buf_size = MAX(pdata->src_len / 6, SGL_BUF_SZ_MIN); + sp.align_size = SGL_ALIGN_SZ; + sp.sge_num_in_sgl = SGE_NUM_IN_SGL; + sp.buf_num_in_sgl = sp.sge_num_in_sgl - 1; + sp.sgl_num = SGL_NUM; + sp.buf_num = sp.buf_num_in_sgl * sp.sgl_num + sp.sgl_num + 2; + + ctx_setup.br.alloc = (void *)wd_alloc_sgl; + ctx_setup.br.free = (void *)wd_free_sgl; + ctx_setup.br.iova_map = (void *)wd_sgl_iova_map; + ctx_setup.br.iova_unmap = (void *)wd_sgl_iova_unmap; + } else { + ctx_setup.data_fmt = WD_FLAT_BUF; + + block_size = MAX(block_size, DMEMSIZE); + blk_setup.block_size = block_size; + blk_setup.block_num = 3; + blk_setup.align_size = 128; + + ctx_setup.br.alloc = (void *)wd_alloc_blk; + ctx_setup.br.free = (void *)wd_free_blk; + ctx_setup.br.iova_map = (void *)wd_blk_iova_map; + ctx_setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + ctx_setup.br.get_bufsize = (void *)wd_blksize; + } + + for (i = 0; i < thread_num; i++) { + pdata = &test_thrds_data[i]; + ctx_setup.data_fmt = pdata->data_fmt; + + if (pdata->data_fmt == WD_SGL_BUF) // sgl + pdata->pool = wd_sglpool_create(q, &sp); + else // pbuf + pdata->pool = wd_blkpool_create(&q[i], &blk_setup); + + if (!pdata->pool) { + ret = -ENOMEM; + WD_ERR("%s - data_fmt = %d, create %dth pool fail!\n", __func__, data_fmt, i); + goto err_pool_destory; + } + + ctx_setup.br.usr = pdata->pool; + ctx_setup.data_fmt = pdata->data_fmt; + pdata->ctx = wcrypto_create_comp_ctx(&q[i], &ctx_setup); + if (!pdata->ctx) { + ret = -ENOMEM; + WD_ERR("%s create %dth ctx fail!\n", __func__, i); + goto err_ctx_delete; + } + + pdata->opdata = calloc(1, sizeof(*pdata->opdata)); + if (!pdata->opdata) { + ret = -ENOMEM; + WD_ERR("%s alloc %dth opdata fail!\n", __func__, i); + goto err_opdata_free; + } + + pdata->opdata->alg_type = alg_type; + pdata->opdata->avail_out = (pdata->data_fmt == WD_SGL_BUF) ? pdata->dst_len : block_size; + pdata->opdata->stream_pos = WCRYPTO_COMP_STREAM_NEW; + if (pdata->data_fmt == WD_SGL_BUF) { // sgl + pdata->opdata->in = (void *)wd_alloc_sgl(pdata->pool, test_thrds_data[i].src_len); + pdata->opdata->out = (void *)wd_alloc_sgl(pdata->pool, test_thrds_data[i].dst_len); + } else { + pdata->opdata->in = wd_alloc_blk(pdata->pool); + pdata->opdata->out = wd_alloc_blk(pdata->pool); + } + if (!pdata->opdata->in || !pdata->opdata->out) { + ret = -ENOMEM; + WD_ERR("%s not enough data memory for cache (bs=%d)\n", + __func__, block_size); + goto err_buffer_free; + } + + if (pdata->alg_type == WCRYPTO_LZ77_ZSTD) { + pdata->opdata->priv = calloc(1, sizeof(struct wcrypto_lz77_zstd_format)); + if (!pdata->opdata->priv) { + WD_ERR("%s alloc %d format fail!\n", __func__, i); + goto err_format_free; + } + + /* when use sgl zstd_lz77, we use 'struct wcrypto_zstd_out' + * as out, which include addresses of 'literals' and 'sequence'. + */ + if (pdata->data_fmt == WD_SGL_BUF) { + zstd_out.literal = (void *)wd_alloc_sgl(pdata->pool, + test_thrds_data[i].dst_len); + if (!zstd_out.literal) { + WD_ERR("alloc for literals failed.\n"); + goto err_format_free; + } + + zstd_out.lit_sz = pdata->dst_len; + zstd_out.sequence = pdata->opdata->out; + zstd_out.seq_sz = pdata->dst_len; + pdata->opdata->out = (void *)&zstd_out; + } + } + } + + dbg("%s succeed!\n", __func__); + + return 0; + +err_format_free: + if (pdata->data_fmt == WD_SGL_BUF) { + wd_free_sgl(test_thrds_data[i].pool, + (struct wd_sgl *)test_thrds_data[i].opdata->in); + if (pdata->alg_type == WCRYPTO_LZ77_ZSTD) { + wd_free_sgl(test_thrds_data[i].pool, + (struct wd_sgl *)zstd_out.literal); + wd_free_sgl(test_thrds_data[i].pool, + (struct wd_sgl *)zstd_out.sequence); + } else { + wd_free_sgl(test_thrds_data[i].pool, + (struct wd_sgl *)test_thrds_data[i].opdata->out); + } + } else { + wd_free_blk(test_thrds_data[i].pool, + test_thrds_data[i].opdata->in); + wd_free_blk(test_thrds_data[i].pool, + test_thrds_data[i].opdata->out); + } + +err_buffer_free: + free(test_thrds_data[i].opdata); + +err_opdata_free: + wcrypto_del_comp_ctx(test_thrds_data[i].ctx); + +err_ctx_delete: + if (pdata->data_fmt == WD_SGL_BUF) + wd_sglpool_destroy(test_thrds_data[i].pool); + else + wd_blkpool_destroy(test_thrds_data[i].pool); + +err_pool_destory: + if (pdata->data_fmt == WD_SGL_BUF) { + for (j = 0; j < i; j++) { + wd_free_sgl(test_thrds_data[j].pool, + (struct wd_sgl *)test_thrds_data[j].opdata->in); + wd_free_sgl(test_thrds_data[j].pool, + (struct wd_sgl *)test_thrds_data[j].opdata->out); + wcrypto_del_comp_ctx(test_thrds_data[j].ctx); + wd_sglpool_destroy(test_thrds_data[j].pool); + free(test_thrds_data[j].opdata); + } + } else { + for (j = 0; j < i; j++) { + wd_free_blk(test_thrds_data[j].pool, + test_thrds_data[j].opdata->in); + wd_free_blk(test_thrds_data[j].pool, + test_thrds_data[j].opdata->out); + wcrypto_del_comp_ctx(test_thrds_data[j].ctx); + wd_blkpool_destroy(test_thrds_data[j].pool); + free(test_thrds_data[j].opdata); + } + } + + return ret; +} + +static int zip_test_init(int alg_type, int window_size, int op_type, int mode) +{ + int ret; + + dbg("%s start!\n", __func__); + + ret = zip_test_request_q(alg_type, op_type); + if (ret) { + WD_ERR("%s request q failed!\n", __func__); + return ret; + } + + ret = zip_test_create_ctx(alg_type, window_size, op_type, mode); + if (ret) { + WD_ERR("%s create ctx failed!\n", __func__); + zip_test_release_q(q_num); + } + + dbg("%s succeed!\n", __func__); + + return ret; +} + +static void zip_test_exit(void) +{ + struct wcrypto_zstd_out *zstd_out; + int i; + + if (test_thrds_data[0].data_fmt == WD_SGL_BUF) { + for (i = 0; i < thread_num; i++) { + wd_free_sgl(test_thrds_data[i].pool, + (struct wd_sgl *)test_thrds_data[i].opdata->in); + + if (test_thrds_data[i].alg_type == WCRYPTO_LZ77_ZSTD) { + zstd_out = (void *)test_thrds_data[i].opdata->out; + wd_free_sgl(test_thrds_data[i].pool, + (struct wd_sgl *)zstd_out->literal); + wd_free_sgl(test_thrds_data[i].pool, + (struct wd_sgl *)zstd_out->sequence); + free(test_thrds_data[i].opdata->priv); + } else { + wd_free_sgl(test_thrds_data[i].pool, + (struct wd_sgl *)test_thrds_data[i].opdata->out); + } + wcrypto_del_comp_ctx(test_thrds_data[i].ctx); + wd_sglpool_destroy(test_thrds_data[i].pool); + free(test_thrds_data[i].opdata); + } + } else { + for (i = 0; i < thread_num; i++) { + wd_free_blk(test_thrds_data[i].pool, + test_thrds_data[i].opdata->in); + wd_free_blk(test_thrds_data[i].pool, + test_thrds_data[i].opdata->out); + if (test_thrds_data[i].alg_type == WCRYPTO_LZ77_ZSTD) + free(test_thrds_data[i].opdata->priv); + wcrypto_del_comp_ctx(test_thrds_data[i].ctx); + wd_blkpool_destroy(test_thrds_data[i].pool); + free(test_thrds_data[i].opdata); + } + } + + zip_test_release_q(q_num); +} + +static void dump_lz77_zstd_format(struct wcrypto_lz77_zstd_format *format) +{ +#ifdef DEBUG_LOG + + struct seq_def *seq; + int i; + + dbg("%s start!\n", __func__); + + dbg("%s literals number: %u\n", __func__, format->lit_num); + + dbg("%s sequences number: %u\n", __func__, format->seq_num); + + dbg("%s overflow cnt: %u\n", __func__, format->lit_length_overflow_cnt); + + dbg("%s overflow pos: %u\n", __func__, format->lit_length_overflow_pos); + + dbg("%s succeed!\n", __func__); + +#endif +} + +static int write_zstd_file(struct wcrypto_lz77_zstd_format *output_format, int data_fmt) +{ + struct wcrypto_lz77_zstd_format *format = output_format; + __u8 *literal = malloc(format->lit_num * sizeof(__u8)); + __u64 *sequence = malloc(format->seq_num * sizeof(__u64)); + int write_size = 0; + FILE *fout; + int ret; + + dbg("%s start!\n", __func__); + + dump_lz77_zstd_format(format); + fout = fopen("./zstd_lz77", "wb+"); + if (fout == NULL) { + WD_ERR("file open failed\n"); + return -1; + } + + ret = fwrite(&format->lit_length_overflow_cnt, sizeof(__u32), 1, fout); + write_size += ret * sizeof(__u32); + + ret = fwrite(&format->lit_length_overflow_pos, sizeof(__u32), 1, fout); + write_size += ret * sizeof(__u32); + + ret = fwrite(&format->lit_num, sizeof(__u32), 1, fout); + write_size += ret * sizeof(__u32); + + if (data_fmt == WD_SGL_BUF) { + memset(literal, 0, sizeof(__u8)); + ret = wd_sgl_cp_to_pbuf((struct wd_sgl *)format->literals_start, 0, literal, format->lit_num); + WD_ERR("format->lit_num = %u, ret = %u\n", format->lit_num, ret); + ret = fwrite(literal, sizeof(__u8), format->lit_num, fout); + } else { + ret = fwrite(format->literals_start, sizeof(__u8), format->lit_num, fout); + } + + write_size += ret * sizeof(__u8); + + ret = fwrite(&format->seq_num, sizeof(__u32), 1, fout); + write_size += ret * sizeof(__u32); + + if (data_fmt == WD_SGL_BUF) { + memset(sequence, 0, sizeof(__u64)); + ret = wd_sgl_cp_to_pbuf((struct wd_sgl *)format->sequences_start, 0, sequence, format->seq_num * sizeof(__u64)); + WD_ERR("format->seq_num = %u, ret = %u\n", format->seq_num, ret); + ret = fwrite(sequence, sizeof(__u64), format->seq_num, fout); + } else { + ret = fwrite(format->sequences_start, sizeof(__u64), format->seq_num, fout); + } + write_size += ret * sizeof(__u64); + + dbg("write size is %d\n", write_size); + + fclose(fout); + + dbg("%s succeed!\n", __func__); + + free(literal); + free(sequence); + + return write_size; +} + +static int hizip_thread_test(FILE *source, FILE *dest, int alg_type, int mode, + int op_type, int window_size, int data_fmt, int iteration) +{ + struct timeval start_tval, end_tval; + struct zip_test_pthread_dt *pdata; + int in_len, sz, fd; + float total_in = 0; + float total_out = 0; + int head_size = 0; + void *file_buf; + struct stat s; + int i, j, ret; + float tc = 0; + float speed; + + fd = fileno(source); + SYS_ERR_COND(fstat(fd, &s) < 0, "%s fstat error!\n", __func__); + in_len = s.st_size; + SYS_ERR_COND(!in_len, "%s input file length zero!\n", __func__); + + file_buf = calloc(1, in_len); + + sz = fread(file_buf, 1, in_len, source); + if (sz != in_len) + WD_ERR("%s read file sz != in_len!\n", __func__); + + if (op_type == WCRYPTO_INFLATE) + head_size = TO_HEAD_SIZE(alg_type); + + dbg("%s entry threadnum= %d, in_len=%d\n", + __func__, thread_num, in_len); + + for (i = 0; i < thread_num; i++) { + pdata = &test_thrds_data[i]; + pdata->thread_id = i; + pdata->thread_num = thread_num; + pdata->alg_type = alg_type; + pdata->op_type = op_type; + pdata->data_fmt = data_fmt; + pdata->iteration = iteration; + pdata->src = file_buf; + pdata->src_len = in_len - head_size; + pdata->dst_len = pdata->src_len * 10; + pdata->src = calloc(1, pdata->src_len); + if (pdata->src == NULL) + goto buf_free; + memcpy(pdata->src, (unsigned char *)file_buf + head_size, + pdata->src_len); + pdata->dst = calloc(1, pdata->dst_len); + if (pdata->dst == NULL) + goto src_buf_free; + } + + ret = zip_test_init(alg_type, window_size, op_type, mode); + if (ret) { + WD_ERR("%s init fail!\n", __func__); + goto all_buf_free; + } + + gettimeofday(&start_tval, NULL); + for (i = 0; i < thread_num; i++) { + if (mode == MODE_ASYNC) + ret = pthread_create(&system_test_thrds[i], NULL, + zip_test_async_thread, + &test_thrds_data[i]); + else if (mode == MODE_STREAM) + ret = pthread_create(&system_test_thrds[i], NULL, + zip_test_stream_thread, + &test_thrds_data[i]); + else + ret = pthread_create(&system_test_thrds[i], NULL, + zip_test_block_thread, + &test_thrds_data[i]); + if (ret) { + WD_ERR("%s create %dth thread fail!\n", __func__, i); + goto all_buf_free; + } + } + + if (mode == MODE_ASYNC) { + ret = pthread_create(&system_test_thrds[thread_num], NULL, + zip_test_async_poll_thread, + &test_thrds_data[0]); + if (ret) { + WD_ERR("%s create poll thread fail!\n", __func__); + goto all_buf_free; + } + } + + for (i = 0; i < thread_num; i++) { + ret = pthread_join(system_test_thrds[i], NULL); + if (ret) { + WD_ERR("%s join %dth thread fail!\n", __func__, i); + goto all_buf_free; + } + } + + if (mode == MODE_ASYNC) { + ret = pthread_join(system_test_thrds[thread_num], NULL); + if (ret) { + WD_ERR("%s join poll thread fail!\n", __func__); + goto all_buf_free; + } + } + gettimeofday(&end_tval, NULL); + + + for (i = 0; i < thread_num; i++) { + total_in += test_thrds_data[i].src_len; + total_out += test_thrds_data[i].dst_len; + } + + tc = (float)((end_tval.tv_sec - start_tval.tv_sec) * 1000000 + + end_tval.tv_usec - start_tval.tv_usec); + + dbg("%s end threadnum= %d, out_len=%ld\n", + __func__, thread_num, test_thrds_data[thread_num-1].dst_len); + + if (alg_type == WCRYPTO_LZ77_ZSTD) + sz = write_zstd_file(test_thrds_data[thread_num-1].opdata->priv, data_fmt); + else + sz = fwrite(test_thrds_data[thread_num-1].dst, 1, + test_thrds_data[thread_num-1].dst_len, dest); + + if (op_type == WCRYPTO_DEFLATE) { + speed = total_in / tc / 1024 / 1024 * + 1000 * 1000 * iteration, + fprintf(stderr, + "Compress threadnum= %d, speed=%0.3f MB/s, timedelay=%0.1f us\n", + thread_num, speed, tc / thread_num / iteration); + } else { + speed = total_out / tc / 1024 / 1024 * + 1000 * 1000 * iteration, + fprintf(stderr, + "Decompress threadnum= %d, speed=%0.3f MB/s, timedelay=%0.1f us\n", + thread_num, speed, tc / thread_num / iteration); + } + + zip_test_exit(); + +all_buf_free: + for (i = 0; i < thread_num; i++) { + free(test_thrds_data[i].src); + free(test_thrds_data[i].dst); + } + + free(file_buf); + + return ret; + +src_buf_free: + free(test_thrds_data[i].src); + +buf_free: + for (j = 0; j < i; j++) { + free(test_thrds_data[i].src); + free(test_thrds_data[i].dst); + } + + free(file_buf); + + WD_ERR("%s thread malloc fail!ENOMEM!\n", __func__); + + return -ENOMEM; +} + +static void print_help(void) +{ + fprintf(stderr, "UPDATE:2021-02-01\n"); + fprintf(stderr, "NAME\n"); + fprintf(stderr, " wd_zip_test_1630: test wd zip function on Kunpeng930, etc\n"); + fprintf(stderr, "USAGE\n"); + fprintf(stderr, " wd_zip_test_1630 [--alg_mode=] [--op=] [--mode=] [--data_fmt=] [--cylcls=]\n"); + fprintf(stderr, " wd_zip_test_1630 [--window_sz=] [--block_sz=] [--thread_num=] [--help] \n"); + + fprintf(stderr, "\nDESCRIPTION\n"); + fprintf(stderr, " [--alg_mode=]:\n"); + fprintf(stderr, " zlib/gzip/deflate/lz77\n"); + + fprintf(stderr, " [--op]: inflate/deflate\n"); + fprintf(stderr, " [--mode=]: block/stream/async\n"); + + fprintf(stderr, " [--data_fmt=]: pbuffer/sgl\n"); + + fprintf(stderr, " [--window_sz=]: window size\n"); + + fprintf(stderr, " [--block_sz=]: block size\n"); + + fprintf(stderr, " [--cycles=]: test cycle set (times)\n"); + + fprintf(stderr, " [--help] = usage\n"); +} + + +static int parse_cmd_line(int argc, char *argv[], struct zip_test_config *g_config) +{ + int option_index = 0; + int optind_t; + int ret = 0; + int c; + + static struct option long_options[] = { + {"window_sz", required_argument, 0, 0 }, + {"block_sz", required_argument, 0, 0 }, + {"thread_num", required_argument, 0, 0 }, + {"cylcls", required_argument, 0, 0 }, + {"alg_mode", required_argument, 0, 0}, + {"op", required_argument, 0, 0 }, + {"mode", required_argument, 0, 0 }, + {"data_fmt", required_argument, 0, 0 }, + {"help", no_argument, 0, 'h' }, + {0, 0, 0, 0 } + }; + + + while (1) { + optind_t = optind ? optind: 1; + + c = getopt_long(argc, argv, "t:c:", long_options, &option_index); + if (c == -1) { + if (optind_t < argc) { + print_help(); + ret = -1; + } + break; + } + switch (c) { + case 0: + if (!strncmp(long_options[option_index].name, "window_sz", 9)) { + g_config->window_sz = strtoul((char *)optarg, NULL, 10); + } else if (!strncmp(long_options[option_index].name, "block_sz", 8)) { + g_config->block_sz = strtoul((char *)optarg, NULL, 10); + } else if (!strncmp(long_options[option_index].name, "thread_num", 9)) { + g_config->thread_num = strtoul((char *)optarg, NULL, 10); + } else if (!strncmp(long_options[option_index].name, "cylcls", 6)) { + g_config->cylcls = strtoul((char *)optarg, NULL, 10); + } else if (!strncmp(long_options[option_index].name, "alg_mode", 8)) { + snprintf(g_config->alg_mode, sizeof(g_config->alg_mode), "%s", optarg); + } else if (!strncmp(long_options[option_index].name, "op", 2)) { + snprintf(g_config->op, sizeof(g_config->op), "%s", optarg); + } else if (!strncmp(long_options[option_index].name, "mode", 4)) { + snprintf(g_config->mode, sizeof(g_config->mode), "%s", optarg); + } else if (!strncmp(long_options[option_index].name, "data_fmt", 8)) { + snprintf(g_config->data_fmt, sizeof(g_config->data_fmt), "%s", optarg); + } + break; + case '?': + case 'h': + print_help(); + ret = -1; + break; + + default: + printf("?? getopt returned character code 0%o ??\n", c); + break; + } + } + + return ret; +} + +int main(int argc, char *argv[]) +{ + int op_type = WCRYPTO_DEFLATE; + int alg_type = WCRYPTO_GZIP; + int mode = MODE_BLOCK; + /* data_fmt: 0 - pbuffer, 1 - sgl. */ + bool data_fmt = 0; + int ret = 0; + + struct zip_test_config g_config = { + .window_sz = WCRYPTO_COMP_WS_8K, + .block_sz = 1048576, // 1024 * 1024, + .thread_num = 1, + .cylcls = 1, + + .alg_mode = "gzip", + .op = "deflate", + .mode = "block", + .data_fmt = "pbuffer", + }; + + ret = parse_cmd_line(argc, argv, &g_config); + if (ret) + return -1; + + if (!strcmp(g_config.alg_mode, "zlib")) + alg_type = WCRYPTO_ZLIB; + else if (!strcmp(g_config.alg_mode, "gzip")) + alg_type = WCRYPTO_GZIP; + else if (!strcmp(g_config.alg_mode, "deflate")) + alg_type = WCRYPTO_RAW_DEFLATE; + else if (!strcmp(g_config.alg_mode, "lz77")) + alg_type = WCRYPTO_LZ77_ZSTD; + else { + fprintf(stderr, "alg_type error, set alg_type = 'gzip'!\n"); + alg_type = WCRYPTO_GZIP; + } + + if (!strcmp(g_config.op, "inflate")) { + op_type = WCRYPTO_INFLATE; + fprintf(stderr,"inflate option!\n"); + } else { + op_type = WCRYPTO_DEFLATE; + fprintf(stderr, "deflate option!\n"); + } + + if (!strcmp(g_config.mode, "stream")) { + mode = MODE_STREAM; + fprintf(stderr, "use stream mode!\n"); + } else if (!strcmp(g_config.mode, "async")) { + mode = MODE_ASYNC; + fprintf(stderr, "use async mode!\n"); + } else if (!strcmp(g_config.mode, "block")) { + mode = MODE_BLOCK; + fprintf(stderr, "use block mode!\n"); + } else { + mode = MODE_BLOCK; + fprintf(stderr, "set mode error, use block mode!\n"); + } + + if (!strcmp(g_config.data_fmt, "sgl")) { + data_fmt = WD_SGL_BUF; + fprintf(stderr, "use memmory of sgl!\n"); + } else { + data_fmt = WD_FLAT_BUF; + fprintf(stderr, "use memmory of pbuffer!\n"); + } + + if (g_config.thread_num > TEST_MAX_THRD) { + fprintf(stderr, "thread_num > 2048, set thread_num = 1!\n"); + g_config.thread_num = 1; + } else if (!thread_num) { + fprintf(stderr, "thread_num can't be 0, set thread_num = 1!\n"); + g_config.thread_num = 1; + } + + if (g_config.cylcls <= 0) { + fprintf(stderr, "cylcls should >= 1, set cylcls = 1!\n"); + g_config.cylcls = 1; + } + + thread_num = g_config.thread_num; + + hizip_thread_test(stdin, stdout, alg_type, mode, op_type, g_config.window_sz, + data_fmt, g_config.cylcls); + + return EXIT_SUCCESS; +} diff --git a/uadk/v1/test/hisi_zip_test/zconf.h b/uadk/v1/test/hisi_zip_test/zconf.h new file mode 100644 index 0000000..1111a39 --- /dev/null +++ b/uadk/v1/test/hisi_zip_test/zconf.h @@ -0,0 +1,534 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". + */ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ +# define Z_PREFIX_SET + +/* all linked symbols and init macros */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_bits z__tr_flush_bits +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# define adler32_z z_adler32_z +# ifndef Z_SOLO +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# endif +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define crc32_z z_crc32_z +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateGetDictionary z_deflateGetDictionary +# define deflateInit z_deflateInit +# define deflateInit2 z_deflateInit2 +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePending z_deflatePending +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateResetKeep z_deflateResetKeep +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# ifndef Z_SOLO +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzfread z_gzfread +# define gzfwrite z_gzfwrite +# define gzgetc z_gzgetc +# define gzgetc_ z_gzgetc_ +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# ifdef _WIN32 +# define gzopen_w z_gzopen_w +# endif +# define gzprintf z_gzprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzvprintf z_gzvprintf +# define gzwrite z_gzwrite +# endif +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit z_inflateBackInit +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCodesUsed z_inflateCodesUsed +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetDictionary z_inflateGetDictionary +# define inflateGetHeader z_inflateGetHeader +# define inflateInit z_inflateInit +# define inflateInit2 z_inflateInit2 +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateResetKeep z_inflateResetKeep +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflateValidate z_inflateValidate +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# ifndef Z_SOLO +# define uncompress z_uncompress +# define uncompress2 z_uncompress2 +# endif +# define zError z_zError +# ifndef Z_SOLO +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# endif +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# ifndef Z_SOLO +# define gzFile z_gzFile +# endif +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# define gz_header_s z_gz_header_s +# define internal_state z_internal_state + +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +#if defined(ZLIB_CONST) && !defined(z_const) +# define z_const const +#else +# define z_const +#endif + +#ifdef Z_SOLO + typedef unsigned long z_size_t; +#else +# define z_longlong long long +# if defined(NO_SIZE_T) + typedef unsigned NO_SIZE_T z_size_t; +# elif defined(STDC) +# include + typedef size_t z_size_t; +# else + typedef unsigned long z_size_t; +# endif +# undef z_longlong +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus about 7 kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +#ifndef Z_ARG /* function prototypes for stdarg */ +# if defined(STDC) || defined(Z_HAVE_STDARG_H) +# define Z_ARG(args) args +# else +# define Z_ARG(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) +# include +# if (UINT_MAX == 0xffffffffUL) +# define Z_U4 unsigned +# elif (ULONG_MAX == 0xffffffffUL) +# define Z_U4 unsigned long +# elif (USHRT_MAX == 0xffffffffUL) +# define Z_U4 unsigned short +# endif +#endif + +#ifdef Z_U4 + typedef Z_U4 z_crc_t; +#else + typedef unsigned long z_crc_t; +#endif + +#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_STDARG_H +#endif + +#ifdef STDC +# ifndef Z_SOLO +# include /* for off_t */ +# endif +#endif + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +# include /* for va_list */ +# endif +#endif + +#ifdef _WIN32 +# ifndef Z_SOLO +# include /* for wchar_t */ +# endif +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) +# define Z_HAVE_UNISTD_H +#endif +#ifndef Z_SOLO +# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ +# ifdef VMS +# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +# endif +#endif + +#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 +# define Z_LFS64 +#endif + +#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) +# define Z_LARGE64 +#endif + +#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) +# define Z_WANT64 +#endif + +#if !defined(SEEK_SET) && !defined(Z_SOLO) +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#ifndef z_off_t +# define z_off_t long +#endif + +#if !defined(_WIN32) && defined(Z_LARGE64) +# define z_off64_t off64_t +#else +# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) +# define z_off64_t __int64 +# else +# define z_off64_t z_off_t +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/uadk/v1/test/hisi_zip_test/zip_alg.c b/uadk/v1/test/hisi_zip_test/zip_alg.c new file mode 100644 index 0000000..202b344 --- /dev/null +++ b/uadk/v1/test/hisi_zip_test/zip_alg.c @@ -0,0 +1,1099 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "v1/wd.h" +#include "v1/wd_util.h" /* It is not API head, to be deleted */ +#include "v1/test/wd_sched.h" +#include "v1/wd_comp.h" +#include "v1/wd_bmm.h" + +#include "v1/drv/hisi_qm_udrv.h" +#include "v1/drv/hisi_zip_udrv.h" +#include "zip_alg.h" +#include "v1/test/smm.h" + + +#define ZLIB_HEADER "\x78\x9c" +#define ZLIB_HEADER_SZ 2 + +/* + * We use a extra field for gzip block length. So the fourth byte is \x04. + * This is necessary because our software don't know the size of block when + * using an hardware decompresser (It is known by hardware). This help our + * decompresser to work and helpfully, compatible with gzip. + */ +#define GZIP_HEADER "\x1f\x8b\x08\x04\x00\x00\x00\x00\x00\x03" +#define GZIP_HEADER_SZ 10 +#define GZIP_EXTRA_SZ 10 +#define GZIP_TAIL_SZ 8 + +/* bytes of data for a request */ +#define BLOCK_SIZE (1024 * 1024) +#define REQ_CACHE_NUM 4 +#define Q_NUM 1 + +struct hizip_priv { + int alg_type; + int op_type; + int block_size; + int dw9; + int total_len; + int out_len; + struct wcrypto_comp_msg *msgs; + void *src, *dst; + int is_fd; +}; + +enum alg_op_type { + COMPRESS, + DECOMPRESS, +}; + +/* block mode api use wd_schedule interface */ + +static void hizip_wd_sched_init_cache(struct wd_scheduler *sched, int i) +{ + struct wd_msg *wd_msg = &sched->msgs[i]; + struct wcrypto_comp_msg *msg; + struct hizip_priv *priv = sched->priv; + + msg = wd_msg->msg = &priv->msgs[i]; + msg->alg_type = priv->alg_type; + msg->avail_out = sched->msg_data_size; + + msg->src = wd_msg->data_in; + msg->dst = wd_msg->data_out; + + dbg("init sched cache %d: %p, %p\n", i, wd_msg, msg); +} + +static int hizip_wd_sched_input(struct wd_msg *msg, void *priv) +{ + size_t ilen, templen, real_len; + struct wcrypto_comp_msg *m = msg->msg; + struct hizip_priv *zip_priv = priv; + + ilen = zip_priv->total_len > zip_priv->block_size ? + zip_priv->block_size : zip_priv->total_len; + templen = ilen; + zip_priv->total_len -= ilen; + if (zip_priv->op_type == WCRYPTO_INFLATE) { + if (zip_priv->alg_type == WCRYPTO_ZLIB) { + zip_priv->src += ZLIB_HEADER_SZ; + ilen -= ZLIB_HEADER_SZ; + } else { + ilen -= GZIP_HEADER_SZ; + if (*((char *)zip_priv->src + 3) == 0x04) { + zip_priv->src += GZIP_HEADER_SZ; + memcpy(&ilen, zip_priv->src + 6, 4); + zip_priv->src += GZIP_EXTRA_SZ; + dbg("gzip iuput len %ld\n", ilen); + SYS_ERR_COND(ilen > zip_priv->block_size * 2, + "gzip protocol_len(%ld) > dmabuf_size(%d)\n", + ilen, zip_priv->block_size); + real_len = GZIP_HEADER_SZ + + GZIP_EXTRA_SZ + ilen; + zip_priv->total_len = zip_priv->total_len + + templen - real_len; + } else + zip_priv->src += GZIP_HEADER_SZ; + } + } + + memcpy(msg->data_in, zip_priv->src, ilen); + zip_priv->src += ilen; + + m->in_size = ilen; + dbg("zip input ilen= %lu, block_size= %d, total_len= %d\n", + ilen, zip_priv->block_size, zip_priv->total_len); + + dbg("zip input(%p, %p): %p, %p, %d, %d\n", + msg, m, + m->src, m->dst, + m->avail_out, m->in_size); + + return 0; +} + +static int hizip_wd_sched_output(struct wd_msg *msg, void *priv) +{ + struct wcrypto_comp_msg *m = msg->msg; + struct hizip_priv *zip_priv = priv; + char gzip_extra[GZIP_EXTRA_SZ] = {0x00, 0x07, 0x48, 0x69, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00}; + + dbg("%s()(%p, %p): %p, %p, inlen=%d, outlen=%d, coms=%d, out=%d\n", + __func__, msg, m, m->src, m->dst, + m->in_size, m->avail_out, m->in_cons, m->produced); + + if (zip_priv->op_type == WCRYPTO_DEFLATE) { + + if (zip_priv->alg_type == WCRYPTO_ZLIB) { + memcpy(zip_priv->dst, + ZLIB_HEADER, ZLIB_HEADER_SZ); + zip_priv->dst += ZLIB_HEADER_SZ; + zip_priv->out_len += ZLIB_HEADER_SZ; + } else { + memcpy(gzip_extra + 6, &m->produced, 4); + memcpy(zip_priv->dst, GZIP_HEADER, + GZIP_HEADER_SZ); + zip_priv->dst += GZIP_HEADER_SZ; + zip_priv->out_len += GZIP_HEADER_SZ; + memcpy(zip_priv->dst, gzip_extra, + GZIP_EXTRA_SZ); + zip_priv->dst += GZIP_EXTRA_SZ; + zip_priv->out_len += GZIP_EXTRA_SZ; + } + } + + memcpy(zip_priv->dst, msg->data_out, m->produced); + zip_priv->dst += m->produced; + zip_priv->out_len += m->produced; + + return 0; +} + +static int hizip_init(struct wd_scheduler *sched, int alg_type, int op_type, + int blk_size) +{ + int ret = -ENOMEM, i; + char *alg; + struct wcrypto_paras *priv; + struct hizip_priv *zip_priv; + + sched->q_num = Q_NUM; + sched->ss_region_size = 0; /* let system make decision */ + sched->msg_cache_num = 1; + /* use twice size of the input data, hope it is engouth for output */ + sched->msg_data_size = blk_size * 2; + sched->init_cache = hizip_wd_sched_init_cache; + sched->input = hizip_wd_sched_input; + sched->output = hizip_wd_sched_output; + + sched->qs = calloc(sched->q_num, sizeof(struct wd_queue)); + if (!sched->qs) + return -ENOMEM; + + zip_priv = calloc(1, sizeof(struct hizip_priv)); + if (!zip_priv) + goto err_with_qs; + + zip_priv->msgs = calloc(sched->msg_cache_num, + sizeof(struct wcrypto_comp_msg)); + if (!zip_priv->msgs) + goto err_with_priv; + + zip_priv->alg_type = alg_type; + zip_priv->op_type = op_type; + zip_priv->block_size = blk_size; + if (alg_type == WCRYPTO_ZLIB) + alg = "zlib"; + else + alg = "gzip"; + + for (i = 0; i < sched->q_num; i++) { + sched->qs[i].capa.alg = alg; + priv = &sched->qs[i].capa.priv; + priv->direction = zip_priv->op_type; + } + + sched->priv = zip_priv; + ret = wd_sched_init(sched); + if (ret) + goto err_with_msgs; + + return 0; + +err_with_msgs: + free(zip_priv->msgs); +err_with_priv: + free(zip_priv); +err_with_qs: + free(sched->qs); + return ret; +} + +static void hizip_fini(struct wd_scheduler *sched) +{ + struct hizip_priv *zip_priv = sched->priv; + + wd_sched_fini(sched); + free(zip_priv->msgs); + free(zip_priv); + free(sched->qs); +} + +/** + * compress() - compress memory buffer. + * @alg_type: alg_type. + * + * This function compress memory buffer. + */ +int hw_blk_compress(int alg_type, int blksize, + unsigned char *dst, ulong *dstlen, + unsigned char *src, ulong srclen) +{ + int ret; + struct wd_scheduler sched; + struct hizip_priv *zip_priv; + + if (blksize < 0 || dst == NULL || src == NULL) + return -EINVAL; + memset(&sched, 0, sizeof(struct wd_scheduler)); + ret = hizip_init(&sched, alg_type, WCRYPTO_DEFLATE, blksize); + if (ret) { + WD_ERR("fail to hizip init!\n"); + return ret; + } + zip_priv = sched.priv; + zip_priv->total_len = srclen; + zip_priv->src = src; + zip_priv->dst = dst; + zip_priv->is_fd = 0; + + while (zip_priv->total_len || !wd_sched_empty(&sched)) { + dbg("request loop: total_len=%d\n", zip_priv->total_len); + ret = wd_sched_work(&sched, zip_priv->total_len); + if (ret < 0) { + WD_ERR("wd_sched_work fail, ret=%d!\n", ret); + return ret; + } + } + + *dstlen = zip_priv->out_len; + hizip_fini(&sched); + + return ret; +} + +int hw_blk_decompress(int alg_type, int blksize, + unsigned char *dst, ulong *dstlen, + unsigned char *src, ulong srclen) +{ + int ret; + struct wd_scheduler sched; + struct hizip_priv *zip_priv; + + if (blksize < 0 || dst == NULL || src == NULL) + return -EINVAL; + memset(&sched, 0, sizeof(struct wd_scheduler)); + ret = hizip_init(&sched, alg_type, WCRYPTO_INFLATE, blksize); + if (ret) { + WD_ERR("fail to hizip init!\n"); + return ret; + } + zip_priv = sched.priv; + zip_priv->total_len = srclen; + zip_priv->src = src; + zip_priv->dst = dst; + zip_priv->is_fd = 0; + + while (zip_priv->total_len || !wd_sched_empty(&sched)) { + dbg("request loop: total_len=%d\n", zip_priv->total_len); + ret = wd_sched_work(&sched, zip_priv->total_len); + if (ret < 0) { + WD_ERR("wd_sched_work fail, ret=%d!\n", ret); + return ret; + } + } + + *dstlen = zip_priv->out_len; + hizip_fini(&sched); + + return ret; +} + +/* stream api */ +#define ST_ZLIB_HEADER "\x78\x9c" +#define ST_GZIP_HEADER "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03" + +#define ST_ZLIB_HEADER_SZ 2 +#define ST_GZIP_HEADER_SZ 10 + +#define EMPTY_ZLIB_APPEND "\x03\x00\x00\x00\x00\x01" +#define EMPTY_ZLIB_SZ 6 +#define EMPTY_GZIP_APPEND "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00" +#define EMPTY_GZIP_SZ 10 + + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_STREAM_NEED_AGAIN 2 + +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-EIO) + +#define swab32(x) \ + ((((x) & 0x000000ff) << 24) | \ + (((x) & 0x0000ff00) << 8) | \ + (((x) & 0x00ff0000) >> 8) | \ + (((x) & 0xff000000) >> 24)) + +#define cpu_to_be32(x) swab32(x) + +/*wrap as zlib basic interface */ +#define HZLIB_VERSION "1.0.1" + +#ifndef MAX_WBITS +#define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* compression levels */ +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) + + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +#ifdef MAXSEG_64K +#define MAX_MEM_LEVEL 8 +#else +#define MAX_MEM_LEVEL 9 +#endif +#endif + +/* default memLevel */ +#ifndef DEF_MEM_LEVEL +#if MAX_MEM_LEVEL >= 8 +#define DEF_MEM_LEVEL 8 +#else +#define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +#endif + +/* compression strategy; see deflateInit2() below for details */ +#define Z_DEFAULT_STRATEGY 0 + +/* default windowBits for decompression. MAX_WBITS is for compression only */ +#ifndef DEF_WBITS +#define DEF_WBITS MAX_WBITS +#endif + +/* The deflate compression method (the only one supported in this version) */ +#define Z_DEFLATED 8 + +struct zip_stream { + void *next_in; /* next input byte */ + unsigned long avail_in; /* number of bytes available at next_in */ + unsigned long total_in; /* total nb of input bytes read so far */ + void *next_out; /* next output byte should be put there */ + unsigned long avail_out; /* remaining free space at next_out */ + unsigned long total_out; /* total nb of bytes output so far */ + char *msg; /* last error message, NULL if no error */ + void *workspace; /* memory allocated for this stream */ + int data_type; /*the data type: ascii or binary */ + unsigned long adler; /* adler32 value of the uncompressed data */ + void *reserved; /* reserved for future use */ +}; + +struct zip_ctl { + void *pool; + void *in; + void *out; + void *ctxbuf; + void *queue; + void *ctx; + void *opdata; +}; + +#define hw_deflateInit(strm, level) \ + hw_deflateInit_(strm, level, HZLIB_VERSION, sizeof(struct zip_stream)) +#define hw_inflateInit(strm) \ + hw_inflateInit_(strm, HZLIB_VERSION, (int)sizeof(struct zip_stream)) +#define hw_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + hw_deflateInit2_(strm, level, method, windowBits, memLevel,\ + (strategy), HZLIB_VERSION, (int)sizeof(struct zip_stream)) +#define hw_inflateInit2(strm, windowBits) \ + hw_inflateInit2_(strm, windowBits, HZLIB_VERSION, \ + (int)sizeof(struct zip_stream)) + +static int stream_chunk = 1024 * 64; + +static int hw_init(struct zip_stream *zstrm, int alg_type, int comp_optype) +{ + struct wcrypto_comp_ctx_setup ctx_setup; + struct wcrypto_comp_op_data *opdata; + struct wd_blkpool_setup mm_setup; + unsigned int block_mm_num = 3; + struct wcrypto_paras *priv; + struct zip_ctl *ctl; + void *in, *out; + struct wd_queue *q; + void *zip_ctx; + void *pool; + int ret; + + q = calloc(1, sizeof(struct wd_queue)); + if (q == NULL) { + ret = -ENOMEM; + fprintf(stderr, "alloc q fail, ret =%d\n", ret); + return ret; + } + + switch (alg_type) { + case WCRYPTO_ZLIB: + q->capa.alg = "zlib"; + break; + case WCRYPTO_GZIP: + q->capa.alg = "gzip"; + break; + default: + ret = -EINVAL; + goto hw_q_free; + } + + q->capa.latency = 0; + q->capa.throughput = 0; + + priv = &q->capa.priv; + priv->direction = comp_optype; + ret = wd_request_queue(q); + if (ret) { + fprintf(stderr, "wd_request_queue fail, ret =%d\n", ret); + goto hw_q_free; + } + SYS_ERR_COND(ret, "wd_request_queue"); + +#ifdef CONFIG_IOMMU_SVA + in = calloc(1, DMEMSIZE); + out = calloc(1, DMEMSIZE); + ctx_buf = calloc(1, HW_CTX_SIZE); + if (in == NULL || out == NULL || ctx_buf == NULL) { + dbg("not enough data ss_region memory for cache (bs=%d)\n", + DMEMSIZE); + goto buf_free; + } + +#else + memset(&mm_setup, 0, sizeof(mm_setup)); + mm_setup.block_size = DMEMSIZE; + mm_setup.block_num = block_mm_num; + mm_setup.align_size = 128; + pool = wd_blkpool_create(q, &mm_setup); + if (!pool) { + WD_ERR("%s(): create pool fail!\n", __func__); + ret = -ENOMEM; + goto release_q; + } + in = wd_alloc_blk(pool); + out = wd_alloc_blk(pool); + + if (in == NULL || out == NULL) { + dbg("not enough data ss_region memory for cache (bs=%d)\n", + DMEMSIZE); + goto buf_free; + } + +#endif + + dbg("%s():va_in=%p, va_out=%p!\n", __func__, in, out); + memset(&ctx_setup, 0, sizeof(ctx_setup)); + ctx_setup.alg_type = alg_type; + ctx_setup.stream_mode = WCRYPTO_COMP_STATEFUL; + ctx_setup.br.alloc = (void *)wd_alloc_blk; + ctx_setup.br.free = (void *)wd_free_blk; + ctx_setup.br.iova_map = (void *)wd_blk_iova_map; + ctx_setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + ctx_setup.br.get_bufsize = (void *)wd_blksize; + ctx_setup.br.usr = pool; + zip_ctx = wcrypto_create_comp_ctx(q, &ctx_setup); + if (!zip_ctx) { + fprintf(stderr, "zip_alloc_comp_ctx fail, ret =%d\n", ret); + goto buf_free; + } + + opdata = calloc(1, sizeof(struct wcrypto_comp_op_data)); + if (opdata == NULL) { + ret = -ENOMEM; + fprintf(stderr, "alloc opdata fail, ret =%d\n", ret); + goto comp_ctx_free; + } + opdata->in = in; + opdata->out = out; + opdata->stream_pos = WCRYPTO_COMP_STREAM_NEW; + opdata->alg_type = ctx_setup.alg_type; + + ctl = calloc(1, sizeof(struct zip_ctl)); + if (ctl == NULL) { + ret = -ENOMEM; + fprintf(stderr, "alloc ctl fail, ret =%d\n", ret); + goto comp_opdata_free; + } + ctl->pool = pool; + ctl->in = in; /* temp for opdata->in*/ + ctl->out = out; + ctl->ctx = zip_ctx; + ctl->queue = q; + ctl->opdata = opdata; + + zstrm->next_in = in; + zstrm->next_out = out; + zstrm->reserved = ctl; + + return Z_OK; + +comp_opdata_free: + free(opdata); + +comp_ctx_free: + wcrypto_del_comp_ctx(zip_ctx); + +buf_free: +#ifdef CONFIG_IOMMU_SVA + if (in) + free(in); + if (out) + free(out); +#else + if (in) + wd_free_blk(pool, in); + if (out) + wd_free_blk(pool, out); + + wd_blkpool_destroy(pool); +#endif +release_q: + wd_release_queue(q); +hw_q_free: + free(q); + + return ret; +} + +static void hw_end(struct zip_stream *zstrm) +{ + struct zip_ctl *ctl = zstrm->reserved; + struct wcrypto_comp_op_data *opdata = ctl->opdata; + +#ifdef CONFIG_IOMMU_SVA + if (ctl->in) + free(ctl->in); + if (ctl->out) + free(ctl->out); +#else + if (ctl->in) + wd_free_blk(ctl->pool, ctl->in); + if (ctl->out) + wd_free_blk(ctl->pool, ctl->out); +#endif + + if (ctl->ctx) + wcrypto_del_comp_ctx(ctl->ctx); + + if (ctl->queue) { + wd_release_queue(ctl->queue); + free(ctl->queue); + } + + wd_blkpool_destroy(ctl->pool); + free(opdata); + free(ctl); +} + +static unsigned int bit_reverse(register unsigned int x) +{ + x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1)); + x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2)); + x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4)); + x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8)); + + return((x >> 16) | (x << 16)); +} + +/* output an empty store block */ +static int append_store_block(struct zip_stream *zstrm, int flush) +{ + char store_block[5] = {0x1, 0x00, 0x00, 0xff, 0xff}; + struct zip_ctl *ctl = zstrm->reserved; + struct wcrypto_comp_op_data *opdata = ctl->opdata; + __u32 checksum = opdata->checksum; + __u32 isize = opdata->isize; + + memcpy(zstrm->next_out, store_block, 5); + zstrm->total_out += 5; + zstrm->avail_out -= 5; + if (flush != WCRYPTO_FINISH) + return Z_STREAM_END; + + if (opdata->alg_type == WCRYPTO_ZLIB) { /*if zlib, ADLER32*/ + checksum = (__u32) cpu_to_be32(checksum); + memcpy(zstrm->next_out + 5, &checksum, 4); + zstrm->total_out += 4; + zstrm->avail_out -= 4; + } else if (opdata->alg_type == WCRYPTO_GZIP) { + checksum = ~checksum; + checksum = bit_reverse(checksum); + /* if gzip, CRC32 and ISIZE */ + memcpy(zstrm->next_out + 5, &checksum, 4); + memcpy(zstrm->next_out + 9, &isize, 4); + zstrm->total_out += 8; + zstrm->avail_out -= 8; + } else + fprintf(stderr, "in append store block, wrong alg type %d.\n", + opdata->alg_type); + + return Z_STREAM_END; +} + +static int hw_send_and_recv(struct zip_stream *zstrm, int flush) +{ + struct zip_ctl *ctl = zstrm->reserved; + struct wcrypto_comp_op_data *opdata = ctl->opdata; + void *zip_ctx = ctl->ctx; + int ret = 0; + + if (zstrm->avail_in == 0 && flush == WCRYPTO_FINISH) + return append_store_block(zstrm, flush); + + opdata->flush = flush; + opdata->in_len = zstrm->avail_in; + opdata->avail_out = zstrm->avail_out; + + dbg("%s():input ,opdata->in_len=%u, zstrm->avail_out=%lu!\n", + __func__, opdata->in_len, zstrm->avail_out); + + ret = wcrypto_do_comp(zip_ctx, opdata, NULL); + if (ret < 0) + return ret; + if (opdata->stream_pos == WCRYPTO_COMP_STREAM_NEW) { + opdata->stream_pos = WCRYPTO_COMP_STREAM_OLD; + zstrm->total_out = 0; + } + + dbg("%s():output, inlen=%d, coms=%d, produced=%d, avail_out=%lu!\n", + __func__, opdata->in_len, opdata->consumed, + opdata->produced, zstrm->avail_out); + + zstrm->avail_in = opdata->in_len - opdata->consumed; + zstrm->avail_out -= opdata->produced; + zstrm->total_out += opdata->produced; + + if (zstrm->avail_in > 0) + opdata->in += opdata->consumed; + if (zstrm->avail_in == 0) + opdata->in = ctl->in; /* origin addr in */ + + if (ret == 0 && flush == WCRYPTO_FINISH) + ret = Z_STREAM_END; + else if (ret == 0 && opdata->status == WCRYPTO_DECOMP_END_NOSPACE) + ret = Z_STREAM_NEED_AGAIN; /* decomp_is_end region */ + else if (ret == 0 && opdata->status == WCRYPTO_DECOMP_END) + ret = Z_STREAM_END; /* decomp_is_end region */ + else if (ret == 0 && opdata->status == WD_VERIFY_ERR) + ret = -WD_VERIFY_ERR; /* crc err */ + else if (ret == 0 && opdata->status == WD_IN_EPARA) + ret = -WD_IN_EPARA; /* msg err */ + + return ret; +} + +int hw_deflateInit2_(struct zip_stream *zstrm, int level, int method, + int windowBits, int memLevel, int strategy, + const char *version, int stream_size) +{ + int alg_type; + int wrap = 0; + + if (windowBits < 0) { /* suppress zlib wrapper */ + wrap = 0; + windowBits = -windowBits; + } else if (windowBits > 15) { + wrap = 2; /* write gzip wrapper instead */ + windowBits -= 16; + } + + if (wrap & 0x02) + alg_type = WCRYPTO_GZIP; + else + alg_type = WCRYPTO_ZLIB; + + return hw_init(zstrm, alg_type, WCRYPTO_DEFLATE); + +} + +int hw_deflateInit_(struct zip_stream *zstrm, int level, const char *version, + int stream_size) +{ + if (zstrm == NULL) + return -EINVAL; + + return hw_deflateInit2_(zstrm, level, Z_DEFLATED, + MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, version, stream_size); +} + +int hw_deflate(struct zip_stream *zstrm, int flush) +{ + int ret; + + if (zstrm == NULL) + return -EINVAL; + ret = hw_send_and_recv(zstrm, flush); + if (ret < 0) + return Z_STREAM_ERROR; + return ret; +} + +int hw_deflateEnd(struct zip_stream *zstrm) +{ + if (zstrm == NULL) + return -EINVAL; + hw_end(zstrm); + return 0; +} + +int hw_inflateInit2_(struct zip_stream *zstrm, int windowBits, + const char *version, int stream_size) +{ + int wrap, alg_type; + + /* extract wrap request from windowBits parameter */ + if (windowBits < 0) { + wrap = 0; + windowBits = -windowBits; + } else { + wrap = (windowBits >> 4) + 5; + + } + if (wrap & 0x01) + alg_type = WCRYPTO_ZLIB; + if (wrap & 0x02) + alg_type = WCRYPTO_GZIP; + + return hw_init(zstrm, alg_type, WCRYPTO_INFLATE); +} + +int hw_inflateInit_(struct zip_stream *zstrm, + const char *version, int stream_size) +{ + if (zstrm == NULL) + return -EINVAL; + return hw_inflateInit2_(zstrm, DEF_WBITS, version, stream_size); +} + +int hw_inflate(struct zip_stream *zstrm, int flush) +{ + int ret; + + if (zstrm == NULL) + return -EINVAL; + ret = hw_send_and_recv(zstrm, flush); + if (ret < 0) + return Z_STREAM_ERROR; + return ret; +} + +int hw_inflateEnd(struct zip_stream *zstrm) +{ + if (zstrm == NULL) + return -EINVAL; + hw_end(zstrm); + return 0; +} + +int hw_stream_compress(int alg_type, int blksize, + unsigned char *dst, ulong *dstlen, + unsigned char *src, ulong srclen) +{ + int flush, have; + int ret; + int level = 0; + struct zip_stream zstrm; + int windowBits = 15; + int GZIP_ENCODING = 16; + + if (blksize < 0 || dst == NULL || src == NULL) + return -EINVAL; + stream_chunk = blksize; + *dstlen = 0; + + /* add zlib compress head and write head + compressed date to a file */ + if (alg_type == WCRYPTO_ZLIB) { + ret = hw_deflateInit(&zstrm, level); + if (ret != Z_OK) + return ret; + memcpy(dst, ST_ZLIB_HEADER, ST_ZLIB_HEADER_SZ); + dst += ST_ZLIB_HEADER_SZ; + *dstlen += ST_ZLIB_HEADER_SZ; + } else { + /* deflate for gzip data */ + ret = hw_deflateInit2(&zstrm, Z_DEFAULT_COMPRESSION, + Z_DEFLATED, windowBits | GZIP_ENCODING, 8, + Z_DEFAULT_STRATEGY); + if (ret != Z_OK) + return ret; + memcpy(dst, ST_GZIP_HEADER, ST_GZIP_HEADER_SZ); + dst += ST_GZIP_HEADER_SZ; + *dstlen += ST_GZIP_HEADER_SZ; + } + do { + if (srclen > stream_chunk) { + memcpy(zstrm.next_in, src, stream_chunk); + src += stream_chunk; + zstrm.avail_in = stream_chunk; + srclen -= stream_chunk; + } else { + memcpy(zstrm.next_in, src, srclen); + zstrm.avail_in = srclen; + srclen = 0; + } + flush = srclen ? WCRYPTO_SYNC_FLUSH : WCRYPTO_FINISH; + do { + zstrm.avail_out = stream_chunk; + ret = hw_deflate(&zstrm, flush); + ASSERT(ret != Z_STREAM_ERROR); + if (ret < 0) { + hw_end(&zstrm); + return ret; + } + have = stream_chunk - zstrm.avail_out; + memcpy(dst, zstrm.next_out, have); + dst += have; + *dstlen += have; + } while (zstrm.avail_in > 0); + ASSERT(zstrm.avail_in == 0); /* all input will be used */ + + /* done when last data in file processed */ + } while (flush != WCRYPTO_FINISH); + + dbg("%s, end strm->total = %ld\n", __func__, zstrm.total_out); + + ASSERT(ret == Z_STREAM_END); /* stream will be complete */ + hw_end(&zstrm); + + return Z_OK; +} + +int hw_stream_decompress(int alg_type, int blksize, + unsigned char *dst, ulong *dstlen, + unsigned char *src, ulong srclen) +{ + struct zip_stream zstrm; + ulong out_size = 0; + int have; + int ret; + + if (blksize < 0 || dst == NULL || src == NULL) + return -EINVAL; + stream_chunk = blksize; + + if (alg_type == WCRYPTO_ZLIB) { + ret = hw_inflateInit(&zstrm); + if (ret != Z_OK) + return ret; + src += ST_ZLIB_HEADER_SZ; + srclen -= ST_ZLIB_HEADER_SZ; + } else { + ret = hw_inflateInit2(&zstrm, 16 + MAX_WBITS); + if (ret != Z_OK) + return ret; + src += ST_GZIP_HEADER_SZ; + srclen -= ST_GZIP_HEADER_SZ; + } + do { + if (srclen > stream_chunk) { + memcpy(zstrm.next_in, src, stream_chunk); + src += stream_chunk; + zstrm.avail_in = stream_chunk; + srclen -= stream_chunk; + } else { + memcpy(zstrm.next_in, src, srclen); + zstrm.avail_in = srclen; + srclen = 0; + } +/* + * if (zstrm.avail_in == 0) { + * ret = Z_STREAM_END; + * break; + * } + */ + /* finish compression if all of source has been read in */ + do { + zstrm.avail_out = stream_chunk; + ret = hw_inflate(&zstrm, WCRYPTO_SYNC_FLUSH); + ASSERT(ret != Z_STREAM_ERROR); + if (ret < 0) { + hw_end(&zstrm); + return ret; + } + have = stream_chunk - zstrm.avail_out; + if (zstrm.total_out > *dstlen) { + hw_end(&zstrm); + return -ENOMEM; + } + memcpy(dst, zstrm.next_out, have); + dst += have; + out_size += have; + } while (zstrm.avail_in > 0); + ASSERT(zstrm.avail_in == 0); /* all input will be used */ + + /* done when last data in file processed */ + } while (ret != Z_STREAM_END); + + dbg("%s, end strm->total = %ld\n", __func__, zstrm.total_out); + + *dstlen = out_size + + ASSERT(ret == Z_STREAM_END); /* stream will be complete */ + hw_end(&zstrm); + return Z_OK; +} + +int hw_stream_def(FILE *source, FILE *dest, int alg_type) +{ + int flush, have; + int ret; + int level = 0; + struct zip_stream zstrm; + int windowBits = 15; + int GZIP_ENCODING = 16; + int fd, file_len; + struct stat s; + + fd = fileno(source); + SYS_ERR_COND(fstat(fd, &s) < 0, "fstat"); + file_len = s.st_size; + if (!file_len) { + if (alg_type == WCRYPTO_ZLIB) { + fwrite(ST_ZLIB_HEADER, 1, ST_ZLIB_HEADER_SZ, dest); + fwrite(EMPTY_ZLIB_APPEND, 1, EMPTY_ZLIB_SZ, dest); + return Z_OK; + } else if (alg_type == WCRYPTO_GZIP) { + fwrite(ST_GZIP_HEADER, 1, ST_GZIP_HEADER_SZ, dest); + fwrite(EMPTY_GZIP_APPEND, 1, EMPTY_GZIP_SZ, dest); + return Z_OK; + } else + return -EINVAL; + } + /* add zlib compress head and write head + compressed date to a file */ + if (alg_type == WCRYPTO_ZLIB) { + ret = hw_deflateInit(&zstrm, level); + if (ret != Z_OK) + return ret; + fwrite(ST_ZLIB_HEADER, 1, ST_ZLIB_HEADER_SZ, dest); + } else { + /* deflate for gzip data */ + ret = hw_deflateInit2(&zstrm, Z_DEFAULT_COMPRESSION, + Z_DEFLATED, windowBits | GZIP_ENCODING, 8, + Z_DEFAULT_STRATEGY); + if (ret != Z_OK) + return ret; + fwrite(ST_GZIP_HEADER, 1, ST_GZIP_HEADER_SZ, dest); + } + do { + + zstrm.avail_in = fread(zstrm.next_in, 1, stream_chunk, source); + flush = feof(source) ? WCRYPTO_FINISH : WCRYPTO_SYNC_FLUSH; + do { + zstrm.avail_out = stream_chunk; + ret = hw_deflate(&zstrm, flush); + ASSERT(ret != Z_STREAM_ERROR); + if (ret < 0) { + hw_end(&zstrm); + return ret; + } + have = stream_chunk - zstrm.avail_out; + if (fwrite(zstrm.next_out, 1, have, dest) != have || + ferror(dest)) { + fprintf(stderr, "errno =%d\n", errno); + (void)hw_end(&zstrm); + return Z_ERRNO; + } + } while (zstrm.avail_in > 0); + ASSERT(zstrm.avail_in == 0); /* all input will be used */ + + /* done when last data in file processed */ + } while (flush != WCRYPTO_FINISH); + + dbg("%s, end strm->total = %ld\n", __func__, zstrm.total_out); + + ASSERT(ret == Z_STREAM_END); /* stream will be complete */ + hw_end(&zstrm); + + return Z_OK; +} + +int hw_stream_inf(FILE *source, FILE *dest, int alg_type) +{ + int have; + int ret; + struct zip_stream zstrm; + + if (alg_type == WCRYPTO_ZLIB) { + ret = hw_inflateInit(&zstrm); + if (ret != Z_OK) + return ret; + fseek(source, ST_ZLIB_HEADER_SZ, SEEK_SET); + } else { + ret = hw_inflateInit2(&zstrm, 16 + MAX_WBITS); + if (ret != Z_OK) + return ret; + fseek(source, ST_GZIP_HEADER_SZ, SEEK_SET); + } + do { + zstrm.avail_in = fread(zstrm.next_in, 1, stream_chunk, source); + if (ferror(source)) { + hw_end(&zstrm); + return Z_ERRNO; + } +/* + * if (zstrm.avail_in == 0) + * break; + */ + /* finish compression if all of source has been read in */ + do { + zstrm.avail_out = stream_chunk; + ret = hw_inflate(&zstrm, WCRYPTO_SYNC_FLUSH); + ASSERT(ret != Z_STREAM_ERROR); + if (ret < 0) { + hw_end(&zstrm); + return ret; + } + have = stream_chunk - zstrm.avail_out; + if (fwrite(zstrm.next_out, 1, have, dest) != have || + ferror(dest)) { + hw_end(&zstrm); + return Z_ERRNO; + } + + } while (zstrm.avail_in > 0); + ASSERT(zstrm.avail_in == 0); /* all input will be used */ + + /* done when last data in file processed */ + } while (ret != Z_STREAM_END); + + dbg("%s, end strm->total = %ld\n", __func__, zstrm.total_out); + + ASSERT(ret == Z_STREAM_END); /* stream will be complete */ + hw_end(&zstrm); + return Z_OK; +} + diff --git a/uadk/v1/test/hisi_zip_test/zip_alg.h b/uadk/v1/test/hisi_zip_test/zip_alg.h new file mode 100644 index 0000000..791801f --- /dev/null +++ b/uadk/v1/test/hisi_zip_test/zip_alg.h @@ -0,0 +1,69 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#ifndef __WD_ZIP_ALG_H__ +#define __WD_ZIP_ALG_H__ + +#include +#include +#include +#include +#include +#include + + +//#define DEFLATE 0 +//#define INFLATE 1 + +#define DMEMSIZE (1024 * 1024) /* 1M */ +#define HW_CTX_SIZE (64 * 1024) + +#define SYS_ERR_COND(cond, msg, ...) \ +do { \ + if (cond) { \ + if (errno) \ + perror(msg); \ + else \ + fprintf(stderr, msg, ##__VA_ARGS__); \ + exit(EXIT_FAILURE); \ + } \ +} while (0) + + +/* for block interface */ +extern int hw_blk_compress(int alg_type, int blksize, + unsigned char *dst, ulong *dstlen, + unsigned char *src, ulong srclen); + +extern int hw_blk_decompress(int alg_type, int blksize, + unsigned char *dst, ulong *dstlen, + unsigned char *src, ulong srclen); + +/* for stream memory interface */ +extern int hw_stream_compress(int alg_type, int blksize, + unsigned char *dst, ulong *dstlen, + unsigned char *src, ulong srclen); + +extern int hw_stream_decompress(int alg_type, int blksize, + unsigned char *dst, ulong *dstlen, + unsigned char *src, ulong srclen); + +/* for stream file interface */ +extern int hw_stream_def(FILE *source, FILE *dest, int alg_type); +extern int hw_stream_inf(FILE *source, FILE *dest, int alg_type); + +#endif + diff --git a/uadk/v1/test/hisi_zip_test/zlib.h b/uadk/v1/test/hisi_zip_test/zlib.h new file mode 100644 index 0000000..c0396fa --- /dev/null +++ b/uadk/v1/test/hisi_zip_test/zlib.h @@ -0,0 +1,1912 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.11, January 15th, 2017 + + Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 + (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.11" +#define ZLIB_VERNUM 0x12b0 +#define ZLIB_VER_MAJOR 1 +#define ZLIB_VER_MINOR 2 +#define ZLIB_VER_REVISION 11 +#define ZLIB_VER_SUBREVISION 0 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed data. + This version of the library supports only one compression method (deflation) + but other algorithms will be added later and will have the same stream + interface. + + Compression can be done in a single step if the buffers are large enough, + or can be done by repeated calls of the compression function. In the latter + case, the application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip and raw deflate streams in + memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never crash + even in the case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + z_const Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total number of input bytes read so far */ + + Bytef *next_out; /* next output byte will go here */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total number of bytes output so far */ + + z_const char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text + for deflate, or the decoding state for inflate */ + uLong adler; /* Adler-32 or CRC-32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has dropped + to zero. It must update next_out and avail_out when avail_out has dropped + to zero. The application must initialize zalloc, zfree and opaque before + calling the init function. All other fields are set by the compression + library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. In that case, zlib is thread-safe. When zalloc and zfree are + Z_NULL on entry to the initialization function, they are set to internal + routines that use the standard library functions malloc() and free(). + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this if + the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers + returned by zalloc for objects of exactly 65536 bytes *must* have their + offset normalized to zero. The default allocation function provided by this + library ensures this (see zutil.c). To reduce memory requirements and avoid + any allocation of 64K objects, at the expense of compression ratio, compile + the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or progress + reports. After compression, total_in holds the total size of the + uncompressed data and may be saved for use by the decompressor (particularly + if the decompressor wants to decompress everything in a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +#define Z_TREES 6 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field for deflate() */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is not + compatible with the zlib.h header file used by the application. This check + is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. If + zalloc and zfree are set to Z_NULL, deflateInit updates them to use default + allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at all + (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION + requests a default compromise between speed and compression (currently + equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if level is not a valid compression level, or + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). msg is set to null + if there is no error message. deflateInit does not perform any compression: + this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Generate more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary. Some output may be provided even if + flush is zero. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating avail_in or avail_out accordingly; avail_out should + never be zero before the call. The application can consume the compressed + output when it wants, for example when the output buffer is full (avail_out + == 0), or after each call of deflate(). If deflate returns Z_OK and with + zero avail_out, it must be called again after making room in the output + buffer because there might be more output pending. See deflatePending(), + which can be used if desired to determine whether or not there is more ouput + in that case. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumulate before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In + particular avail_in is zero after the call if enough output space has been + provided before the call.) Flushing may degrade compression for some + compression algorithms and so it should be used only when necessary. This + completes the current deflate block and follows it with an empty stored block + that is three bits plus filler bits to the next byte, followed by four bytes + (00 00 ff ff). + + If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the + output buffer, but the output is not aligned to a byte boundary. All of the + input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. + This completes the current deflate block and follows it with an empty fixed + codes block that is 10 bits long. This assures that enough bytes are output + in order for the decompressor to finish the block before the empty fixed + codes block. + + If flush is set to Z_BLOCK, a deflate block is completed and emitted, as + for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to + seven bits of the current block are held to be written as the next byte after + the next deflate block is completed. In this case, the decompressor may not + be provided enough bits at this point in order to complete decompression of + the data provided so far to the compressor. It may need to wait for the next + block to be emitted. This is for advanced applications that need to control + the emission of deflate blocks. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there was + enough output space. If deflate returns with Z_OK or Z_BUF_ERROR, this + function must be called again with Z_FINISH and more output space (updated + avail_out) but no more input data, until it returns with Z_STREAM_END or an + error. After deflate has returned Z_STREAM_END, the only possible operations + on the stream are deflateReset or deflateEnd. + + Z_FINISH can be used in the first deflate call after deflateInit if all the + compression is to be done in a single step. In order to complete in one + call, avail_out must be at least the value returned by deflateBound (see + below). Then deflate is guaranteed to return Z_STREAM_END. If not enough + output space is provided, deflate will not return Z_STREAM_END, and it must + be called again as described above. + + deflate() sets strm->adler to the Adler-32 checksum of all input read + so far (that is, total_in bytes). If a gzip stream is being generated, then + strm->adler will be the CRC-32 checksum of the input read so far. (See + deflateInit2 below.) + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). If in doubt, the data is + considered binary. This field is only for information purposes and does not + affect the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was Z_NULL or the state was inadvertently written over + by the application), or Z_BUF_ERROR if no progress is possible (for example + avail_in or avail_out was zero). Note that Z_BUF_ERROR is not fatal, and + deflate() can be called again with more input and more output space to + continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, msg + may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. In the current version of inflate, the provided input is not + read or consumed. The allocation of a sliding window will be deferred to + the first call of inflate (if the decompression does not complete on the + first call). If zalloc and zfree are set to Z_NULL, inflateInit updates + them to use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit does not perform any decompression. + Actual decompression will be done by inflate(). So next_in, and avail_in, + next_out, and avail_out are unused and unchanged. The current + implementation of inflateInit() does not process any header information -- + that is deferred until inflate() is called. +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), then next_in and avail_in are updated + accordingly, and processing will resume at this point for the next call of + inflate(). + + - Generate more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there is + no more input data or no more space in the output buffer (see below about + the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating the next_* and avail_* values accordingly. If the + caller of inflate() does not provide both available input and available + output space, it is possible that there will be no progress made. The + application can consume the uncompressed output when it wants, for example + when the output buffer is full (avail_out == 0), or after each call of + inflate(). If inflate returns Z_OK and with zero avail_out, it must be + called again after making room in the output buffer because there might be + more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, + Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() + stop if and when it gets to the next deflate block boundary. When decoding + the zlib or gzip format, this will cause inflate() to return immediately + after the header and before the first block. When doing a raw inflate, + inflate() will go ahead and process the first block, and will return when it + gets to the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + To assist in this, on return inflate() always sets strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 if + inflate() is currently decoding the last block in the deflate stream, plus + 128 if inflate() returned immediately after decoding an end-of-block code or + decoding the complete header up to just before the first byte of the deflate + stream. The end-of-block will not be indicated until all of the uncompressed + data from that block has been written to strm->next_out. The number of + unused bits may in general be greater than seven, except when bit 7 of + data_type is set, in which case the number of unused bits will be less than + eight. data_type is set as noted here every time inflate() returns for all + flush options, and so can be used to determine the amount of currently + consumed input in bits. + + The Z_TREES option behaves as Z_BLOCK does, but it also returns when the + end of each deflate block header is reached, before any actual data in that + block is decoded. This allows the caller to determine the length of the + deflate block header for later use in random access within a deflate block. + 256 is added to the value of strm->data_type when inflate() returns + immediately after reaching the end of the deflate block header. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step (a + single call of inflate), the parameter flush should be set to Z_FINISH. In + this case all pending input is processed and all pending output is flushed; + avail_out must be large enough to hold all of the uncompressed data for the + operation to complete. (The size of the uncompressed data may have been + saved by the compressor for this purpose.) The use of Z_FINISH is not + required to perform an inflation in one step. However it may be used to + inform inflate that a faster approach can be used for the single inflate() + call. Z_FINISH also informs inflate to not maintain a sliding window if the + stream completes, which reduces inflate's memory footprint. If the stream + does not complete, either because not all of the stream is provided or not + enough output space is provided, then a sliding window will be allocated and + inflate() can be called again to continue the operation as if Z_NO_FLUSH had + been used. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the effects of the flush parameter in this implementation are + on the return value of inflate() as noted below, when inflate() returns early + when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of + memory for a sliding window when Z_FINISH is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the Adler-32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the Adler-32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed Adler-32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() can decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically, if requested when + initializing with inflateInit2(). Any information contained in the gzip + header is not retained unless inflateGetHeader() is used. When processing + gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output + produced so far. The CRC-32 is checked against the gzip trailer, as is the + uncompressed length, modulo 2^32. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value, in which case strm->msg points to a string with a more specific + error), Z_STREAM_ERROR if the stream structure was inconsistent (for example + next_in or next_out was Z_NULL, or the state was inadvertently written over + by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR + if no progress was possible or if there was not enough room in the output + buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may + then call inflateSync() to look for a good compression block if a partial + recovery of the data is to be attempted. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state + was inconsistent. +*/ + + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by the + caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + For the current implementation of deflate(), a windowBits value of 8 (a + window size of 256 bytes) is not supported. As a result, a request for 8 + will result in 9 (a 512-byte window). In that case, providing 8 to + inflateInit2() will result in an error when the zlib header with 9 is + checked against the initialization of inflate(). The remedy is to not use 8 + with deflateInit2() with this initialization, or at least in that case use 9 + with inflateInit2(). + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute a check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), no + header crc, and the operating system will be set to the appropriate value, + if the operating system was determined at compile time. If a gzip stream is + being written, strm->adler is a CRC-32 instead of an Adler-32. + + For raw deflate or gzip encoding, a request for a 256-byte window is + rejected as invalid, since only the zlib header provides a means of + transmitting the window size to the decompressor. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but is + slow and reduces compression ratio; memLevel=9 uses maximum memory for + optimal speed. The default value is 8. See zconf.h for total memory usage + as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as + fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The + strategy parameter only affects the compression ratio but not the + correctness of the compressed output even if it is not set appropriately. + Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler + decoder for special applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid + method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is + incompatible with the version assumed by the caller (ZLIB_VERSION). msg is + set to null if there is no error message. deflateInit2 does not perform any + compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. When using the zlib format, this + function must be called immediately after deflateInit, deflateInit2 or + deflateReset, and before any call of deflate. When doing raw deflate, this + function must be called either before any call of deflate, or immediately + after the completion of a deflate block, i.e. after all input has been + consumed and all output has been delivered when using any of the flush + options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The + compressor and decompressor must use exactly the same dictionary (see + inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size + provided in deflateInit or deflateInit2. Thus the strings most likely to be + useful should be put at the end of the dictionary, not at the front. In + addition, the current implementation of deflate will use at most the window + size minus 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the Adler-32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The Adler-32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + Adler-32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if not at a block boundary for raw deflate). deflateSetDictionary does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm, + Bytef *dictionary, + uInt *dictLength)); +/* + Returns the sliding dictionary being maintained by deflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If deflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similary, if dictLength is Z_NULL, then it is not set. + + deflateGetDictionary() may return a length less than the window size, even + when more than the window size in input has been provided. It may return up + to 258 bytes less in that case, due to how zlib's implementation of deflate + manages the sliding window and lookahead for matches, where matches can be + up to 258 bytes long. If the application needs the last window-size bytes of + input, then that would need to be saved by the application outside of zlib. + + deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and can + consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, but + does not free and reallocate the internal compression state. The stream + will leave the compression level and any other attributes that may have been + set unchanged. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2(). This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different strategy. + If the compression approach (which is a function of the level) or the + strategy is changed, and if any input has been consumed in a previous + deflate() call, then the input available so far is compressed with the old + level and strategy using deflate(strm, Z_BLOCK). There are three approaches + for the compression levels 0, 1..3, and 4..9 respectively. The new level + and strategy will take effect at the next call of deflate(). + + If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does + not have enough output space to complete, then the parameter change will not + take effect. In this case, deflateParams() can be called again with the + same parameters and more output space to try again. + + In order to assure a change in the parameters on the first try, the + deflate stream should be flushed using deflate() with Z_BLOCK or other flush + request until strm.avail_out is not zero, before calling deflateParams(). + Then no more input data should be provided before the deflateParams() call. + If this is done, the old level and strategy will be applied to the data + compressed before deflateParams(), and the new level and strategy will be + applied to the the data compressed after deflateParams(). + + deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream + state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if + there was not enough output space to complete the compression of the + available input data before a change in the strategy or approach. Note that + in the case of a Z_BUF_ERROR, the parameters are not changed. A return + value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be + retried with more output space. +*/ + +ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() or + deflateInit2(), and after deflateSetHeader(), if used. This would be used + to allocate an output buffer for deflation in a single pass, and so would be + called before deflate(). If that first deflate() call is provided the + sourceLen input bytes, an output buffer allocated to the size returned by + deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed + to return Z_STREAM_END. Note that it is possible for the compressed size to + be larger than the value returned by deflateBound() if flush options other + than Z_FINISH or Z_NO_FLUSH are used. +*/ + +ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm, + unsigned *pending, + int *bits)); +/* + deflatePending() returns the number of bytes and bits of output that have + been generated, but not yet provided in the available output. The bytes not + provided would be due to the available output space having being consumed. + The number of bits of output not provided are between 0 and 7, where they + await more bits to join them in order to fill out a full byte. If pending + or bits are Z_NULL, then those values are not set. + + deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. + */ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the bits + leftover from a previous deflate stream when appending to it. As such, this + function can only be used for raw deflate, and must be used before the first + deflate() call after a deflateInit2() or deflateReset(). bits must be less + than or equal to 16, and that many of the least significant bits of value + will be inserted in the output. + + deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough + room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, + gz_headerp head)); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be zero to request that inflate use the window size in + the zlib header of the compressed stream. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an Adler-32 or a CRC-32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a + CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see + below), inflate() will not automatically decode concatenated gzip streams. + inflate() will return Z_STREAM_END at the end of the gzip stream. The state + would need to be reset to continue decoding a subsequent gzip stream. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit2 does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit2() does not process any header information -- that is + deferred until inflate() is called. +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the Adler-32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called at any + time to set the dictionary. If the provided dictionary is smaller than the + window and there is already data in the window, then the provided dictionary + will amend what's there. The application must insure that the dictionary + that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect Adler-32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm, + Bytef *dictionary, + uInt *dictLength)); +/* + Returns the sliding dictionary being maintained by inflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If inflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similary, if dictLength is Z_NULL, then it is not set. + + inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a possible full flush point (see above + for the description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync searches for a 00 00 FF FF pattern in the compressed data. + All full flush points have this pattern, but not all occurrences of this + pattern are full flush points. + + inflateSync returns Z_OK if a possible full flush point has been found, + Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point + has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. + In the success case, the application may save the current current value of + total_in which indicates where valid compressed data was found. In the + error case, the application may repeatedly call inflateSync, providing more + input each time, until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate the internal decompression state. The + stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, + int windowBits)); +/* + This function is the same as inflateReset, but it also permits changing + the wrap and window size requests. The windowBits parameter is interpreted + the same as it is for inflateInit2. If the window size is changed, then the + memory allocated for the window is freed, and the window will be reallocated + by inflate() if needed. + + inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL), or if + the windowBits parameter is invalid. +*/ + +ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + If bits is negative, then the input stream bit buffer is emptied. Then + inflatePrime() can be called again to put bits in the buffer. This is used + to clear out bits leftover after feeding inflate a block description prior + to feeding inflate codes. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); +/* + This function returns two values, one in the lower 16 bits of the return + value, and the other in the remaining upper bits, obtained by shifting the + return value down 16 bits. If the upper value is -1 and the lower value is + zero, then inflate() is currently decoding information outside of a block. + If the upper value is -1 and the lower value is non-zero, then inflate is in + the middle of a stored block, with the lower value equaling the number of + bytes from the input remaining to copy. If the upper value is not -1, then + it is the number of bits back from the current bit position in the input of + the code (literal or length/distance pair) currently being processed. In + that case the lower value is the number of bytes already emitted for that + code. + + A code is being processed if inflate is waiting for more input to complete + decoding of the code, or if it has completed decoding but is waiting for + more output space to write the literal or match data. + + inflateMark() is used to mark locations in the input data for random + access, which may be at bit positions, and to note those cases where the + output of a code may span boundaries of random access blocks. The current + location in the input stream can be determined from avail_in and data_type + as noted in the description for the Z_BLOCK flush parameter for inflate. + + inflateMark returns the value noted above, or -65536 if the provided + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + gz_headerp head)); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be + used to force inflate() to return immediately after header processing is + complete and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When any + of extra, name, or comment are not Z_NULL and the respective field is not + present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the parameters are invalid, Z_MEM_ERROR if the internal state could not be + allocated, or Z_VERSION_ERROR if the version of the library does not match + the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, + z_const unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is potentially more efficient than + inflate() for file i/o applications, in that it avoids copying between the + output and the sliding window by simply making the window itself the output + buffer. inflate() can be faster on modern CPUs when used with large + buffers. inflateBack() trusts the application to not change the output + buffer passed by the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free the + allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects only + the raw deflate stream to decompress. This is different from the default + behavior of inflate(), which expects a zlib header and trailer around the + deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero -- buf is ignored in that + case -- and inflateBack() will return a buffer error. inflateBack() will + call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. + out() should return zero on success, or non-zero on failure. If out() + returns non-zero, inflateBack() will return with an error. Neither in() nor + out() are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format error + in the deflate stream (in which case strm->msg is set to indicate the nature + of the error), or Z_STREAM_ERROR if the stream was not properly initialized. + In the case of Z_BUF_ERROR, an input or output error can be distinguished + using strm->next_in which will be Z_NULL only if in() returned an error. If + strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning + non-zero. (in() will always be called before out(), so strm->next_in is + assured to be defined if out() returns non-zero.) Note that inflateBack() + cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: ZLIB_DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + +#ifndef Z_SOLO + + /* utility functions */ + +/* + The following utility functions are implemented on top of the basic + stream-oriented functions. To simplify the interface, some default options + are assumed (compression level and memory usage, standard memory allocation + functions). The source code of these utility functions can be modified if + you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed data. compress() is equivalent to compress2() with a level + parameter of Z_DEFAULT_COMPRESSION. + + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed data. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before a + compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be large enough to hold the entire + uncompressed data. (The size of the uncompressed data must have been saved + previously by the compressor and transmitted to the decompressor by some + mechanism outside the scope of this compression library.) Upon exit, destLen + is the actual size of the uncompressed data. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In + the case where there is not enough room, uncompress() will fill the output + buffer with the uncompressed data up to that point. +*/ + +ZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong *sourceLen)); +/* + Same as uncompress, except that sourceLen is a pointer, where the + length of the source is *sourceLen. On return, *sourceLen is the number of + source bytes consumed. +*/ + + /* gzip file access functions */ + +/* + This library supports reading and writing files in gzip (.gz) format with + an interface similar to that of stdio, using the functions that start with + "gz". The gzip format is different from the zlib format. gzip is a gzip + wrapper, documented in RFC 1952, wrapped around a deflate stream. +*/ + +typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ + +/* +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); + + Opens a gzip (.gz) file for reading or writing. The mode parameter is as + in fopen ("rb" or "wb") but can also include a compression level ("wb9") or + a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only + compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' + for fixed code compression as in "wb9F". (See the description of + deflateInit2 for more information about the strategy parameter.) 'T' will + request transparent writing or appending with no compression and not using + the gzip format. + + "a" can be used instead of "w" to request that the gzip stream that will + be written be appended to the file. "+" will result in an error, since + reading and writing to the same gzip file is not supported. The addition of + "x" when writing will create the file exclusively, which fails if the file + already exists. On systems that support it, the addition of "e" when + reading or writing will set the flag to close the file on an execve() call. + + These functions, as well as gzip, will read and decode a sequence of gzip + streams in a file. The append function of gzopen() can be used to create + such a file. (Also see gzflush() for another way to do this.) When + appending, gzopen does not test whether the file begins with a gzip stream, + nor does it look for the end of the gzip streams to begin appending. gzopen + will simply append a gzip stream to the existing file. + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. When + reading, this will be detected automatically by looking for the magic two- + byte gzip header. + + gzopen returns NULL if the file could not be opened, if there was + insufficient memory to allocate the gzFile state, or if an invalid mode was + specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). + errno can be checked to determine if the reason gzopen failed was that the + file could not be opened. +*/ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen associates a gzFile with the file descriptor fd. File descriptors + are obtained from calls like open, dup, creat, pipe or fileno (if the file + has been previously opened with fopen). The mode parameter is as in gzopen. + + The next call of gzclose on the returned gzFile will also close the file + descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor + fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, + mode);. The duplicated descriptor should be saved to avoid a leak, since + gzdopen does not close fd if it fails. If you are using fileno() to get the + file descriptor from a FILE *, then you will have to use dup() to avoid + double-close()ing the file descriptor. Both gzclose() and fclose() will + close the associated file descriptor, so they need to have different file + descriptors. + + gzdopen returns NULL if there was insufficient memory to allocate the + gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not + provided, or '+' was provided), or if fd is -1. The file descriptor is not + used until the next gz* read, write, seek, or close operation, so gzdopen + will not detect if fd is invalid (unless fd is -1). +*/ + +ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); +/* + Set the internal buffer size used by this library's functions. The + default buffer size is 8192 bytes. This function must be called after + gzopen() or gzdopen(), and before any other calls that read or write the + file. The buffer memory allocation is always deferred to the first read or + write. Three times that size in buffer space is allocated. A larger buffer + size of, for example, 64K or 128K bytes will noticeably increase the speed + of decompression (reading). + + The new buffer size also affects the maximum length for gzprintf(). + + gzbuffer() returns 0 on success, or -1 on failure, such as being called + too late. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. Previously provided + data is flushed before the parameter change. + + gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not + opened for writing, Z_ERRNO if there is an error writing the flushed data, + or Z_MEM_ERROR if there is a memory allocation error. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. If + the input file is not in gzip format, gzread copies the given number of + bytes into the buffer directly from the file. + + After reaching the end of a gzip stream in the input, gzread will continue + to read, looking for another gzip stream. Any number of gzip streams may be + concatenated in the input file, and will all be decompressed by gzread(). + If something other than a gzip stream is encountered after a gzip stream, + that remaining trailing garbage is ignored (and no error is returned). + + gzread can be used to read a gzip file that is being concurrently written. + Upon reaching the end of the input, gzread will return with the available + data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then + gzclearerr can be used to clear the end of file indicator in order to permit + gzread to be tried again. Z_OK indicates that a gzip stream was completed + on the last gzread. Z_BUF_ERROR indicates that the input file ended in the + middle of a gzip stream. Note that gzread does not return -1 in the event + of an incomplete gzip stream. This error is deferred until gzclose(), which + will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip + stream. Alternatively, gzerror can be used before gzclose to detect this + case. + + gzread returns the number of uncompressed bytes actually read, less than + len for end of file, or -1 for error. If len is too large to fit in an int, + then nothing is read, -1 is returned, and the error state is set to + Z_STREAM_ERROR. +*/ + +ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems, + gzFile file)); +/* + Read up to nitems items of size size from file to buf, otherwise operating + as gzread() does. This duplicates the interface of stdio's fread(), with + size_t request and return types. If the library defines size_t, then + z_size_t is identical to size_t. If not, then z_size_t is an unsigned + integer type that can contain a pointer. + + gzfread() returns the number of full items read of size size, or zero if + the end of the file was reached and a full item could not be read, or if + there was an error. gzerror() must be consulted if zero is returned in + order to determine if there was an error. If the multiplication of size and + nitems overflows, i.e. the product does not fit in a z_size_t, then nothing + is read, zero is returned, and the error state is set to Z_STREAM_ERROR. + + In the event that the end of file is reached and only a partial item is + available at the end, i.e. the remaining uncompressed data length is not a + multiple of size, then the final partial item is nevetheless read into buf + and the end-of-file flag is set. The length of the partial item read is not + provided, but could be inferred from the result of gztell(). This behavior + is the same as the behavior of fread() implementations in common libraries, + but it prevents the direct use of gzfread() to read a concurrently written + file, reseting and retrying on end-of-file, when size is not 1. +*/ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes written or 0 in case of + error. +*/ + +ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size, + z_size_t nitems, gzFile file)); +/* + gzfwrite() writes nitems items of size size from buf to file, duplicating + the interface of stdio's fwrite(), with size_t request and return types. If + the library defines size_t, then z_size_t is identical to size_t. If not, + then z_size_t is an unsigned integer type that can contain a pointer. + + gzfwrite() returns the number of full items written of size size, or zero + if there was an error. If the multiplication of size and nitems overflows, + i.e. the product does not fit in a z_size_t, then nothing is written, zero + is returned, and the error state is set to Z_STREAM_ERROR. +*/ + +ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the arguments to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written, or a negative zlib error code in case + of error. The number of uncompressed bytes written is limited to 8191, or + one less than the buffer size given to gzbuffer(). The caller should assure + that this limit is not exceeded. If it is exceeded, then gzprintf() will + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf() + because the secure snprintf() or vsnprintf() functions were not available. + This can be determined using zlibCompileFlags(). +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or a + newline character is read and transferred to buf, or an end-of-file + condition is encountered. If any characters are read or if len == 1, the + string is terminated with a null character. If no characters are read due + to an end-of-file or len < 1, then the buffer is left untouched. + + gzgets returns buf which is a null-terminated string, or it returns NULL + for end-of-file or in case of error. If there was an error, the contents at + buf are indeterminate. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. gzputc + returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte or -1 + in case of end of file or error. This is implemented as a macro for speed. + As such, it does not do all of the checking the other functions do. I.e. + it does not check to see if file is NULL, nor whether the structure file + points to has been clobbered or not. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read as the first character + on the next read. At least one character of push-back is allowed. + gzungetc() returns the character pushed, or -1 on failure. gzungetc() will + fail if c is -1, and may fail if a character has been pushed but not read + yet. If gzungetc is used immediately after gzopen or gzdopen, at least the + output buffer size of pushed characters is allowed. (See gzbuffer above.) + The pushed character will be discarded if the stream is repositioned with + gzseek() or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter flush + is as in the deflate() function. The return value is the zlib error number + (see function gzerror below). gzflush is only permitted when writing. + + If the flush parameter is Z_FINISH, the remaining data is written and the + gzip stream is completed in the output. If gzwrite() is called again, a new + gzip stream will be started in the output. gzread() is able to read such + concatenated gzip streams. + + gzflush should be called only when strictly necessary because it will + degrade compression if called too often. +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); + + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); + + Returns the starting position for the next gzread or gzwrite on the given + compressed file. This position represents a number of bytes in the + uncompressed data stream, and is zero when starting, even if appending or + reading a gzip stream from the middle of a file using gzdopen(). + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); + + Returns the current offset in the file being read or written. This offset + includes the count of bytes that precede the gzip stream, for example when + appending or when using gzdopen() for reading. When reading, the offset + does not include as yet unused buffered input. This information can be used + for a progress indicator. On error, gzoffset() returns -1. +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns true (1) if the end-of-file indicator has been set while reading, + false (0) otherwise. Note that the end-of-file indicator is set only if the + read tried to go past the end of the input, but came up short. Therefore, + just like feof(), gzeof() may return false even if there is no more data to + read, in the event that the last read request was for the exact number of + bytes remaining in the input file. This will happen if the input file size + is an exact multiple of the buffer size. + + If gzeof() returns true, then the read functions will return no more data, + unless the end-of-file indicator is reset by gzclearerr() and the input file + has grown since the previous end of file was detected. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Returns true (1) if file is being copied directly while reading, or false + (0) if file is a gzip stream being decompressed. + + If the input file is empty, gzdirect() will return true, since the input + does not contain a gzip stream. + + If gzdirect() is used immediately after gzopen() or gzdopen() it will + cause buffers to be allocated to allow reading the file to determine if it + is a gzip file. Therefore if gzbuffer() is used, it should be called before + gzdirect(). + + When writing, gzdirect() returns true (1) if transparent writing was + requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: + gzdirect() is not needed when writing. Transparent writing must be + explicitly requested, so the application already knows the answer. When + linking statically, using gzdirect() will include all of the zlib code for + gzip file reading and decompression, which may not be desired.) +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file and + deallocates the (de)compression state. Note that once file is closed, you + cannot call gzerror with file, since its structures have been deallocated. + gzclose must not be called more than once on the same file, just as free + must not be called more than once on the same allocation. + + gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a + file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the + last read ended in the middle of a gzip stream, or Z_OK on success. +*/ + +ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); +ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); +/* + Same as gzclose(), but gzclose_r() is only for use when reading, and + gzclose_w() is only for use when writing or appending. The advantage to + using these instead of gzclose() is that they avoid linking in zlib + compression or decompression code that is not used when only reading or only + writing respectively. If gzclose() is used, then both compression and + decompression code will be included the application when linking to a static + zlib library. +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the given + compressed file. errnum is set to zlib error number. If an error occurred + in the file system and not in the compression library, errnum is set to + Z_ERRNO and the application may consult errno to get the exact error code. + + The application must not modify the returned string. Future calls to + this function may invalidate the previously returned string. If file is + closed, then the string previously returned by gzerror will no longer be + available. + + gzerror() should be used to distinguish errors from end-of-file for those + functions above that do not distinguish those cases in their return values. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + +#endif /* !Z_SOLO */ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the compression + library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is Z_NULL, this function returns the + required initial value for the checksum. + + An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed + much faster. + + Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT adler32_z OF((uLong adler, const Bytef *buf, + z_size_t len)); +/* + Same as adler32(), but with a size_t length. +*/ + +/* +ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); + + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note + that the z_off_t type (like off_t) is a signed integer. If len2 is + negative, the result has no meaning or utility. +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. If buf is Z_NULL, this function returns the required + initial value for the crc. Pre- and post-conditioning (one's complement) is + performed within this function so it shouldn't be done by the application. + + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32_z OF((uLong adler, const Bytef *buf, + z_size_t len)); +/* + Same as crc32(), but with a size_t length. +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#ifdef Z_PREFIX_SET +# define z_deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define z_inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#else +# define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#endif + +#ifndef Z_SOLO + +/* gzgetc() macro and its supporting function and exposed data structure. Note + * that the real internal state is much larger than the exposed structure. + * This abbreviated structure exposes just enough for the gzgetc() macro. The + * user should not mess with these exposed elements, since their names or + * behavior could change in the future, perhaps even capriciously. They can + * only be used by the gzgetc() macro. You have been warned. + */ +struct gzFile_s { + unsigned have; + unsigned char *next; + z_off64_t pos; +}; +ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ +#ifdef Z_PREFIX_SET +# undef z_gzgetc +# define z_gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +#else +# define gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +#endif + +/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or + * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if + * both are true, the application gets the *64 functions, and the regular + * functions are changed to 64 bits) -- in case these are set on systems + * without large file support, _LFS64_LARGEFILE must also be true + */ +#ifdef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); + ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); +#endif + +#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) +# ifdef Z_PREFIX_SET +# define z_gzopen z_gzopen64 +# define z_gzseek z_gzseek64 +# define z_gztell z_gztell64 +# define z_gzoffset z_gzoffset64 +# define z_adler32_combine z_adler32_combine64 +# define z_crc32_combine z_crc32_combine64 +# else +# define gzopen gzopen64 +# define gzseek gzseek64 +# define gztell gztell64 +# define gzoffset gzoffset64 +# define adler32_combine adler32_combine64 +# define crc32_combine crc32_combine64 +# endif +# ifndef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +# endif +#else + ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); +#endif + +#else /* Z_SOLO */ + + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); + +#endif /* !Z_SOLO */ + +/* undocumented functions */ +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); +ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void)); +ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); +ZEXTERN int ZEXPORT inflateValidate OF((z_streamp, int)); +ZEXTERN unsigned long ZEXPORT inflateCodesUsed OF ((z_streamp)); +ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp)); +ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); +#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(Z_SOLO) +ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path, + const char *mode)); +#endif +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +ZEXTERN int ZEXPORTVA gzvprintf Z_ARG((gzFile file, + const char *format, + va_list va)); +# endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/uadk/v1/test/hisi_zip_test_sgl/Makefile.am b/uadk/v1/test/hisi_zip_test_sgl/Makefile.am new file mode 100644 index 0000000..7ffd760 --- /dev/null +++ b/uadk/v1/test/hisi_zip_test_sgl/Makefile.am @@ -0,0 +1,14 @@ +AM_CFLAGS=-Wall -O0 -fno-strict-aliasing -I$(top_srcdir)/v1 -I$(top_srcdir) -I$(srcdir) -pthread +AUTOMAKE_OPTIONS = subdir-objects +bin_PROGRAMS=wd_zip_test_sgl sgl_test + +wd_zip_test_sgl_SOURCES=wd_zip_test_sgl.c zip_alg_sgl.c ../smm.c zip_alg_sgl.h wd_sched_sgl.c wd_sched_sgl.h +sgl_test_SOURCES=sgl_test.c sgl_test.h + +if WD_STATIC_DRV +wd_zip_test_sgl_LDADD=../../../.libs/libwd.a +sgl_test_LDADD=../../../.libs/libwd.a +else +wd_zip_test_sgl_LDADD=../../../.libs/libwd.so -lnuma +sgl_test_LDADD=../../../.libs/libwd.so -lnuma +endif diff --git a/uadk/v1/test/hisi_zip_test_sgl/sgl_test.c b/uadk/v1/test/hisi_zip_test_sgl/sgl_test.c new file mode 100644 index 0000000..0add095 --- /dev/null +++ b/uadk/v1/test/hisi_zip_test_sgl/sgl_test.c @@ -0,0 +1,547 @@ +#include +#include +#include +#include +#define __USE_GNU +#include +#include +#include +#include + +#include "../../wd.h" +#include "../../wd_sgl.h" +#include "sgl_test.h" + +void *sgl_addr[4]; + +void sgl_alloc_and_get_test(void *addr); +void sgl_free_and_get_test(void *addr); +void func_test(void *pool, void *sgl); +void func_get_len(struct wd_sgl *sgl); + +int main(int argc, char *argv[]) +{ + int opt; + __u16 sgl_num = 5; + __u32 buf_num = 40; + __u32 buf_size = 4096; + __u8 sge_num_in_sgl = 4; + __u8 buf_num_in_sgl = 3; + __u32 align_size = 64; + + while ((opt = getopt(argc, argv, "a:b:c:d:e:f:")) != -1) { + switch (opt) { + case 'a': + sgl_num = atoi(optarg); + break; + case 'b': + buf_num = atoi(optarg); + break; + case 'c': + buf_size = atoi(optarg); + break; + case 'd': + sge_num_in_sgl = atoi(optarg); + break; + case 'e': + buf_num_in_sgl = atoi(optarg); + break; + case 'f': + align_size = atoi(optarg); + break; + default: + fprintf(stderr, "./sgl [-a sgl_num] [-b buf_num] [-c buf_size] [-d sge_num_in_sgl] [-e buf_num_in_sgl] [-f align_size]\n"); + return -1; + } + } +fprintf(stderr, "sgl_num = %hu, buf_num = %u, buf_size = %u.\nsge_num_in_sgl = %hhu, buf_num_in_sgl = %hhu, align_size = %u.\n\n", + sgl_num, buf_num, buf_size, sge_num_in_sgl, buf_num_in_sgl, align_size); + + struct wd_queue *q; + struct wd_sglpool_setup sp; + __u32 free_sgl_num; + void *sgl_pool; + int ret; +#if 0 + pthread_t test_thrds[2]; + int loop = 1; +#endif + + q = calloc(1, sizeof(struct wd_queue)); + if (q == NULL) { + ret = -ENOMEM; + fprintf(stderr, "alloc q fail, ret =%d\n", ret); + return -1;; + } + + q->capa.alg = "zlib"; + q->capa.latency = 0; + q->capa.throughput = 0; + ret = wd_request_queue(q); + if (ret) { + fprintf(stderr, "wd_request_queue fail, ret =%d\n", ret); + free(q); + } + + sp.buf_size = buf_size; // 128K + sp.align_size = align_size; + sp.sge_num_in_sgl = sge_num_in_sgl; + sp.buf_num_in_sgl = buf_num_in_sgl; + sp.sgl_num = sgl_num; + sp.buf_num = buf_num; + //sp.buf_num = sp.buf_num_in_sgl * sp.sgl_num + sp.sgl_num + 2; + /* 创建sgl pool */ + sgl_pool = wd_sglpool_create(q, &sp); + if (!sgl_pool) { + printf("failed to create sgl pool.\n"); + wd_release_queue(q); + free(q); + return -1; + } + printf("sgl_pool = %p\n", sgl_pool); + + /* 获取sgl pool中空闲的sgl */ + ret = wd_get_free_sgl_num(sgl_pool, &free_sgl_num); + if (ret) + printf("test: failed to alloc sgl.\n"); + printf("free_sgl_num = %d\n", free_sgl_num); + + + sgl_addr[0] = wd_alloc_sgl(sgl_pool, 4096); + sgl_addr[1] = wd_alloc_sgl(sgl_pool, 4096); + sgl_addr[2] = wd_alloc_sgl(sgl_pool, 4096); + sgl_addr[3] = wd_alloc_sgl(sgl_pool, 4096); + /* 合并sgl */ + ret = wd_sgl_merge(sgl_addr[0], sgl_addr[1]); + if (ret) + printf("test: wd_sgl_merge failed.\n"); + + printf("after merge sgl_addr[0] and sgl_addr[1] ...\n"); + +#if 1 + func_test(sgl_pool, sgl_addr[0]); + char a[5016] = { 0 }; + char b[10000] = { 0 }; + char c[50000] = { 0 }; + memset(a, 'f', sizeof(a)); + +#endif + + ret = wd_sgl_cp_from_pbuf(sgl_addr[2], 1000, a, sizeof(a)); + if (ret < 0) + printf("a coypy failed!\n"); + printf("sgl_addr[2]: coypy sz = %ld.\n", (ret == 0) ? sizeof(a) : ret); + func_get_len(sgl_addr[2]); + + ret = wd_sgl_cp_from_pbuf(sgl_addr[3], 2000, a, sizeof(a)); + if (ret < 0) + printf("a coypy failed!\n"); + printf("sgl_addr[3]: coypy sz = %ld.\n", (ret == 0) ? sizeof(a) : ret); + func_get_len(sgl_addr[3]); + + ret = wd_sgl_merge(sgl_addr[2], sgl_addr[3]); + if (ret) + printf("test: wd_sgl_merge failed.\n"); + + printf("after merge sgl_addr[2] and sgl_addr[3] ...\n"); + func_get_len(sgl_addr[3]); + func_get_len(sgl_addr[2]); + + wd_free_sgl(sgl_pool, sgl_addr[2]); + wd_free_sgl(sgl_pool, sgl_addr[3]); + wd_free_sgl(sgl_pool, sgl_addr[2]); + +printf("\n ......... wd_sgl_cp_from_pbuf start ........ \n"); + ret = wd_sgl_cp_from_pbuf(sgl_addr[0], 0, a, sizeof(a)); + if (ret < 0) + printf("a coypy failed!\n"); + printf("1 coypy sz = %ld.\n", (ret == 0) ? sizeof(a) : ret); + func_get_len(sgl_addr[0]); + func_get_len(sgl_addr[1]); + + ret = wd_sgl_cp_from_pbuf(sgl_addr[0], 0, b, sizeof(b)); + if (ret < 0) + printf("b coypy failed!\n"); + printf("2 coypy sz = %ld.\n", (ret == 0) ? sizeof(b) : ret); + func_get_len(sgl_addr[0]); + func_get_len(sgl_addr[1]); + + ret = wd_sgl_cp_from_pbuf(sgl_addr[0], 0, c, sizeof(c)); + if (ret < 0) + printf("c coypy failed!\n"); + printf("3 coypy sz = %ld.\n", (ret == 0) ? sizeof(c) : ret); + func_get_len(sgl_addr[0]); + func_get_len(sgl_addr[1]); + +printf("\n ......... test 1 ........ \n"); +#if 1 + ret = wd_sgl_cp_from_pbuf(sgl_addr[0], 2407, a, sizeof(a)); + if (ret < 0) + printf("a coypy failed!\n"); + printf("1 coypy sz = %ld.\n", (ret == 0) ? sizeof(a) : ret); + func_get_len(sgl_addr[0]); + func_get_len(sgl_addr[1]); + + ret = wd_sgl_cp_from_pbuf(sgl_addr[0], 2407, b, sizeof(b)); + if (ret < 0) + printf("b coypy failed!\n"); + printf("2 coypy sz = %ld.\n", (ret == 0) ? sizeof(b) : ret); + func_get_len(sgl_addr[0]); + func_get_len(sgl_addr[1]); + + ret = wd_sgl_cp_from_pbuf(sgl_addr[0], 2407, c, sizeof(c)); + if (ret < 0) + printf("c coypy failed!\n"); + printf("3 coypy sz = %ld.\n", (ret == 0) ? sizeof(c) : ret); + func_get_len(sgl_addr[0]); + func_get_len(sgl_addr[1]); + +printf("\n ......... test 2 ........ \n"); + + ret = wd_sgl_cp_from_pbuf(sgl_addr[0], 4000, a, sizeof(a)); + if (ret < 0) + printf("a coypy failed!\n"); + printf("1 coypy sz = %ld.\n", (ret == 0) ? sizeof(a) : ret); + func_get_len(sgl_addr[0]); + func_get_len(sgl_addr[1]); + + ret = wd_sgl_cp_from_pbuf(sgl_addr[0], 4000, b, sizeof(b)); + if (ret < 0) + printf("b coypy failed!\n"); + printf("2 coypy sz = %ld.\n", (ret == 0) ? sizeof(b) : ret); + func_get_len(sgl_addr[0]); + func_get_len(sgl_addr[1]); + + ret = wd_sgl_cp_from_pbuf(sgl_addr[0], 4000, c, sizeof(c)); + if (ret < 0) + printf("c coypy failed!\n"); + printf("3 coypy sz = %ld.\n", (ret == 0) ? sizeof(c) : ret); + func_get_len(sgl_addr[0]); + func_get_len(sgl_addr[1]); + + printf("\n ......... test 3 ........ \n"); + + ret = wd_sgl_cp_from_pbuf(sgl_addr[0], 6000, a, sizeof(a)); + if (ret < 0) + printf("a coypy failed!\n"); + printf("1 coypy sz = %ld.\n", (ret == 0) ? sizeof(a) : ret); + func_get_len(sgl_addr[0]); + func_get_len(sgl_addr[1]); + + ret = wd_sgl_cp_from_pbuf(sgl_addr[0], 6000, b, sizeof(b)); + if (ret < 0) + printf("b coypy failed!\n"); + printf("2 coypy sz = %ld.\n", (ret == 0) ? sizeof(b) : ret); + func_get_len(sgl_addr[0]); + func_get_len(sgl_addr[1]); + + ret = wd_sgl_cp_from_pbuf(sgl_addr[0], 6000, c, sizeof(c)); + if (ret < 0) + printf("c coypy failed!\n"); + printf("3 coypy sz = %ld.\n", (ret == 0) ? sizeof(c) : ret); + func_get_len(sgl_addr[0]); + func_get_len(sgl_addr[1]); + +printf("\n ......... test 4 ........ \n"); + + ret = wd_sgl_cp_from_pbuf(sgl_addr[0], 9000, a, sizeof(a)); + if (ret < 0) + printf("a coypy failed!\n"); + printf("1 coypy sz = %ld.\n", (ret == 0) ? sizeof(a) : ret); + func_get_len(sgl_addr[0]); + func_get_len(sgl_addr[1]); + + ret = wd_sgl_cp_from_pbuf(sgl_addr[0], 9000, b, sizeof(b)); + if (ret < 0) + printf("b coypy failed!\n"); + printf("2 coypy sz = %ld.\n", (ret == 0) ? sizeof(b) : ret);\ + func_get_len(sgl_addr[0]); + func_get_len(sgl_addr[1]); + + ret = wd_sgl_cp_from_pbuf(sgl_addr[0], 9000, c, sizeof(c)); + if (ret < 0) + printf("c coypy failed!\n"); + printf("3 coypy sz = %ld.\n", (ret == 0) ? sizeof(c) : ret); + func_get_len(sgl_addr[0]); + func_get_len(sgl_addr[1]); + +printf("\n ......... test 5 ........ \n"); + + ret = wd_sgl_cp_from_pbuf(sgl_addr[0], 10000, a, sizeof(a)); + if (ret < 0) + printf("a coypy failed!\n"); + printf("1 coypy sz = %ld.\n", (ret == 0) ? sizeof(a) : ret); + func_get_len(sgl_addr[0]); + func_get_len(sgl_addr[1]); + + ret = wd_sgl_cp_from_pbuf(sgl_addr[0], 10000, b, sizeof(b)); + if (ret < 0) + printf("b coypy failed!\n"); + printf("2 coypy sz = %ld.\n", (ret == 0) ? sizeof(b) : ret); + func_get_len(sgl_addr[0]); + func_get_len(sgl_addr[1]); + + ret = wd_sgl_cp_from_pbuf(sgl_addr[0], 10000, c, sizeof(c)); + if (ret < 0) + printf("c coypy failed!\n"); + printf("3 coypy sz = %ld.\n", (ret == 0) ? sizeof(c) : ret); + func_get_len(sgl_addr[0]); + func_get_len(sgl_addr[1]); +printf("\n ......... test end ........ \n"); +#endif + +#if 1 +printf("\n ......... wd_sgl_cp_to_pbuf start ........ \n"); + ret = wd_sgl_cp_to_pbuf(sgl_addr[0], 0, a, sizeof(a)); + if (ret < 0) + printf("a coypy failed!\n"); + + ret = wd_sgl_cp_to_pbuf(sgl_addr[0], 0, b, sizeof(b)); + if (ret < 0) + printf("b coypy failed!\n"); + + ret = wd_sgl_cp_to_pbuf(sgl_addr[0], 0, c, sizeof(c)); + if (ret < 0) + printf("c coypy failed!\n"); + +printf("\n ......... test 1 ........ \n"); + + ret = wd_sgl_cp_to_pbuf(sgl_addr[0], 2407, a, sizeof(a)); + if (ret < 0) + printf("a coypy failed!\n"); + + ret = wd_sgl_cp_to_pbuf(sgl_addr[0], 2407, b, sizeof(b)); + if (ret < 0) + printf("b coypy failed!\n"); + + ret = wd_sgl_cp_to_pbuf(sgl_addr[0], 2407, c, sizeof(c)); + if (ret < 0) + printf("c coypy failed!\n"); + +printf("\n ......... test 2 ........ \n"); + + ret = wd_sgl_cp_to_pbuf(sgl_addr[0], 4000, a, sizeof(a)); + if (ret < 0) + printf("a coypy failed!\n"); + + ret = wd_sgl_cp_to_pbuf(sgl_addr[0], 4000, b, sizeof(b)); + if (ret < 0) + printf("b coypy failed!\n"); + + ret = wd_sgl_cp_to_pbuf(sgl_addr[0], 4000, c, sizeof(c)); + if (ret < 0) + printf("c coypy failed!\n"); + + printf("\n ......... test 3 ........ \n"); + + ret = wd_sgl_cp_to_pbuf(sgl_addr[0], 6000, a, sizeof(a)); + if (ret < 0) + printf("a coypy failed!\n"); + + ret = wd_sgl_cp_to_pbuf(sgl_addr[0], 6000, b, sizeof(b)); + if (ret < 0) + printf("b coypy failed!\n"); + + ret = wd_sgl_cp_to_pbuf(sgl_addr[0], 6000, c, sizeof(c)); + if (ret < 0) + printf("c coypy failed!\n"); + +printf("\n ......... test 4 ........ \n"); + + ret = wd_sgl_cp_to_pbuf(sgl_addr[0], 9000, a, sizeof(a)); + if (ret < 0) + printf("a coypy failed!\n"); + + ret = wd_sgl_cp_to_pbuf(sgl_addr[0], 9000, b, sizeof(b)); + if (ret < 0) + printf("b coypy failed!\n"); + + ret = wd_sgl_cp_to_pbuf(sgl_addr[0], 9000, c, sizeof(c)); + if (ret < 0) + printf("c coypy failed!\n"); + +printf("\n ......... test 5 ........ \n"); + + ret = wd_sgl_cp_to_pbuf(sgl_addr[0], 10000, a, sizeof(a)); + if (ret < 0) + printf("a coypy failed!\n"); + + ret = wd_sgl_cp_to_pbuf(sgl_addr[0], 10000, b, sizeof(b)); + if (ret < 0) + printf("b coypy failed!\n"); + + ret = wd_sgl_cp_to_pbuf(sgl_addr[0], 10000, c, sizeof(c)); + if (ret < 0) + printf("c coypy failed!\n"); + +printf("\n ......... test end ........ \n"); +#endif + +#if 0 + ret = pthread_create(&test_thrds[0], NULL, (void *)sgl_alloc_and_get_test, sgl_pool); + if (ret) { + printf("Create 1'th thread fail!\n"); + return ret; + } + + ret = pthread_create(&test_thrds[1], NULL, (void *)sgl_free_and_get_test, sgl_pool); + if (ret) { + printf("Create 2'th thread fail!\n"); + return ret; + } + + while (loop--) + sleep(2); + + for (i = 0; i < 2; i++) { + ret = pthread_join(test_thrds[i], NULL); + if (ret) { + printf("Join %dth thread fail!\n", i); + return ret; + } + } +#endif + wd_free_sgl(sgl_pool, sgl_addr[1]); + wd_free_sgl(sgl_pool, sgl_addr[0]); + wd_free_sgl(sgl_pool, sgl_addr[0]); + + func_test(sgl_pool, sgl_addr[0]); + wd_sglpool_destroy(sgl_pool); + wd_sglpool_destroy(sgl_pool); + wd_release_queue(q); + free(q); + + return 0; +} + +void func_get_len(struct wd_sgl *sgl) +{ + __u32 dtsize; + int ret, i; + + ret = wd_get_sgl_datalen(sgl, &dtsize); + if (ret) { + printf("wd_get_sgl_datalen failed!\n"); + return; + } + printf("wd_get_sgl_datalen ok: dtsize = %u!\n", dtsize); + for (i = 1; i <= 3; i++) { + ret = wd_get_sge_datalen(sgl, i, &dtsize); + if (ret) { + printf("wd_get_sgl_datalen failed!\n"); + return; + } + printf(" wd_get_sge_datalen ok: dtsize = %u!\n", dtsize); + } +} + +void sgl_alloc_and_get_test(void *pool) +{ + __u32 free_sgl_num = 0; + int ret; + + /* 分配sgl */ + sgl_addr[0] = wd_alloc_sgl(pool, 10000); + printf("%s, after alloc a sgl ...\n", __func__); + + /* 获取sgl pool中空闲的sgl */ + ret = wd_get_free_sgl_num(pool, &free_sgl_num); + if (ret) + printf("%s, test: failed to alloc sgl.\n", __func__); + printf("%s, get free_sgl_num = %d\n", __func__, free_sgl_num); + + /* 分配sgl */ + sgl_addr[1] = wd_alloc_sgl(pool, 10000); + printf("%s, after alloc a sgl ...\n", __func__); + + sgl_addr[2] = wd_alloc_sgl(pool, 10000); + //sgl_addr[3] = wd_alloc_sgl(pool, 10000); + func_test(pool, sgl_addr[0]); +} + +void sgl_free_and_get_test(void *pool) +{ + __u32 free_sgl_num; + int ret; + + ret = wd_get_free_sgl_num(pool, &free_sgl_num); + if (ret) + printf("test: failed to alloc sgl.\n"); + printf("%s, free_sgl_num = %d\n", __func__, free_sgl_num); + + if (sgl_addr[0] && sgl_addr[1]) { + /* 合并sgl */ + ret = wd_sgl_merge(sgl_addr[0], sgl_addr[1]); + if (ret) + printf("test: wd_sgl_merge failed.\n"); + + printf("after merge 2 sgls ...\n"); + sleep(2); + + func_test(pool, sgl_addr[0]); + } + + wd_free_sgl(pool, sgl_addr[0]); + func_test(pool, sgl_addr[0]); + + //wd_free_sgl(pool, sgl_addr[0]); + //wd_free_sgl(pool, sgl_addr[1]); + wd_free_sgl(pool, sgl_addr[2]); +} + +void func_test(void *pool, void *sgl) +{ + void *addr; + __u32 sz; + size_t mem_sz; + __u32 free_num, num; + int ret; + + printf("..........start .................\n"); + printf(".................................\n"); + addr = wd_get_last_sge_buf(sgl); + printf("wd_get_last_sge_buf - sgl = %p\n", addr); + + addr = wd_get_first_sge_buf(sgl); + printf("wd_get_first_sge_buf - sgl = %p\n", addr); + + ret = wd_get_sgl_sge_num(sgl); + printf("wd_get_sgl_sge_num = %d\n",ret); + + ret = wd_get_sgl_buf_num(sgl); + printf("wd_get_sgl_buf_num = %d\n", ret); + + addr = wd_get_sge_buf(sgl, 2); + printf("wd_get_sge_buf - sgl_addr[1].buf = %p\n", addr); + + ret = wd_get_sgl_buf_sum(sgl); + printf("wd_get_sgl_buf_sum = %d\n", ret); + + ret = wd_get_sgl_mem_size(sgl, &mem_sz); + printf("wd_get_sgl_mem_size = %ld\n", mem_sz); + + ret = wd_get_free_sgl_num(pool, &free_num); + if (ret) + printf("wd_get_free_sgl_num err."); + else + printf("wd_get_free_sgl_num = %d\n", free_num); + + ret = wd_get_free_sgl_sge_num(sgl, &num); + printf("wd_get_free_sgl_sge_num = %u\n", num); + + ret = wd_get_free_buf_num(pool, &free_num); + printf("wd_get_free_buf_num = %d\n", free_num); + + __u32 dtsize; + ret = wd_get_sgl_datalen(sgl, &dtsize); + printf("wd_get_sgl_datalen = %d\n", dtsize); + + ret = wd_get_sge_datalen(sgl, 2, &dtsize); + printf("wd_get_sge_datalen = %d\n", dtsize); + + ret = wd_get_sgl_bufsize(sgl, &sz); + printf("wd_get_sgl_bufsize = %d\n", sz); + + printf(".................................\n"); + printf("..............end...................\n\n"); +} diff --git a/uadk/v1/test/hisi_zip_test_sgl/sgl_test.h b/uadk/v1/test/hisi_zip_test_sgl/sgl_test.h new file mode 100644 index 0000000..1b46219 --- /dev/null +++ b/uadk/v1/test/hisi_zip_test_sgl/sgl_test.h @@ -0,0 +1,4 @@ +#ifndef __SGL_TEST_H__ +#define __SGL_TEST_H__ + +#endif /* __SGL_TEST_H__ */ diff --git a/uadk/v1/test/hisi_zip_test_sgl/wd_sched_sgl.c b/uadk/v1/test/hisi_zip_test_sgl/wd_sched_sgl.c new file mode 100644 index 0000000..3163756 --- /dev/null +++ b/uadk/v1/test/hisi_zip_test_sgl/wd_sched_sgl.c @@ -0,0 +1,353 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#include "config.h" +#include "wd_util.h" +#include "wd_sched_sgl.h" +#include "wd_bmm.h" +#include "wd_sgl.h" + +#define EXTRA_SIZE 4096 +#define WD_WAIT_MS 1000 + +static int __init_cache(struct wd_scheduler *sched, int data_fmt) +{ + int i; + int ret = -ENOMEM; + struct q_info *qinfo; + void *pool; + + sched->msgs = calloc(sched->msg_cache_num, sizeof(*sched->msgs)); + if (!sched->msgs) { + WD_ERR("calloc for sched->msgs fail!\n"); + return ret; + } + sched->stat = calloc(sched->q_num, sizeof(*sched->stat)); + if (!sched->stat) { + WD_ERR("calloc for sched->stat fail!\n"); + goto err_with_msgs; + } + qinfo = sched->qs[0].qinfo; + pool = qinfo->br.usr; + for (i = 0; i < sched->msg_cache_num; i++) { + if (data_fmt == WD_FLAT_BUF) { /* use pbuffer */ + sched->msgs[i].data_in = wd_alloc_blk(pool); + sched->msgs[i].data_out = wd_alloc_blk(pool); + if (!sched->msgs[i].data_in || !sched->msgs[i].data_out) { + dbg("not enough data ss_region memory " + "for cache %d (bs=%d)\n", i, sched->msg_data_size); + goto err_with_stat; + } + } else { /* use sgl */ + sched->msgs[i].data_in = wd_alloc_sgl(pool, sched->msg_data_size); + sched->msgs[i].data_out = wd_alloc_sgl(pool, sched->msg_data_size); + if (!sched->msgs[i].data_in || !sched->msgs[i].data_out) { + dbg("not enough data ss_region memory " + "for cache %d (bs=%d)\n", i, sched->msg_data_size); + goto err_with_stat; + } + } + + if (sched->init_cache) + sched->init_cache(sched, i, data_fmt); + } + + return 0; + +err_with_stat: + free(sched->stat); + sched->stat = NULL; +err_with_msgs: + free(sched->msgs); + sched->msgs = NULL; + return ret; +} + +static void __fini_cache(struct wd_scheduler *sched, int data_fmt) +{ + struct q_info *qinfo = sched->qs[0].qinfo; + unsigned int flags = qinfo->dev_flags; + void *pool; + int i; + + if (sched->stat) { + free(sched->stat); + sched->stat = NULL; + } + if (!(flags & WD_UACCE_DEV_PASID)) { + pool = qinfo->br.usr; + if (pool) { + if (data_fmt == WD_FLAT_BUF) { /* use pbuffer */ + for (i = 0; i < sched->msg_cache_num; i++) { + if (sched->msgs[i].data_in) + wd_free_blk(pool, sched->msgs[i].data_in); + if (sched->msgs[i].data_out) + wd_free_blk(pool, sched->msgs[i].data_out); + } + wd_blkpool_destroy(pool); + } else { /* use sgl */ + for (i = 0; i < sched->msg_cache_num; i++) { + if (sched->msgs[i].data_in) + wd_free_sgl(pool, sched->msgs[i].data_in); + if (sched->msgs[i].data_out) + wd_free_sgl(pool, sched->msgs[i].data_out); + } + wd_sglpool_destroy(pool); + } + } + } + if (sched->msgs) { + free(sched->msgs); + sched->msgs = NULL; + } +} + +static int wd_sched_preinit(struct wd_scheduler *sched, int data_fmt) +{ + int ret, i, j; + unsigned int flags = 0; + struct q_info *qinfo; + struct wd_blkpool_setup mm_setup; + struct wd_sglpool_setup sp; + void *pool; + + for (i = 0; i < sched->q_num; i++) { + ret = wd_request_queue(&sched->qs[i]); + if (ret) { + WD_ERR("fail to request queue!\n"); + goto out_with_queues; + } + } + + if (!sched->ss_region_size) + sched->ss_region_size = EXTRA_SIZE + /* add 1 page extra */ + sched->msg_cache_num * (sched->msg_data_size << 0x1); + + qinfo = sched->qs[0].qinfo; + flags = qinfo->dev_flags; + if (flags & WD_UACCE_DEV_PASID) { + sched->ss_region = malloc(sched->ss_region_size); + if (!sched->ss_region) { + WD_ERR("fail to alloc sched ss region mem!\n"); + ret = -ENOMEM; + goto out_with_queues; + } + } else { + if (data_fmt == WD_FLAT_BUF) { /* use pbuffer*/ + memset(&mm_setup, 0, sizeof(mm_setup)); + mm_setup.block_size = sched->msg_data_size; + mm_setup.block_num = sched->msg_cache_num << 0x1; /* in and out */ + mm_setup.align_size = 128; + pool = wd_blkpool_create(&sched->qs[0], &mm_setup); + if (!pool) { + WD_ERR("%s(): create pool fail!\n", __func__); + ret = -ENOMEM; + goto out_with_queues; + } + qinfo->br.alloc = (void *)wd_alloc_blk; + qinfo->br.free = (void *)wd_free_blk; + qinfo->br.iova_map = (void *)wd_blk_iova_map; + qinfo->br.iova_unmap = (void *)wd_blk_iova_unmap; + qinfo->br.usr = pool; + } else { /* use sgl*/ + memset(&sp, 0, sizeof(sp)); + sp.buf_size = sched->msg_data_size / 10; + sp.align_size = 64; + sp.sge_num_in_sgl = 60; + sp.buf_num_in_sgl = sp.sge_num_in_sgl; + sp.sgl_num = 3 * sched->msg_cache_num; + sp.buf_num = sp.buf_num_in_sgl * sp.sgl_num + sp.sgl_num * 2; + + pool = wd_sglpool_create(&sched->qs[0], &sp); + if (!pool) { + WD_ERR("%s(): create pool fail!\n", __func__); + ret = -ENOMEM; + goto out_with_queues; + } + qinfo->br.alloc = (void *)wd_alloc_sgl; + qinfo->br.free = (void *)wd_free_sgl; + qinfo->br.iova_map = (void *)wd_sgl_iova_map; + qinfo->br.iova_unmap = (void *)wd_sgl_iova_unmap; + qinfo->br.usr = pool; + } + + } + + return 0; + +out_with_queues: + if (flags & WD_UACCE_DEV_PASID) { + if (sched->ss_region) { + free(sched->ss_region); + sched->ss_region = NULL; + } + } + for (j = i-1; j >= 0; j--) + wd_release_queue(&sched->qs[j]); + return ret; +} + + +int wd_sched_init(struct wd_scheduler *sched, int data_fmt) +{ + int ret, j, k; + unsigned int flags; + struct q_info *qinfo; + + ret = wd_sched_preinit(sched, data_fmt); + if (ret < 0) + return -EINVAL; + + qinfo = sched->qs[0].qinfo; + flags = qinfo->dev_flags; + if (!(flags & WD_UACCE_DEV_PASID)) { + for (k = 1; k < sched->q_num; k++) { + ret = wd_share_reserved_memory(&sched->qs[0], + &sched->qs[k]); + if (ret) { + WD_ERR("fail to share queue reserved mem!\n"); + goto out_with_queues; + } + } + } + + sched->cl = sched->msg_cache_num; + + ret = __init_cache(sched, data_fmt); + if (ret) { + WD_ERR("fail to init caches!\n"); + goto out_with_queues; + } + + return 0; + +out_with_queues: + if (flags & WD_UACCE_DEV_PASID) { + if (sched->ss_region) { + free(sched->ss_region); + sched->ss_region = NULL; + } + } + for (j = sched->q_num - 1; j >= 0; j--) + wd_release_queue(&sched->qs[j]); + return ret; +} + +void wd_sched_fini(struct wd_scheduler *sched, int data_fmt) +{ + int i; + struct q_info *qinfo = sched->qs[0].qinfo; + unsigned int flags = qinfo->dev_flags; + + __fini_cache(sched, data_fmt); + if (flags & WD_UACCE_DEV_PASID) { + if (sched->ss_region) { + free(sched->ss_region); + sched->ss_region = NULL; + } + } + + for (i = sched->q_num - 1; i >= 0; i--) + wd_release_queue(&sched->qs[i]); +} + +static int __sync_send(struct wd_scheduler *sched) +{ + int ret; + + dbg("send ci(%d) to q(%d): %p\n", sched->c_h, sched->q_h, + sched->msgs[sched->c_h].msg); + do { + sched->stat[sched->q_h].send++; + ret = wd_send(&sched->qs[sched->q_h], + sched->msgs[sched->c_h].msg); + if (ret == -EBUSY) { + usleep(1); + sched->stat[sched->q_h].send_retries++; + continue; + } + if (ret) + return ret; + } while (ret); + + sched->q_h = (sched->q_h + 1) % sched->q_num; + return 0; +} + +static int __sync_wait(struct wd_scheduler *sched) +{ + void *recv_msg = NULL; + int ret; + + dbg("recv, ci(%d) from q(%d): %p\n", sched->c_t, sched->q_t, + sched->msgs[sched->c_h].msg); + do { + sched->stat[sched->q_t].recv++; + ret = wd_recv(&sched->qs[sched->q_t], &recv_msg); + if (ret == 0) { + sched->stat[sched->q_t].recv_retries++; + continue; + } else if (ret == -WD_EIO || ret == -WD_HW_EACCESS) + return ret; + + if (recv_msg != sched->msgs[sched->c_t].msg) { + fprintf(stderr, "recv msg %p and input %p mismatch\n", + recv_msg, sched->msgs[sched->c_t].msg); + return -EINVAL; + } + } while (!ret); + + sched->q_t = (sched->q_t + 1) % sched->q_num; + return 0; +} + +/* return number of msg in the sent cache or negative errno */ +int wd_sched_work(struct wd_scheduler *sched, int remained) +{ + int ret; + +#define MOV_INDEX(id) do { \ + sched->id = (sched->id + 1) % sched->msg_cache_num; \ +} while (0) + + dbg("sched: cl=%d, data_remained=%d\n", sched->cl, remained); + + if (sched->cl && remained) { + ret = sched->input(&sched->msgs[sched->c_h], sched->priv); + if (ret) + return ret; + + ret = __sync_send(sched); + if (ret) + return ret; + + MOV_INDEX(c_h); + sched->cl--; + } else { + ret = __sync_wait(sched); + if (ret) + return ret; + + ret = sched->output(&sched->msgs[sched->c_t], sched->priv); + if (ret) + return ret; + + MOV_INDEX(c_t); + sched->cl++; + } + + return sched->cl; +} \ No newline at end of file diff --git a/uadk/v1/test/hisi_zip_test_sgl/wd_sched_sgl.h b/uadk/v1/test/hisi_zip_test_sgl/wd_sched_sgl.h new file mode 100644 index 0000000..57911d2 --- /dev/null +++ b/uadk/v1/test/hisi_zip_test_sgl/wd_sched_sgl.h @@ -0,0 +1,71 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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 common drv header define the unified interface for wd */ +#ifndef __WD_SCHED_SGL_H__ +#define __WD_SCHED_SGL_H__ + +#include "../../wd.h" + +struct wd_msg { + void *data_in; + void *data_out; + void *msg; +}; + +struct wd_scheduler { + struct wd_queue *qs; + int q_num; + + void *ss_region; + size_t ss_region_size; + + struct wd_msg *msgs; + int msg_cache_num; + unsigned int msg_data_size; + + /* cache head, cache tail */ + int c_h, c_t; + /* queue head, queue tail */ + int q_h, q_t; + /* cache left */ + int cl; + + void (*init_cache)(struct wd_scheduler *sched, int i, int data_fmt); + int (*input)(struct wd_msg *msg, void *priv); + int (*output)(struct wd_msg *msg, void *priv); + + void *priv; + + /* statistic */ + struct { + int send; + int send_retries; + int recv; + int recv_retries; + } *stat; +}; + +extern int wd_sched_init(struct wd_scheduler *sched, int data_fmt); +extern void wd_sched_fini(struct wd_scheduler *sched, int data_fmt); +extern int wd_sched_work(struct wd_scheduler *sched, int have_input); + +static inline int wd_sched_empty(struct wd_scheduler *sched) +{ + return sched->cl == sched->msg_cache_num; +} + +#endif diff --git a/uadk/v1/test/hisi_zip_test_sgl/wd_zip_test_sgl.c b/uadk/v1/test/hisi_zip_test_sgl/wd_zip_test_sgl.c new file mode 100644 index 0000000..331b11b --- /dev/null +++ b/uadk/v1/test/hisi_zip_test_sgl/wd_zip_test_sgl.c @@ -0,0 +1,703 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#define __USE_GNU +#include +#include +#include +#include + +#include "../../wd.h" +#include "zip_alg_sgl.h" +#include "../../wd_comp.h" +#include "../../wd_sgl.h" +#include "../smm.h" + +#ifdef DEBUG_LOG +#define dbg(msg, ...) fprintf(stderr, msg, ##__VA_ARGS__) +#else +#define dbg(msg, ...) +#endif + +enum mode { + MODE_BLOCK, + MODE_STREAM, + ASYNC, +}; + +struct test_zip_pthread_dt { + int cpu_id; + int thread_num; + int alg_type; + int op_type; + int data_fmt; + int hw_flag; + int blksize; + int iteration; + void *src; + void *dst; + ulong src_len; + ulong dst_len; + float com_time; + float decom_time; +}; + +struct user_comp_tag_info { + int cpu_id; + pid_t tid; + int alg_type; +}; + +#define TEST_MAX_THRD 2048 +#define MAX_CORES 128 + +static pthread_t system_test_thrds[TEST_MAX_THRD]; +static struct test_zip_pthread_dt test_thrds_data[TEST_MAX_THRD]; + +/* bytes of data for a request */ +static int block_size = 512000; +static int req_cache_num = 4; +static int q_num = 1; +static int verify; + +pid_t gettid(void) +{ + return syscall(__NR_gettid); +} + +/* stream mode test thread */ +void *zlib_sys_stream_test_thread(void *args) +{ + int cpu_id, ret; + pid_t tid; + cpu_set_t mask; + struct test_zip_pthread_dt *pdata = args; + int i = pdata->iteration; + + cpu_id = pdata->cpu_id; + tid = gettid(); + + CPU_ZERO(&mask); + if (cpu_id) { + if (cpu_id <= 0 || cpu_id > MAX_CORES) { + dbg("set cpu no affinity!\n"); + goto therad_no_affinity; + } + CPU_SET(cpu_id, &mask); + if (pthread_setaffinity_np(pthread_self(), + sizeof(mask), &mask) < 0) { + perror("pthread_setaffinity fail!\n"); + return NULL; + } + } + +therad_no_affinity: + + dbg("%s entry thread_id=%d\n", __func__, (int)tid); + do { + if (pdata->op_type == WCRYPTO_DEFLATE) { + if (pdata->hw_flag) { + ret = hw_stream_compress(pdata->alg_type, + pdata->blksize, + pdata->dst, + &pdata->dst_len, + pdata->src, + pdata->src_len, + pdata->data_fmt); + if (ret < 0) + WD_ERR("comp fail! id=%d tid=%d ret=%d\n", + cpu_id, (int)tid, ret); + } + } else if (pdata->op_type == WCRYPTO_INFLATE) { + if (pdata->hw_flag) { + ret = hw_stream_decompress(pdata->alg_type, + pdata->blksize, + pdata->dst, + &pdata->dst_len, + pdata->src, + pdata->src_len, + pdata->data_fmt); + if (ret < 0) + WD_ERR("decomp fail! id=%d tid=%d ret=%d\n", + cpu_id, (int)tid, ret); + } + } + + if (verify) { + ret = hw_stream_decompress(pdata->alg_type, + pdata->blksize, + pdata->src, + &pdata->src_len, + pdata->dst, + pdata->dst_len, + pdata->data_fmt); + if (ret < 0) + WD_ERR("loop verify fail! ret=%d, id=%d\n", + ret, cpu_id); + else + dbg("loop verify success! id=%d\n", cpu_id); + } + + } while (--i); + dbg("%s end thread_id=%d\n", __func__, (int)tid); + + return NULL; + +} + +static int out_len; + +void zip_callback(const void *msg, void *tag) +{ + const struct wcrypto_comp_msg *respmsg = msg; + + out_len = respmsg->produced; + + dbg("[%s], cpu_id =%d consume=%d, produce=%d\n", + __func__, ((struct user_comp_tag_info *)tag)->cpu_id, + respmsg->in_cons, respmsg->produced); + +} + +void *zip_sys_async_test_thread(void *args) +{ + int cpu_id, ret; + cpu_set_t mask; + pid_t tid; + struct test_zip_pthread_dt *pdata = args; + struct user_comp_tag_info u_tag; + int i = pdata->iteration; + size_t ss_region_size; + struct wcrypto_paras *priv; + struct wd_queue *q; + void *zip_ctx; + struct wcrypto_comp_ctx_setup ctx_setup; + struct wcrypto_comp_op_data *opdata; + struct wd_sglpool_setup sp; + void *in, *out, *ss_buf; + void *src = NULL, *dst = NULL; + int loop; + + cpu_id = pdata->cpu_id; + tid = gettid(); + + CPU_ZERO(&mask); + if (cpu_id) { + if (cpu_id <= 0 || cpu_id > MAX_CORES) { + dbg("set cpu no affinity!\n"); + goto therad_no_affinity; + } + CPU_SET(cpu_id, &mask); + if (pthread_setaffinity_np(pthread_self(), + sizeof(mask), &mask) < 0) { + perror("pthread_setaffinity fail!\n"); + return NULL; + } + } + +therad_no_affinity: + + q = calloc(1, sizeof(struct wd_queue)); + if (q == NULL) { + ret = -ENOMEM; + fprintf(stderr, "alloc q fail, ret =%d\n", ret); + goto hw_q_free; + } + memset(&ctx_setup, 0, sizeof(ctx_setup)); + + switch (pdata->alg_type) { + case 0: + ctx_setup.alg_type = WCRYPTO_ZLIB; + q->capa.alg = "zlib"; + break; + case 1: + ctx_setup.alg_type = WCRYPTO_GZIP; + q->capa.alg = "gzip"; + break; + default: + ctx_setup.alg_type = WCRYPTO_ZLIB; + q->capa.alg = "zlib"; + } + ctx_setup.stream_mode = WCRYPTO_COMP_STATELESS; + q->capa.latency = 0; + q->capa.throughput = 0; + priv = &q->capa.priv; + priv->direction = pdata->op_type; + ret = wd_request_queue(q); + if (ret) { + fprintf(stderr, "wd_request_queue fail, ret =%d\n", ret); + goto hw_q_free; + } + SYS_ERR_COND(ret, "wd_request_queue"); + + ss_region_size = 4096 + DMEMSIZE * 2 + HW_CTX_SIZE; + +#ifdef CONFIG_IOMMU_SVA + ss_buf = calloc(1, ss_region_size); +#else + if (pdata->data_fmt == WD_FLAT_BUF) { /* use pbuf */ + ss_buf = wd_reserve_memory(q, ss_region_size); + } else { /* pdata->data_fmt == WD_SGL_BUF, use nosva-sgl */ + sp.buf_size = pdata->src_len / 10; + sp.align_size = 64; + sp.sge_num_in_sgl = 12; + sp.buf_num_in_sgl = sp.sge_num_in_sgl - 1; + sp.sgl_num = 3; + sp.buf_num = sp.buf_num_in_sgl * sp.sgl_num + sp.sgl_num + 2; + ss_buf = wd_sglpool_create(q, &sp); + WD_ERR("ss_buf = %p\n", ss_buf); + } +#endif + if (!ss_buf) { + fprintf(stderr, "fail to reserve %ld dmabuf\n", ss_region_size); + ret = -ENOMEM; + goto release_q; + } + + if (pdata->data_fmt == WD_FLAT_BUF) { /* use pbuf */ + ctx_setup.data_fmt = WD_FLAT_BUF; + ret = smm_init(ss_buf, ss_region_size, 0xF); + if (ret) + goto buf_free; + + src = in = smm_alloc(ss_buf, DMEMSIZE); + dst = out = smm_alloc(ss_buf, DMEMSIZE); + if (in == NULL || out == NULL) { + WD_ERR("not enough data ss_region memory for cache (bs=%d)\n", + DMEMSIZE); + goto buf_free; + } + } else { /* pdata->data_fmt == WD_SGL_BUF, use nosva-sgl */ + ctx_setup.data_fmt = WD_SGL_BUF; + src = in = wd_alloc_sgl(ss_buf, pdata->src_len); + dst = out = wd_alloc_sgl(ss_buf, pdata->src_len); + if (in == NULL || out == NULL) { + WD_ERR("sgl: not enough data ss_region memory for cache (bs=%d)\n", + DMEMSIZE); + goto buf_free; + } + + ctx_setup.br.alloc = (void *)wd_alloc_sgl; + ctx_setup.br.free = (void *)wd_free_sgl; + ctx_setup.br.iova_map = (void *)wd_sgl_iova_map; + ctx_setup.br.iova_unmap = (void *)wd_sgl_iova_unmap; + ctx_setup.br.usr = ss_buf; + } + + ctx_setup.cb = zip_callback; + zip_ctx = wcrypto_create_comp_ctx(q, &ctx_setup); + if (zip_ctx == NULL) { + fprintf(stderr, "zip_alloc_comp_ctx fail, ret =%d\n", ret); + goto buf_free; + } + + opdata = calloc(1, sizeof(struct wcrypto_comp_op_data)); + if (opdata == NULL) { + ret = -ENOMEM; + fprintf(stderr, "alloc opdata fail, ret =%d\n", ret); + goto comp_ctx_free; + } + opdata->in = in; + opdata->out = out; + opdata->stream_pos = WCRYPTO_COMP_STREAM_NEW; + + if (pdata->data_fmt == WD_FLAT_BUF) { /* use pbuf */ + memcpy(src, pdata->src, pdata->src_len); + opdata->avail_out = DMEMSIZE; + } else { /* pdata->data_fmt == WD_SGL_BUF, use nosva-sgl */ + + wd_sgl_cp_from_pbuf((struct wd_sgl *)src, 0, + pdata->src, pdata->src_len); + opdata->avail_out = sp.buf_size * sp.buf_num_in_sgl; + } + opdata->in_len = pdata->src_len; + + u_tag.alg_type = ctx_setup.alg_type; + u_tag.cpu_id = cpu_id; + u_tag.tid = tid; + loop = 10; + int loop1 = 100; + + dbg("%s entry thread_id=%d\n", __func__, (int)tid); + do { + i = pdata->iteration; + do { + ret = wcrypto_do_comp(zip_ctx, opdata, &u_tag); + if (ret == -WD_EBUSY) { + WD_ERR("%s(): asynctest no cache!\n", __func__); + break; + } + + } while (--i); + + while (loop1--) { + ret = wcrypto_comp_poll(q, pdata->iteration); + if (ret < 0) + WD_ERR("poll fail! thread_id=%d, tid=%d. ret:%d\n", + cpu_id, (int)tid, ret); + + if (ret > 0) { + WD_ERR("test poll end, count=%d\n", ret); + break; + } + usleep(10); + } + } while (--loop); + + opdata->produced = out_len; + dbg("%s(): test !,produce=%d\n", __func__, opdata->produced); + + if (pdata->data_fmt == WD_FLAT_BUF) /* use pbuf */ + memcpy(pdata->dst, dst, opdata->produced); + else /* pdata->data_fmt == WD_SGL_BUF, use nosva-sgl */ + wd_sgl_cp_to_pbuf((struct wd_sgl *)dst, 0, pdata->dst, + opdata->produced); + + pdata->dst_len = opdata->produced; + + dbg("%s end thread_id=%d\n", __func__, pdata->cpu_id); + + if (opdata) + free(opdata); + + wcrypto_del_comp_ctx(zip_ctx); + if (pdata->data_fmt == WD_SGL_BUF) { /* use nosva-sgl */ + wd_free_sgl(ss_buf, src); + wd_free_sgl(ss_buf, dst); + wd_sglpool_destroy(ss_buf); + } + + wd_release_queue(q); + free(q); + + return NULL; + +comp_ctx_free: + wcrypto_del_comp_ctx(zip_ctx); +buf_free: +#ifdef CONFIG_IOMMU_SVA + if (ss_buf) + free(ss_buf); +#endif + if (pdata->data_fmt == WD_SGL_BUF) { /* use nosva-sgl */ + if (src) + wd_free_sgl(ss_buf, src); + if (dst) + wd_free_sgl(ss_buf, dst); + + wd_sglpool_destroy(ss_buf); + } + +release_q: + wd_release_queue(q); +hw_q_free: + free(q); + + return NULL; +} + +void *zip_sys_block_test_thread(void *args) +{ + int cpu_id, ret; + cpu_set_t mask; + pid_t tid; + struct test_zip_pthread_dt *pdata = args; + int i = pdata->iteration; + + cpu_id = pdata->cpu_id; + tid = gettid(); + + CPU_ZERO(&mask); + if (cpu_id) { + if (cpu_id <= 0 || cpu_id > MAX_CORES) { + dbg("set cpu no affinity!\n"); + goto therad_no_affinity; + } + CPU_SET(cpu_id, &mask); + if (pthread_setaffinity_np(pthread_self(), + sizeof(mask), &mask) < 0) { + perror("pthread_setaffinity fail!\n"); + return NULL; + } + } + +therad_no_affinity: + + dbg("%s entry thread_id=%d\n", __func__, (int)tid); + do { + if (pdata->op_type == WCRYPTO_DEFLATE) { + ret = hw_blk_compress(pdata->alg_type, pdata->blksize, + pdata->dst, &pdata->dst_len, + pdata->src, pdata->src_len, + pdata->data_fmt); + if (ret < 0) + WD_ERR("comp fail! thread_id=%d, tid=%d\n", + cpu_id, (int)tid); + } else if (pdata->op_type == WCRYPTO_INFLATE) { + ret = hw_blk_decompress(pdata->alg_type, pdata->blksize, + pdata->dst, &pdata->dst_len, + pdata->src, pdata->src_len, + pdata->data_fmt); + if (ret < 0) + WD_ERR("decomp fail! thread_id=%d, tid=%d\n", + cpu_id, (int)tid); + } + if (verify) { + ret = hw_blk_decompress(pdata->alg_type, pdata->blksize, + pdata->src, &pdata->src_len, + pdata->dst, pdata->dst_len, + pdata->data_fmt); + if (ret < 0) + WD_ERR("loop verify fail! ret=%d, id=%d\n", + ret, cpu_id); + else + dbg("loop verify success! id=%d\n", cpu_id); + } + } while (--i); + dbg("%s end thread_id=%d\n", __func__, pdata->cpu_id); + + return NULL; +} + +static int hizip_thread_test(FILE *source, FILE *dest, + int thread_num, int alg_type, int op_type, + int mode, int hw_flag, int data_fmt, int iteration) +{ + int fd; + struct stat s; + int i, j, ret; + int cnt = 0; + void *file_buf; + int in_len, sz; + float tc = 0; + float speed; + float total_in = 0; + float total_out = 0; + int count = 0; + struct timeval start_tval, end_tval; + + fd = fileno(source); + SYS_ERR_COND(fstat(fd, &s) < 0, "fstat"); + in_len = s.st_size; + SYS_ERR_COND(!in_len, "input file length zero"); + + file_buf = calloc(1, in_len); + + sz = fread(file_buf, 1, in_len, source); + if (sz != in_len) + WD_ERR("read file sz != in_len!\n"); + count = in_len/block_size; + + if (!count) + count = 1; + + dbg("%s entry blocksize=%d, count=%d, threadnum= %d, in_len=%d\n", + __func__, block_size, count, thread_num, in_len); + + cnt = thread_num; + for (i = 0; i < cnt; i++) { + test_thrds_data[i].thread_num = thread_num; + test_thrds_data[i].cpu_id = i; + test_thrds_data[i].alg_type = alg_type; + test_thrds_data[i].op_type = op_type; + test_thrds_data[i].data_fmt = data_fmt; + test_thrds_data[i].hw_flag = hw_flag; + test_thrds_data[i].blksize = block_size; + test_thrds_data[i].iteration = iteration; + test_thrds_data[i].src = file_buf; + test_thrds_data[i].src_len = in_len; + test_thrds_data[i].dst_len = test_thrds_data[i].src_len * 8; + test_thrds_data[i].src = calloc(1, test_thrds_data[i].src_len); + if (test_thrds_data[i].src == NULL) + goto buf_free; + memcpy(test_thrds_data[i].src, file_buf, in_len); + test_thrds_data[i].dst = calloc(1, test_thrds_data[i].dst_len); + if (test_thrds_data[i].dst == NULL) + goto src_buf_free; + } + + gettimeofday(&start_tval, NULL); + for (i = 0; i < cnt; i++) { + if (mode == MODE_STREAM || hw_flag == 0) + ret = pthread_create(&system_test_thrds[i], NULL, + zlib_sys_stream_test_thread, + &test_thrds_data[i]); + else if (mode == ASYNC) + ret = pthread_create(&system_test_thrds[i], NULL, + zip_sys_async_test_thread, + &test_thrds_data[i]); + else + ret = pthread_create(&system_test_thrds[i], NULL, + zip_sys_block_test_thread, + &test_thrds_data[i]); + if (ret) { + WD_ERR("Create %dth thread fail!\n", i); + return ret; + } + } + + for (i = 0; i < thread_num; i++) { + ret = pthread_join(system_test_thrds[i], NULL); + if (ret) { + WD_ERR("Join %dth thread fail!\n", i); + return ret; + } + } + gettimeofday(&end_tval, NULL); + for (i = 0; i < thread_num; i++) { + total_in += test_thrds_data[i].src_len; + total_out += test_thrds_data[i].dst_len; + } + tc = (float)((end_tval.tv_sec-start_tval.tv_sec) * 1000000 + + end_tval.tv_usec - start_tval.tv_usec); + dbg("%s end threadnum= %d, out_len=%ld\n", + __func__, thread_num, test_thrds_data[thread_num-1].dst_len); + sz = fwrite(test_thrds_data[thread_num-1].dst, 1, + test_thrds_data[thread_num-1].dst_len, dest); + + for (i = 0; i < thread_num; i++) { + free(test_thrds_data[i].src); + free(test_thrds_data[i].dst); + } + if (op_type == WCRYPTO_DEFLATE) { + speed = total_in / tc / + 1024 / 1024 * 1000 * 1000 * iteration; + fprintf(stderr, + "Compress bz=%d, threadnum= %d, speed=%0.3f MB/s, timedelay=%0.1f us\n", + block_size, thread_num, speed, + tc / thread_num / count / iteration); + } else { + speed = total_out / tc / + 1024 / 1024 * 1000 * 1000 * iteration; + fprintf(stderr, + "Decompress bz=%d, threadnum= %d, speed=%0.3f MB/s, timedelay=%0.1f us\n", + block_size, thread_num, speed, + tc / thread_num / count / iteration); + } + + free(file_buf); + + return 0; + +src_buf_free: + free(test_thrds_data[i].src); + +buf_free: + for (j = 0; j < i; j++) { + free(test_thrds_data[i].src); + free(test_thrds_data[i].dst); + } + + free(file_buf); + + WD_ERR("thread malloc fail!ENOMEM!\n"); + + return -ENOMEM; +} + +int main(int argc, char *argv[]) +{ + int alg_type = WCRYPTO_GZIP; + int op_type = WCRYPTO_DEFLATE; + int opt; + int show_help = 0; + int thread_num = 1; + int mode = 0; + int hw_flag = 1; + int iteration = 1; + /* data_fmt: 0 - pbuffer, 1 - sgl. */ + bool data_fmt = 0; + + while ((opt = getopt(argc, argv, "zghq:ab:dvc:kmsp:i:f:")) != -1) { + switch (opt) { + case 'z': + alg_type = WCRYPTO_ZLIB; + break; + case 'g': + alg_type = WCRYPTO_GZIP; + break; + case 'q': + q_num = atoi(optarg); + if (q_num <= 0) + show_help = 1; + break; + case 'b': + block_size = atoi(optarg); + if (block_size <= 0) + show_help = 1; + else if (block_size > 1024 * 1024) + SYS_ERR_COND(1, "blocksize > 1M!\n"); + break; + case 'c': + req_cache_num = atoi(optarg); + if (req_cache_num <= 0) + show_help = 1; + break; + case 'd': + op_type = WCRYPTO_INFLATE; + break; + case 'k': + mode = MODE_BLOCK; + break; + case 'm': + mode = MODE_STREAM; + break; + case 'a': + mode = ASYNC; + break; + case 'p': + thread_num = atoi(optarg); + if (thread_num > TEST_MAX_THRD) + SYS_ERR_COND(1, "thread_num > 2048!\n"); + break; + case 's': + hw_flag = 0; + break; + case 'v': + verify = 1; + break; + case 'i': + iteration = atoi(optarg); + if (iteration <= 0) + show_help = 1; + break; + case 'f': + data_fmt = atoi(optarg); + if (data_fmt == WD_FLAT_BUF) + fprintf(stderr, "use memmory of pbuffer!\n"); + else if(data_fmt == WD_SGL_BUF) + fprintf(stderr, "use memmory of sgl!\n"); + else + show_help = 1; + break; + default: + show_help = 1; + break; + } + } + + SYS_ERR_COND(show_help || optind > argc, + "version 1.00:wd_test_zip -[k/m/s] -[g|z] -d [-b block][-p thread_num] [-i iteration] [-f num] < in > out"); + + (void)hizip_thread_test(stdin, stdout, thread_num, alg_type, + op_type, mode, hw_flag, data_fmt, iteration); + + return EXIT_SUCCESS; +} diff --git a/uadk/v1/test/hisi_zip_test_sgl/zip_alg_sgl.c b/uadk/v1/test/hisi_zip_test_sgl/zip_alg_sgl.c new file mode 100644 index 0000000..4bb9781 --- /dev/null +++ b/uadk/v1/test/hisi_zip_test_sgl/zip_alg_sgl.c @@ -0,0 +1,1194 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../../wd.h" +#include "../../wd_util.h" /* It is not API head, to be deleted */ +#include "wd_sched_sgl.h" +#include "../../wd_comp.h" +#include "../../wd_bmm.h" +#include "../../wd_sgl.h" + +#include "zip_alg_sgl.h" +#include "../smm.h" + + +#define ZLIB_HEADER "\x78\x9c" +#define ZLIB_HEADER_SZ 2 + +/* + * We use a extra field for gzip block length. So the fourth byte is \x04. + * This is necessary because our software don't know the size of block when + * using an hardware decompresser (It is known by hardware). This help our + * decompresser to work and helpfully, compatible with gzip. + */ +#define GZIP_HEADER "\x1f\x8b\x08\x04\x00\x00\x00\x00\x00\x03" +#define GZIP_HEADER_SZ 10 +#define GZIP_EXTRA_SZ 10 +#define GZIP_TAIL_SZ 8 + +/* bytes of data for a request */ +#define BLOCK_SIZE (1024 * 1024) +#define REQ_CACHE_NUM 4 +#define Q_NUM 1 + +struct hizip_priv { + int alg_type; + int op_type; + int block_size; + int dw9; + int total_len; + int out_len; + struct wcrypto_comp_msg *msgs; + void *src, *dst; + int is_fd; +}; + +enum alg_op_type { + COMPRESS, + DECOMPRESS, +}; + +/* block mode api use wd_schedule interface */ + +static void hizip_wd_sched_init_cache(struct wd_scheduler *sched, int i, int data_fmt) +{ + struct wd_msg *wd_msg = &sched->msgs[i]; + struct wcrypto_comp_msg *msg; + struct hizip_priv *priv = sched->priv; + + msg = wd_msg->msg = &priv->msgs[i]; + msg->alg_type = priv->alg_type; + msg->avail_out = sched->msg_data_size; + msg->data_fmt = data_fmt; + + msg->src = wd_msg->data_in; + msg->dst = wd_msg->data_out; + + dbg("init sched cache %d: %p, %p\n", i, wd_msg, msg); +} + +static int hizip_wd_sched_input(struct wd_msg *msg, void *priv) +{ + size_t ilen, templen, real_len; + struct wcrypto_comp_msg *m = msg->msg; + struct hizip_priv *zip_priv = priv; + + ilen = zip_priv->total_len > zip_priv->block_size ? + zip_priv->block_size : zip_priv->total_len; + templen = ilen; + zip_priv->total_len -= ilen; + if (zip_priv->op_type == WCRYPTO_INFLATE) { + if (zip_priv->alg_type == WCRYPTO_ZLIB) { + zip_priv->src += ZLIB_HEADER_SZ; + ilen -= ZLIB_HEADER_SZ; + } else { + ilen -= GZIP_HEADER_SZ; + if (*((char *)zip_priv->src + 3) == 0x04) { + zip_priv->src += GZIP_HEADER_SZ; + memcpy(&ilen, zip_priv->src + 6, 4); + zip_priv->src += GZIP_EXTRA_SZ; + dbg("gzip iuput len %ld\n", ilen); + SYS_ERR_COND(ilen > zip_priv->block_size * 2, + "gzip protocol_len(%ld) > dmabuf_size(%d)\n", + ilen, zip_priv->block_size); + real_len = GZIP_HEADER_SZ + + GZIP_EXTRA_SZ + ilen; + zip_priv->total_len = zip_priv->total_len + + templen - real_len; + } else + zip_priv->src += GZIP_HEADER_SZ; + } + } + + if (m->data_fmt == WD_FLAT_BUF) /* use pbuffer */ + memcpy(msg->data_in, zip_priv->src, ilen); + else /* use sgl */ + wd_sgl_cp_from_pbuf(msg->data_in, 0, zip_priv->src, ilen); + + zip_priv->src += ilen; + + m->in_size = ilen; + dbg("zip input ilen= %lu, block_size= %d, total_len= %d\n", + ilen, zip_priv->block_size, zip_priv->total_len); + + dbg("zip input(%p, %p): %p, %p, %d, %d\n", + msg, m, m->src, m->dst, m->avail_out, m->in_size); + + return 0; +} + +static int hizip_wd_sched_output(struct wd_msg *msg, void *priv) +{ + struct wcrypto_comp_msg *m = msg->msg; + struct hizip_priv *zip_priv = priv; + char gzip_extra[GZIP_EXTRA_SZ] = {0x00, 0x07, 0x48, 0x69, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00}; + + dbg("%s()(%p, %p): %p, %p, inlen=%d, outlen=%d, coms=%d, out=%d\n", + __func__, msg, m, m->src, m->dst, + m->in_size, m->avail_out, m->in_cons, m->produced); + + if (zip_priv->op_type == WCRYPTO_DEFLATE) { + + if (zip_priv->alg_type == WCRYPTO_ZLIB) { + memcpy(zip_priv->dst, + ZLIB_HEADER, ZLIB_HEADER_SZ); + zip_priv->dst += ZLIB_HEADER_SZ; + zip_priv->out_len += ZLIB_HEADER_SZ; + } else { + memcpy(gzip_extra + 6, &m->produced, 4); + memcpy(zip_priv->dst, GZIP_HEADER, + GZIP_HEADER_SZ); + zip_priv->dst += GZIP_HEADER_SZ; + zip_priv->out_len += GZIP_HEADER_SZ; + memcpy(zip_priv->dst, gzip_extra, + GZIP_EXTRA_SZ); + zip_priv->dst += GZIP_EXTRA_SZ; + zip_priv->out_len += GZIP_EXTRA_SZ; + } + } + + if (m->data_fmt == WD_FLAT_BUF) /* use pbuffer */ + memcpy(zip_priv->dst, msg->data_out, m->produced); + else /* use sgl */ + wd_sgl_cp_to_pbuf(msg->data_out, 0, zip_priv->dst, m->produced); + + zip_priv->dst += m->produced; + zip_priv->out_len += m->produced; + + return 0; +} + +static int hizip_init(struct wd_scheduler *sched, int alg_type, int op_type, + int blk_size, int data_fmt) +{ + int ret = -ENOMEM, i; + char *alg; + struct wcrypto_paras *priv; + struct hizip_priv *zip_priv; + + sched->q_num = Q_NUM; + sched->ss_region_size = 0; /* let system make decision */ + sched->msg_cache_num = 1; + /* use twice size of the input data, hope it is engouth for output */ + sched->msg_data_size = blk_size * 2; + sched->init_cache = hizip_wd_sched_init_cache; + sched->input = hizip_wd_sched_input; + sched->output = hizip_wd_sched_output; + + sched->qs = calloc(sched->q_num, sizeof(struct wd_queue)); + if (!sched->qs) + return -ENOMEM; + + zip_priv = calloc(1, sizeof(struct hizip_priv)); + if (!zip_priv) + goto err_with_qs; + + zip_priv->msgs = calloc(sched->msg_cache_num, + sizeof(struct wcrypto_comp_msg)); + if (!zip_priv->msgs) + goto err_with_priv; + + zip_priv->alg_type = alg_type; + zip_priv->op_type = op_type; + zip_priv->block_size = blk_size; + if (alg_type == WCRYPTO_ZLIB) + alg = "zlib"; + else + alg = "gzip"; + + for (i = 0; i < sched->q_num; i++) { + sched->qs[i].capa.alg = alg; + priv = &sched->qs[i].capa.priv; + priv->direction = zip_priv->op_type; + } + + sched->priv = zip_priv; + ret = wd_sched_init(sched, data_fmt); + if (ret) + goto err_with_msgs; + + return 0; + +err_with_msgs: + free(zip_priv->msgs); +err_with_priv: + free(zip_priv); +err_with_qs: + free(sched->qs); + return ret; +} + +static void hizip_fini(struct wd_scheduler *sched, int data_fmt) +{ + struct hizip_priv *zip_priv = sched->priv; + + wd_sched_fini(sched, data_fmt); + free(zip_priv->msgs); + free(zip_priv); + free(sched->qs); +} + +/** + * compress() - compress memory buffer. + * @alg_type: alg_type. + * + * This function compress memory buffer. + */ +int hw_blk_compress(int alg_type, int blksize, + unsigned char *dst, ulong *dstlen, + unsigned char *src, ulong srclen, int data_fmt) +{ + int ret; + struct wd_scheduler sched; + struct hizip_priv *zip_priv; + + if (blksize < 0 || dst == NULL || src == NULL) + return -EINVAL; + memset(&sched, 0, sizeof(struct wd_scheduler)); + //ret = hizip_init(&sched, alg_type, WCRYPTO_DEFLATE, blksize); + ret = hizip_init(&sched, alg_type, WCRYPTO_DEFLATE, srclen, data_fmt); + if (ret) { + WD_ERR("fail to hizip init!\n"); + return ret; + } + zip_priv = sched.priv; + zip_priv->total_len = srclen; + zip_priv->src = src; + zip_priv->dst = dst; + zip_priv->is_fd = 0; + + while (zip_priv->total_len || !wd_sched_empty(&sched)) { + dbg("request loop: total_len=%d\n", zip_priv->total_len); + ret = wd_sched_work(&sched, zip_priv->total_len); + if (ret < 0) { + WD_ERR("wd_sched_work fail, ret=%d!\n", ret); + return ret; + } + } + + *dstlen = zip_priv->out_len; + hizip_fini(&sched, data_fmt); + + return ret; +} + +int hw_blk_decompress(int alg_type, int blksize, + unsigned char *dst, ulong *dstlen, + unsigned char *src, ulong srclen, int data_fmt) +{ + int ret; + struct wd_scheduler sched; + struct hizip_priv *zip_priv; + + if (blksize < 0 || dst == NULL || src == NULL) + return -EINVAL; + memset(&sched, 0, sizeof(struct wd_scheduler)); + //ret = hizip_init(&sched, alg_type, WCRYPTO_INFLATE, blksize); + ret = hizip_init(&sched, alg_type, WCRYPTO_INFLATE, srclen, data_fmt); + if (ret) { + WD_ERR("fail to hizip init!\n"); + return ret; + } + zip_priv = sched.priv; + zip_priv->total_len = srclen; + zip_priv->src = src; + zip_priv->dst = dst; + zip_priv->is_fd = 0; + + while (zip_priv->total_len || !wd_sched_empty(&sched)) { + dbg("request loop: total_len=%d\n", zip_priv->total_len); + ret = wd_sched_work(&sched, zip_priv->total_len); + if (ret < 0) { + WD_ERR("wd_sched_work fail, ret=%d!\n", ret); + return ret; + } + } + + *dstlen = zip_priv->out_len; + hizip_fini(&sched, data_fmt); + + return ret; +} + +/* stream api */ +#define ST_ZLIB_HEADER "\x78\x9c" +#define ST_GZIP_HEADER "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03" + +#define ST_ZLIB_HEADER_SZ 2 +#define ST_GZIP_HEADER_SZ 10 + +#define EMPTY_ZLIB_APPEND "\x03\x00\x00\x00\x00\x01" +#define EMPTY_ZLIB_SZ 6 +#define EMPTY_GZIP_APPEND "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00" +#define EMPTY_GZIP_SZ 10 + + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_STREAM_NEED_AGAIN 2 + +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-EIO) + +#define swab32(x) \ + ((((x) & 0x000000ff) << 24) | \ + (((x) & 0x0000ff00) << 8) | \ + (((x) & 0x00ff0000) >> 8) | \ + (((x) & 0xff000000) >> 24)) + +#define cpu_to_be32(x) swab32(x) + +/*wrap as zlib basic interface */ +#define HZLIB_VERSION "1.0.1" + +#ifndef MAX_WBITS +#define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* compression levels */ +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) + + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +#ifdef MAXSEG_64K +#define MAX_MEM_LEVEL 8 +#else +#define MAX_MEM_LEVEL 9 +#endif +#endif + +/* default memLevel */ +#ifndef DEF_MEM_LEVEL +#if MAX_MEM_LEVEL >= 8 +#define DEF_MEM_LEVEL 8 +#else +#define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +#endif + +/* compression strategy; see deflateInit2() below for details */ +#define Z_DEFAULT_STRATEGY 0 + +/* default windowBits for decompression. MAX_WBITS is for compression only */ +#ifndef DEF_WBITS +#define DEF_WBITS MAX_WBITS +#endif + +/* The deflate compression method (the only one supported in this version) */ +#define Z_DEFLATED 8 + +struct zip_stream { + void *next_in; /* next input byte */ + unsigned long avail_in; /* number of bytes available at next_in */ + unsigned long total_in; /* total nb of input bytes read so far */ + void *next_out; /* next output byte should be put there */ + unsigned long avail_out; /* remaining free space at next_out */ + unsigned long total_out; /* total nb of bytes output so far */ + char *msg; /* last error message, NULL if no error */ + void *workspace; /* memory allocated for this stream */ + int data_type; /*the data type: ascii or binary */ + unsigned long adler; /* adler32 value of the uncompressed data */ + void *reserved; /* reserved for future use */ + int data_fmt; +}; + +struct zip_ctl { + void *pool; + void *in; + void *out; + void *ctxbuf; + void *queue; + void *ctx; + void *opdata; +}; + +#define hw_deflateInit(strm, level) \ + hw_deflateInit_(strm, level, HZLIB_VERSION, sizeof(struct zip_stream)) +#define hw_inflateInit(strm) \ + hw_inflateInit_(strm, HZLIB_VERSION, (int)sizeof(struct zip_stream)) +#define hw_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + hw_deflateInit2_(strm, level, method, windowBits, memLevel,\ + (strategy), HZLIB_VERSION, (int)sizeof(struct zip_stream)) +#define hw_inflateInit2(strm, windowBits) \ + hw_inflateInit2_(strm, windowBits, HZLIB_VERSION, \ + (int)sizeof(struct zip_stream)) + +static int stream_chunk = 1024 * 64; + +static int hw_init(struct zip_stream *zstrm, int alg_type, int comp_optype) +{ + struct wcrypto_comp_ctx_setup ctx_setup; + struct wcrypto_comp_op_data *opdata; + struct wd_blkpool_setup mm_setup; + struct wd_sglpool_setup sp; + unsigned int block_mm_num = 3; + struct wcrypto_paras *priv; + struct zip_ctl *ctl; + void *in, *out; + struct wd_queue *q; + void *zip_ctx; + void *pool; + int ret; + + q = calloc(1, sizeof(struct wd_queue)); + if (q == NULL) { + ret = -ENOMEM; + fprintf(stderr, "alloc q fail, ret =%d\n", ret); + return ret; + } + + switch (alg_type) { + case WCRYPTO_ZLIB: + q->capa.alg = "zlib"; + break; + case WCRYPTO_GZIP: + q->capa.alg = "gzip"; + break; + default: + ret = -EINVAL; + goto hw_q_free; + } + + q->capa.latency = 0; + q->capa.throughput = 0; + + priv = &q->capa.priv; + priv->direction = comp_optype; + ret = wd_request_queue(q); + if (ret) { + fprintf(stderr, "wd_request_queue fail, ret =%d\n", ret); + goto hw_q_free; + } + SYS_ERR_COND(ret, "wd_request_queue"); + +#ifdef CONFIG_IOMMU_SVA + in = calloc(1, DMEMSIZE); + out = calloc(1, DMEMSIZE); + ctx_buf = calloc(1, HW_CTX_SIZE); + if (in == NULL || out == NULL || ctx_buf == NULL) { + dbg("not enough data ss_region memory for cache (bs=%d)\n", + DMEMSIZE); + goto buf_free; + } + +#else + if (zstrm->data_fmt == WD_FLAT_BUF) { /* use pbuffer */ + memset(&mm_setup, 0, sizeof(mm_setup)); + mm_setup.block_size = DMEMSIZE; + mm_setup.block_num = block_mm_num; + mm_setup.align_size = 128; + pool = wd_blkpool_create(q, &mm_setup); + if (!pool) { + WD_ERR("%s(): create pool fail!\n", __func__); + ret = -ENOMEM; + goto release_q; + } + in = wd_alloc_blk(pool); + out = wd_alloc_blk(pool); + + if (in == NULL || out == NULL) { + dbg("not enough data ss_region memory for cache (bs=%d)\n", + DMEMSIZE); + goto buf_free; + } + } else { /* use sgl */ + memset(&sp, 0, sizeof(sp)); + sp.buf_num = 200; + sp.buf_size = 1024 * 1024 * 7; + sp.align_size = 64; + sp.sge_num_in_sgl = 20; //(DMEMSIZE / 1024 / sp.buf_size * 10 + 1) * 2; + sp.buf_num_in_sgl = sp.sge_num_in_sgl; + sp.sgl_num = block_mm_num; + + pool = wd_sglpool_create(q, &sp); + if (!pool) { + WD_ERR("%s(): create pool fail!\n", __func__); + ret = -ENOMEM; + goto release_q; + } + in = wd_alloc_sgl(pool, zstrm->avail_in); + out = wd_alloc_sgl(pool, zstrm->avail_in); + + if (in == NULL || out == NULL) { + dbg("not enough data ss_region memory for cache (bs=%d)\n", + DMEMSIZE); + goto buf_free; + } + } + +#endif + + dbg("%s():va_in=%p, va_out=%p!\n", __func__, in, out); + memset(&ctx_setup, 0, sizeof(ctx_setup)); + ctx_setup.alg_type = alg_type; + ctx_setup.stream_mode = WCRYPTO_COMP_STATEFUL; + if (zstrm->data_fmt == WD_FLAT_BUF) { /* use pbuffer */ + ctx_setup.data_fmt = WD_FLAT_BUF; + ctx_setup.br.alloc = (void *)wd_alloc_blk; + ctx_setup.br.free = (void *)wd_free_blk; + ctx_setup.br.iova_map = (void *)wd_blk_iova_map; + ctx_setup.br.iova_unmap = (void *)wd_blk_iova_unmap; + ctx_setup.br.get_bufsize = (void *)wd_blksize; + ctx_setup.br.usr = pool; + } else { /* WD_SGL_BUF */ + ctx_setup.data_fmt = WD_SGL_BUF; + ctx_setup.br.alloc = (void *)wd_alloc_sgl; + ctx_setup.br.free = (void *)wd_free_sgl; + ctx_setup.br.iova_map = (void *)wd_sgl_iova_map; + ctx_setup.br.iova_unmap = (void *)wd_sgl_iova_unmap; + ctx_setup.br.usr = pool; + } + + zip_ctx = wcrypto_create_comp_ctx(q, &ctx_setup); + if (!zip_ctx) { + fprintf(stderr, "zip_alloc_comp_ctx fail, ret =%d\n", ret); + goto buf_free; + } + + opdata = calloc(1, sizeof(struct wcrypto_comp_op_data)); + if (opdata == NULL) { + ret = -ENOMEM; + fprintf(stderr, "alloc opdata fail, ret =%d\n", ret); + goto comp_ctx_free; + } + opdata->in = in; + opdata->out = out; + opdata->stream_pos = WCRYPTO_COMP_STREAM_NEW; + opdata->alg_type = ctx_setup.alg_type; + + ctl = calloc(1, sizeof(struct zip_ctl)); + if (ctl == NULL) { + ret = -ENOMEM; + fprintf(stderr, "alloc ctl fail, ret =%d\n", ret); + goto comp_opdata_free; + } + ctl->pool = pool; + ctl->in = in; /* temp for opdata->in*/ + ctl->out = out; + ctl->ctx = zip_ctx; + ctl->queue = q; + ctl->opdata = opdata; + + zstrm->next_in = in; + zstrm->next_out = out; + zstrm->reserved = ctl; + + return Z_OK; + +comp_opdata_free: + free(opdata); + +comp_ctx_free: + wcrypto_del_comp_ctx(zip_ctx); + +buf_free: +#ifdef CONFIG_IOMMU_SVA + if (in) + free(in); + if (out) + free(out); +#else + if (zstrm->data_fmt == WD_FLAT_BUF) { /* use pbuffer */ + if (in) + wd_free_blk(pool, in); + if (out) + wd_free_blk(pool, out); + + wd_blkpool_destroy(pool); + } else { /* use sgl */ + if (in) + wd_free_sgl(pool, in); + if (out) + wd_free_sgl(pool, out); + + wd_sglpool_destroy(pool); + } + +#endif +release_q: + wd_release_queue(q); +hw_q_free: + free(q); + + return ret; +} + +static void hw_end(struct zip_stream *zstrm) +{ + struct zip_ctl *ctl = zstrm->reserved; + struct wcrypto_comp_op_data *opdata = ctl->opdata; + +#ifdef CONFIG_IOMMU_SVA + if (ctl->in) + free(ctl->in); + if (ctl->out) + free(ctl->out); +#else + if (zstrm->data_fmt == WD_FLAT_BUF) { /* use pbuffer */ + if (ctl->in) + wd_free_blk(ctl->pool, ctl->in); + if (ctl->out) + wd_free_blk(ctl->pool, ctl->out); + } else { /* use sgl */ + if (ctl->in) + wd_free_sgl(ctl->pool, ctl->in); + if (ctl->out) + wd_free_sgl(ctl->pool, ctl->out); + } +#endif + + if (ctl->ctx) + wcrypto_del_comp_ctx(ctl->ctx); + + if (zstrm->data_fmt == WD_FLAT_BUF) /* use pbuffer */ + wd_blkpool_destroy(ctl->pool); + else /* use sgl */ + wd_sglpool_destroy(ctl->pool); + + if (ctl->queue) { + wd_release_queue(ctl->queue); + free(ctl->queue); + } + + free(opdata); + free(ctl); +} + +static unsigned int bit_reverse(register unsigned int x) +{ + x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1)); + x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2)); + x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4)); + x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8)); + + return((x >> 16) | (x << 16)); +} + +/* output an empty store block */ +static int append_store_block(struct zip_stream *zstrm, int flush) +{ + char store_block[5] = {0x1, 0x00, 0x00, 0xff, 0xff}; + struct zip_ctl *ctl = zstrm->reserved; + struct wcrypto_comp_op_data *opdata = ctl->opdata; + __u32 checksum = opdata->checksum; + __u32 isize = opdata->isize; + + memcpy(zstrm->next_out, store_block, 5); + zstrm->total_out += 5; + zstrm->avail_out -= 5; + if (flush != WCRYPTO_FINISH) + return Z_STREAM_END; + + if (opdata->alg_type == WCRYPTO_ZLIB) { /*if zlib, ADLER32*/ + checksum = (__u32) cpu_to_be32(checksum); + memcpy(zstrm->next_out + 5, &checksum, 4); + zstrm->total_out += 4; + zstrm->avail_out -= 4; + } else if (opdata->alg_type == WCRYPTO_GZIP) { + checksum = ~checksum; + checksum = bit_reverse(checksum); + /* if gzip, CRC32 and ISIZE */ + memcpy(zstrm->next_out + 5, &checksum, 4); + memcpy(zstrm->next_out + 9, &isize, 4); + zstrm->total_out += 8; + zstrm->avail_out -= 8; + } else + fprintf(stderr, "in append store block, wrong alg type %d.\n", + opdata->alg_type); + + return Z_STREAM_END; +} + +static int hw_send_and_recv(struct zip_stream *zstrm, int flush) +{ + struct zip_ctl *ctl = zstrm->reserved; + struct wcrypto_comp_op_data *opdata = ctl->opdata; + void *zip_ctx = ctl->ctx; + int ret = 0; + + if (zstrm->avail_in == 0 && flush == WCRYPTO_FINISH) + return append_store_block(zstrm, flush); + + opdata->flush = flush; + opdata->in_len = zstrm->avail_in; + opdata->avail_out = zstrm->avail_out; + + dbg("%s():input ,opdata->in_len=%u, zstrm->avail_out=%lu!\n", + __func__, opdata->in_len, zstrm->avail_out); + + ret = wcrypto_do_comp(zip_ctx, opdata, NULL); + if (ret < 0) + return ret; + if (opdata->stream_pos == WCRYPTO_COMP_STREAM_NEW) { + opdata->stream_pos = WCRYPTO_COMP_STREAM_OLD; + zstrm->total_out = 0; + } + + dbg("%s():output, inlen=%d, coms=%d, produced=%d, avail_out=%lu!\n", + __func__, opdata->in_len, opdata->consumed, + opdata->produced, zstrm->avail_out); + + zstrm->avail_in = opdata->in_len - opdata->consumed; + zstrm->avail_out -= opdata->produced; + zstrm->total_out += opdata->produced; + + if (zstrm->avail_in > 0) + opdata->in += opdata->consumed; + if (zstrm->avail_in == 0) + opdata->in = ctl->in; /* origin addr in */ + + if (ret == 0 && flush == WCRYPTO_FINISH) + ret = Z_STREAM_END; + else if (ret == 0 && opdata->status == WCRYPTO_DECOMP_END_NOSPACE) + ret = Z_STREAM_NEED_AGAIN; /* decomp_is_end region */ + else if (ret == 0 && opdata->status == WCRYPTO_DECOMP_END) + ret = Z_STREAM_END; /* decomp_is_end region */ + else if (ret == 0 && opdata->status == WD_VERIFY_ERR) + ret = -WD_VERIFY_ERR; /* crc err */ + else if (ret == 0 && opdata->status == WD_IN_EPARA) + ret = -WD_IN_EPARA; /* msg err */ + + return ret; +} + +int hw_deflateInit2_(struct zip_stream *zstrm, int level, int method, + int windowBits, int memLevel, int strategy, + const char *version, int stream_size) +{ + int alg_type; + int wrap = 0; + + if (windowBits < 0) { /* suppress zlib wrapper */ + wrap = 0; + windowBits = -windowBits; + } else if (windowBits > 15) { + wrap = 2; /* write gzip wrapper instead */ + windowBits -= 16; + } + + if (wrap & 0x02) + alg_type = WCRYPTO_GZIP; + else + alg_type = WCRYPTO_ZLIB; + + return hw_init(zstrm, alg_type, WCRYPTO_DEFLATE); + +} + +int hw_deflateInit_(struct zip_stream *zstrm, int level, const char *version, + int stream_size) +{ + if (zstrm == NULL) + return -EINVAL; + + return hw_deflateInit2_(zstrm, level, Z_DEFLATED, + MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, version, stream_size); +} + +int hw_deflate(struct zip_stream *zstrm, int flush) +{ + int ret; + + if (zstrm == NULL) + return -EINVAL; + ret = hw_send_and_recv(zstrm, flush); + if (ret < 0) + return Z_STREAM_ERROR; + return ret; +} + +int hw_deflateEnd(struct zip_stream *zstrm) +{ + if (zstrm == NULL) + return -EINVAL; + hw_end(zstrm); + return 0; +} + +int hw_inflateInit2_(struct zip_stream *zstrm, int windowBits, + const char *version, int stream_size) +{ + int wrap, alg_type; + + /* extract wrap request from windowBits parameter */ + if (windowBits < 0) { + wrap = 0; + windowBits = -windowBits; + } else { + wrap = (windowBits >> 4) + 5; + + } + if (wrap & 0x01) + alg_type = WCRYPTO_ZLIB; + if (wrap & 0x02) + alg_type = WCRYPTO_GZIP; + + return hw_init(zstrm, alg_type, WCRYPTO_INFLATE); +} + +int hw_inflateInit_(struct zip_stream *zstrm, + const char *version, int stream_size) +{ + if (zstrm == NULL) + return -EINVAL; + return hw_inflateInit2_(zstrm, DEF_WBITS, version, stream_size); +} + +int hw_inflate(struct zip_stream *zstrm, int flush) +{ + int ret; + + if (zstrm == NULL) + return -EINVAL; + ret = hw_send_and_recv(zstrm, flush); + if (ret < 0) + return Z_STREAM_ERROR; + return ret; +} + +int hw_inflateEnd(struct zip_stream *zstrm) +{ + if (zstrm == NULL) + return -EINVAL; + hw_end(zstrm); + return 0; +} + +int hw_stream_compress(int alg_type, int blksize, + unsigned char *dst, ulong *dstlen, + unsigned char *src, ulong srclen, int data_fmt) +{ + int flush, have; + int ret; + int level = 0; + struct zip_stream zstrm; + int windowBits = 15; + int GZIP_ENCODING = 16; + + if (blksize < 0 || dst == NULL || src == NULL) + return -EINVAL; + stream_chunk = 10240; // blksize; + *dstlen = 0; + + zstrm.data_fmt = data_fmt; + /* add zlib compress head and write head + compressed date to a file */ + if (alg_type == WCRYPTO_ZLIB) { + ret = hw_deflateInit(&zstrm, level); + if (ret != Z_OK) + return ret; + memcpy(dst, ST_ZLIB_HEADER, ST_ZLIB_HEADER_SZ); + dst += ST_ZLIB_HEADER_SZ; + *dstlen += ST_ZLIB_HEADER_SZ; + } else { + /* deflate for gzip data */ + ret = hw_deflateInit2(&zstrm, Z_DEFAULT_COMPRESSION, + Z_DEFLATED, windowBits | GZIP_ENCODING, 8, + Z_DEFAULT_STRATEGY); + if (ret != Z_OK) + return ret; + memcpy(dst, ST_GZIP_HEADER, ST_GZIP_HEADER_SZ); + dst += ST_GZIP_HEADER_SZ; + *dstlen += ST_GZIP_HEADER_SZ; + } + + do { + if (srclen > stream_chunk) { + if (data_fmt == WD_FLAT_BUF) /* use pbuffer */ + memcpy(zstrm.next_in, src, stream_chunk); + else /* use sgl */ + wd_sgl_cp_from_pbuf((struct wd_sgl *)zstrm.next_in, 0, src, stream_chunk); + + src += stream_chunk; + zstrm.avail_in = stream_chunk; + srclen -= stream_chunk; + } else { + if (data_fmt == WD_FLAT_BUF) /* use pbuffer */ + memcpy(zstrm.next_in, src, srclen); + else /* use sgl */ + wd_sgl_cp_from_pbuf((struct wd_sgl *)zstrm.next_in, 0, src, srclen); + + zstrm.avail_in = srclen; + srclen = 0; + } + flush = srclen ? WCRYPTO_SYNC_FLUSH : WCRYPTO_FINISH; + do { + zstrm.avail_out = stream_chunk; + ret = hw_deflate(&zstrm, flush); + ASSERT(ret != Z_STREAM_ERROR); + if (ret < 0) { + hw_end(&zstrm); + return ret; + } + have = stream_chunk - zstrm.avail_out; + if (data_fmt == WD_FLAT_BUF) /* use pbuffer */ + memcpy(dst, zstrm.next_out, have); + else /* use sgl */ + wd_sgl_cp_to_pbuf((struct wd_sgl *)zstrm.next_out, 0, dst, have); + + dst += have; + *dstlen += have; + } while (zstrm.avail_in > 0); + ASSERT(zstrm.avail_in == 0); /* all input will be used */ + + /* done when last data in file processed */ + } while (flush != WCRYPTO_FINISH); + + dbg("%s, end strm->total = %ld\n", __func__, zstrm.total_out); + + ASSERT(ret == Z_STREAM_END); /* stream will be complete */ + hw_end(&zstrm); + + return Z_OK; +} + +int hw_stream_decompress(int alg_type, int blksize, + unsigned char *dst, ulong *dstlen, + unsigned char *src, ulong srclen, int data_fmt) +{ + struct zip_stream zstrm; + ulong out_size = 0; + int have; + int ret; + + if (blksize < 0 || dst == NULL || src == NULL) + return -EINVAL; + stream_chunk = 10240; //blksize; + + zstrm.data_fmt = data_fmt; + + if (alg_type == WCRYPTO_ZLIB) { + ret = hw_inflateInit(&zstrm); + if (ret != Z_OK) + return ret; + src += ST_ZLIB_HEADER_SZ; + srclen -= ST_ZLIB_HEADER_SZ; + } else { + ret = hw_inflateInit2(&zstrm, 16 + MAX_WBITS); + if (ret != Z_OK) + return ret; + src += ST_GZIP_HEADER_SZ; + srclen -= ST_GZIP_HEADER_SZ; + } + do { + if (srclen > stream_chunk) { + if (data_fmt == WD_FLAT_BUF) /* use pbuffer */ + memcpy(zstrm.next_in, src, stream_chunk); + else /* use sgl */ + wd_sgl_cp_from_pbuf((struct wd_sgl *)zstrm.next_in, 0, src, stream_chunk); + + src += stream_chunk; + zstrm.avail_in = stream_chunk; + srclen -= stream_chunk; + } else { + if (data_fmt == WD_FLAT_BUF) /* use pbuffer */ + memcpy(zstrm.next_in, src, srclen); + else /* use sgl */ + wd_sgl_cp_from_pbuf((struct wd_sgl *)zstrm.next_in, 0, src, srclen); + + zstrm.avail_in = srclen; + srclen = 0; + } +/* + * if (zstrm.avail_in == 0) { + * ret = Z_STREAM_END; + * break; + * } + */ + /* finish compression if all of source has been read in */ + do { + zstrm.avail_out = stream_chunk; + ret = hw_inflate(&zstrm, WCRYPTO_SYNC_FLUSH); + ASSERT(ret != Z_STREAM_ERROR); + if (ret < 0) { + hw_end(&zstrm); + return ret; + } + have = stream_chunk - zstrm.avail_out; + if (zstrm.total_out > *dstlen) { + hw_end(&zstrm); + return -ENOMEM; + } + if (data_fmt == WD_FLAT_BUF) /* use pbuffer */ + memcpy(dst, zstrm.next_out, have); + else /* use sgl */ + wd_sgl_cp_to_pbuf((struct wd_sgl *)zstrm.next_out, 0, dst, have); + + dst += have; + out_size += have; + } while (zstrm.avail_in > 0); + ASSERT(zstrm.avail_in == 0); /* all input will be used */ + + /* done when last data in file processed */ + } while (ret != Z_STREAM_END); + + dbg("%s, end strm->total = %ld\n", __func__, zstrm.total_out); + + *dstlen = out_size + + ASSERT(ret == Z_STREAM_END); /* stream will be complete */ + hw_end(&zstrm); + return Z_OK; +} + +int hw_stream_def(FILE *source, FILE *dest, int alg_type) +{ + int flush, have; + int ret; + int level = 0; + struct zip_stream zstrm; + int windowBits = 15; + int GZIP_ENCODING = 16; + int fd, file_len; + struct stat s; + + fd = fileno(source); + SYS_ERR_COND(fstat(fd, &s) < 0, "fstat"); + file_len = s.st_size; + if (!file_len) { + if (alg_type == WCRYPTO_ZLIB) { + fwrite(ST_ZLIB_HEADER, 1, ST_ZLIB_HEADER_SZ, dest); + fwrite(EMPTY_ZLIB_APPEND, 1, EMPTY_ZLIB_SZ, dest); + return Z_OK; + } else if (alg_type == WCRYPTO_GZIP) { + fwrite(ST_GZIP_HEADER, 1, ST_GZIP_HEADER_SZ, dest); + fwrite(EMPTY_GZIP_APPEND, 1, EMPTY_GZIP_SZ, dest); + return Z_OK; + } else + return -EINVAL; + } + /* add zlib compress head and write head + compressed date to a file */ + if (alg_type == WCRYPTO_ZLIB) { + ret = hw_deflateInit(&zstrm, level); + if (ret != Z_OK) + return ret; + fwrite(ST_ZLIB_HEADER, 1, ST_ZLIB_HEADER_SZ, dest); + } else { + /* deflate for gzip data */ + ret = hw_deflateInit2(&zstrm, Z_DEFAULT_COMPRESSION, + Z_DEFLATED, windowBits | GZIP_ENCODING, 8, + Z_DEFAULT_STRATEGY); + if (ret != Z_OK) + return ret; + fwrite(ST_GZIP_HEADER, 1, ST_GZIP_HEADER_SZ, dest); + } + do { + + zstrm.avail_in = fread(zstrm.next_in, 1, stream_chunk, source); + flush = feof(source) ? WCRYPTO_FINISH : WCRYPTO_SYNC_FLUSH; + do { + zstrm.avail_out = stream_chunk; + ret = hw_deflate(&zstrm, flush); + ASSERT(ret != Z_STREAM_ERROR); + if (ret < 0) { + hw_end(&zstrm); + return ret; + } + have = stream_chunk - zstrm.avail_out; + if (fwrite(zstrm.next_out, 1, have, dest) != have || + ferror(dest)) { + fprintf(stderr, "errno =%d\n", errno); + (void)hw_end(&zstrm); + return Z_ERRNO; + } + } while (zstrm.avail_in > 0); + ASSERT(zstrm.avail_in == 0); /* all input will be used */ + + /* done when last data in file processed */ + } while (flush != WCRYPTO_FINISH); + + dbg("%s, end strm->total = %ld\n", __func__, zstrm.total_out); + + ASSERT(ret == Z_STREAM_END); /* stream will be complete */ + hw_end(&zstrm); + + return Z_OK; +} + +int hw_stream_inf(FILE *source, FILE *dest, int alg_type) +{ + int have; + int ret; + struct zip_stream zstrm; + + if (alg_type == WCRYPTO_ZLIB) { + ret = hw_inflateInit(&zstrm); + if (ret != Z_OK) + return ret; + fseek(source, ST_ZLIB_HEADER_SZ, SEEK_SET); + } else { + ret = hw_inflateInit2(&zstrm, 16 + MAX_WBITS); + if (ret != Z_OK) + return ret; + fseek(source, ST_GZIP_HEADER_SZ, SEEK_SET); + } + do { + zstrm.avail_in = fread(zstrm.next_in, 1, stream_chunk, source); + if (ferror(source)) { + hw_end(&zstrm); + return Z_ERRNO; + } +/* + * if (zstrm.avail_in == 0) + * break; + */ + /* finish compression if all of source has been read in */ + do { + zstrm.avail_out = stream_chunk; + ret = hw_inflate(&zstrm, WCRYPTO_SYNC_FLUSH); + ASSERT(ret != Z_STREAM_ERROR); + if (ret < 0) { + hw_end(&zstrm); + return ret; + } + have = stream_chunk - zstrm.avail_out; + if (fwrite(zstrm.next_out, 1, have, dest) != have || + ferror(dest)) { + hw_end(&zstrm); + return Z_ERRNO; + } + + } while (zstrm.avail_in > 0); + ASSERT(zstrm.avail_in == 0); /* all input will be used */ + + /* done when last data in file processed */ + } while (ret != Z_STREAM_END); + + dbg("%s, end strm->total = %ld\n", __func__, zstrm.total_out); + + ASSERT(ret == Z_STREAM_END); /* stream will be complete */ + hw_end(&zstrm); + return Z_OK; +} + diff --git a/uadk/v1/test/hisi_zip_test_sgl/zip_alg_sgl.h b/uadk/v1/test/hisi_zip_test_sgl/zip_alg_sgl.h new file mode 100644 index 0000000..0baa35b --- /dev/null +++ b/uadk/v1/test/hisi_zip_test_sgl/zip_alg_sgl.h @@ -0,0 +1,68 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#ifndef __WD_ZIP_ALG_SGL__H__ +#define __WD_ZIP_ALG_SGL_H__ + +#include +#include +#include +#include +#include +#include + +//#define DEFLATE 0 +//#define INFLATE 1 + +#define DMEMSIZE (1024 * 1024) /* 1M */ +#define HW_CTX_SIZE (64 * 1024) + +#define SYS_ERR_COND(cond, msg, ...) \ +do { \ + if (cond) { \ + if (errno) \ + perror(msg); \ + else \ + fprintf(stderr, msg, ##__VA_ARGS__); \ + exit(EXIT_FAILURE); \ + } \ +} while (0) + + +/* for block interface */ +extern int hw_blk_compress(int alg_type, int blksize, + unsigned char *dst, ulong *dstlen, + unsigned char *src, ulong srclen, int data_fmt); + +extern int hw_blk_decompress(int alg_type, int blksize, + unsigned char *dst, ulong *dstlen, + unsigned char *src, ulong srclen, int data_fmt); + +/* for stream memory interface */ +extern int hw_stream_compress(int alg_type, int blksize, + unsigned char *dst, ulong *dstlen, + unsigned char *src, ulong srclen, int data_fmt); + +extern int hw_stream_decompress(int alg_type, int blksize, + unsigned char *dst, ulong *dstlen, + unsigned char *src, ulong srclen, int data_fmt); + +/* for stream file interface */ +extern int hw_stream_def(FILE *source, FILE *dest, int alg_type); +extern int hw_stream_inf(FILE *source, FILE *dest, int alg_type); + +#endif + diff --git a/uadk/v1/test/smm.c b/uadk/v1/test/smm.c new file mode 100644 index 0000000..441d0fd --- /dev/null +++ b/uadk/v1/test/smm.c @@ -0,0 +1,201 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +/* Simple Memory Memory (lib): A simple first fit memory algorithm */ + +#include +#include +#include +#include "v1/test/smm.h" +#include "v1/wd.h" +#include "v1/wd_util.h" + +#define SMM_HEAD_TAG 0xE5E5 +#define SMMB_HEAD_FREE_TAG 0x5E5E +#define SMMB_HEAD_ALLOCED_TAG 0xAAAA + +/* todo: free block need not to be the same as allocated block */ +struct smmb_head { + int tag; + size_t size; + struct smmb_head *next; +}; + +/* todo: make alignment */ +struct smm_head { + int tag; + unsigned int align_mask; + struct smmb_head *freelist; +}; + +static size_t __aligned_size(size_t sz, unsigned int align_mask) +{ + return (sz + align_mask) & ~align_mask; +} + +/** + * Initial a continue memory region to be managed by smm. + * + * @pt_addr the first address of the managed memory region + * @size size of the region + * @align_mask mask for address mask, + * e.g. 0xFFF for aligning the memory block to 4K boundary + */ +int smm_init(void *pt_addr, size_t size, unsigned int align_mask) +{ + struct smm_head *h = pt_addr; + struct smmb_head *bh; + size_t hs = __aligned_size(sizeof(*h), align_mask); + size_t bs = __aligned_size(sizeof(*bh), align_mask); + + if (size < hs + bs) + return -ENOMEM; + + h->tag = SMM_HEAD_TAG; + h->align_mask = align_mask; + bh = h->freelist = pt_addr + hs; + bh->tag = SMMB_HEAD_FREE_TAG; + bh->next = NULL; + bh->size = size - hs; + return 0; +} + +void *smm_alloc(void *pt_addr, size_t size) +{ + struct smm_head *h = pt_addr; + struct smmb_head **bhp = &h->freelist; + struct smmb_head *bh_new, *bh = h->freelist; + size_t sz = __aligned_size(size + sizeof(*bh), h->align_mask); + + ASSERT(h->tag == SMM_HEAD_TAG); + + while (bh) { + ASSERT(bh->tag == SMMB_HEAD_FREE_TAG); + + if (bh->size >= sz) { + if (bh->size < sz + sizeof(*bh)) { + *bhp = bh->next; + } else { + bh_new = (void *)bh + sz; + bh_new->tag = SMMB_HEAD_FREE_TAG; + bh_new->size = bh->size - sz; + bh_new->next = bh->next; + *bhp = bh_new; + bh->size = sz; + } + + bh->tag = SMMB_HEAD_ALLOCED_TAG; + return bh + 1; + } + + bhp = &(bh->next); + bh = bh->next; + } + + return NULL; +} + +static inline int __merge_free_block(struct smmb_head *h1, + struct smmb_head *h2) +{ + if ((void *)h1 + h1->size == h2) { + h1->size += h2->size; + h1->next = h2->next; + return true; + } + return false; +} + +void smm_free(void *pt_addr, void *ptr) +{ + struct smm_head *h = pt_addr; + struct smmb_head **bhp = &h->freelist; + struct smmb_head *bh = h->freelist; + struct smmb_head *bh_cur = ptr - sizeof(struct smmb_head); + + ASSERT(h->tag == SMM_HEAD_TAG); + ASSERT(bh_cur->tag == SMMB_HEAD_ALLOCED_TAG); + + if (!bh) { + *bhp = bh_cur; + bh_cur->tag = SMMB_HEAD_FREE_TAG; + return; + } + + while (bh) { + ASSERT(bh->tag == SMMB_HEAD_FREE_TAG); + + if (bh_cur < bh) { + *bhp = bh_cur; + bh_cur->tag = SMMB_HEAD_FREE_TAG; + + if (!__merge_free_block(bh_cur, bh)) + bh_cur->next = bh; + + return; + } else if ((void *)bh + bh->size == bh_cur) { + bh->size += bh_cur->size; + (void)__merge_free_block(bh, bh->next); + return; + } + + bhp = &(bh->next); + bh = bh->next; + } + + ASSERT(false); +} + +void *smm_realloc(void *pt_addr, void *ptr, size_t size) +{ + /* there is no benefit to do reallocation in this algorithm */ + ASSERT(false); + return NULL; +} + +#ifndef NDEBUG +void smm_dump(void *pt_addr) +{ + struct smm_head *h = pt_addr; + struct smmb_head *bh = h->freelist; + + ASSERT(h->tag == SMM_HEAD_TAG); + + printf("dump pt %p: align_mask = 0x%x\n", h, h->align_mask); + while (bh) { + ASSERT(bh->tag == SMMB_HEAD_FREE_TAG); + printf("freeblock(%p): sz=%ld\n", bh, bh->size); + bh = bh->next; + } +} + +int smm_get_freeblock_num(void *pt_addr) +{ + struct smm_head *h = pt_addr; + struct smmb_head *bh = h->freelist; + int ret = 0; + + ASSERT(h->tag == SMM_HEAD_TAG); + + while (bh) { + ASSERT(bh->tag == SMMB_HEAD_FREE_TAG); + bh = bh->next; + ret++; + } + + return ret; +} +#endif diff --git a/uadk/v1/test/smm.h b/uadk/v1/test/smm.h new file mode 100644 index 0000000..55a1140 --- /dev/null +++ b/uadk/v1/test/smm.h @@ -0,0 +1,31 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#ifndef __SMM_H +#define __SMM_H + +//#include + +extern int smm_init(void *pt_addr, size_t size, unsigned int align_mask); +extern void *smm_alloc(void *pt_addr, size_t size); +extern void smm_free(void *pt_addr, void *ptr); + +#ifndef NDEBUG +extern void smm_dump(void *pt_addr); +extern int smm_get_freeblock_num(void *pt_addr); +#endif + +#endif diff --git a/uadk/v1/test/test_dummy.c b/uadk/v1/test/test_dummy.c new file mode 100644 index 0000000..75ab33a --- /dev/null +++ b/uadk/v1/test/test_dummy.c @@ -0,0 +1,126 @@ +/* + * Copyright 2018-2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#include "../config.h" +#include +#include +#include +#include +#include + +#include "wd_sched.h" +#include "wd_dummy_usr_if.h" +#include "dummy_hw_usr_if.h" + +#define CPSZ 4096 + +#define SYS_ERR_COND(cond, msg) if(cond) { \ + perror(msg); \ + exit(EXIT_FAILURE); } + +struct wd_dummy_cpy_msg *msgs; + +int wd_dummy_memcpy(struct wd_queue *q, void *dst, void *src, size_t size) +{ + struct wd_dummy_cpy_msg req, *resp; + int ret; + + req.src_addr = src; + req.tgt_addr = dst; + req.size = size; + + ret = wd_send(q, (void *)&req); + if (ret) + return ret; + + return wd_recv_sync(q, (void **)&resp, 1000); +} + +static void wd_dummy_sched_init_cache(struct wd_scheduler *sched, int i) +{ + sched->msgs[i].msg = &msgs[i]; + msgs[i].src_addr = sched->msgs[i].data_in; + msgs[i].tgt_addr = sched->msgs[i].data_out; + msgs[i].size = sched->msg_data_size; +} + +static int input_num = 10; +static int wd_dummy_sched_input(struct wd_msg *msg, void *priv) +{ + SYS_ERR_COND(input_num <= 0, "input"); + input_num--; + memset(msg->data_in, '0'+input_num, CPSZ); + memset(msg->data_out, 'x', CPSZ); + + return 0; +} + +static int wd_dummy_sched_output(struct wd_msg *msg, void *priv) +{ + int i; + char *in, *out; + + for (i = 0; i < CPSZ; i++) { + in = (char *)msg->data_in; + out = (char *)msg->data_out; + if(in[i] != out[i]) { + printf("verify result fail on %d\n", i); + break; + } + + } + printf("verify result (%d) success (remained=%d)\n", in[0], input_num); + + return 0; +} + +struct wd_scheduler sched = { + .q_num = 1, + .ss_region_size = 0, + .msg_cache_num = 4, + .msg_data_size = CPSZ, + .init_cache = wd_dummy_sched_init_cache, + .input = wd_dummy_sched_input, + .output = wd_dummy_sched_output, +}; + +int main(int argc, char *argv[]) +{ + int ret, i; + int max_step = 20; + + sched.qs = calloc(sched.q_num, sizeof(*sched.qs)); + SYS_ERR_COND(!sched.qs, "calloc"); + + msgs = calloc(sched.msg_cache_num, sizeof(*msgs)); + SYS_ERR_COND(!msgs, "calloc"); + + for (i = 0; i < sched.q_num; i++) + sched.qs[i].capa.alg = "memcpy"; + + ret = wd_sched_init(&sched); + SYS_ERR_COND(ret, "wd_sched_init"); + + while(input_num || !wd_sched_empty(&sched)) { + ret = wd_sched_work(&sched, input_num); + SYS_ERR_COND(ret < 0, "wd_sched_work"); + SYS_ERR_COND(max_step-- < 0, "max_step"); + } + + wd_sched_fini(&sched); + free(sched.qs); + return EXIT_SUCCESS; +} diff --git a/uadk/v1/test/test_mm/Makefile.am b/uadk/v1/test/test_mm/Makefile.am new file mode 100644 index 0000000..5d86690 --- /dev/null +++ b/uadk/v1/test/test_mm/Makefile.am @@ -0,0 +1,11 @@ +AM_CFLAGS=-Wall -O0 -fno-strict-aliasing -I$(top_srcdir)/v1/include -I$(top_srcdir)/v1 -I$(top_srcdir) -pthread + +bin_PROGRAMS=test_wd_mem + +test_wd_mem_SOURCES=test_wd_mem.c test_wd_mem.h + +if WD_STATIC_DRV +test_wd_mem_LDADD=../../../.libs/libwd.la -ldl -lnuma +else +test_wd_mem_LDADD=../../../.libs/libwd.so -ldl -lnuma +endif diff --git a/uadk/v1/test/test_mm/test_wd_mem.c b/uadk/v1/test/test_mm/test_wd_mem.c new file mode 100644 index 0000000..ba873f9 --- /dev/null +++ b/uadk/v1/test/test_mm/test_wd_mem.c @@ -0,0 +1,541 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#include "test_wd_mem.h" + +/* This head file is not API for user, should be deleted in the next */ +#include "wd_util.h" + +static int with_log = 0; +static pthread_t system_test_thrds[TEST_MAX_THRD]; +static struct mmt_pthread_dt test_thrds_data[TEST_MAX_THRD]; + +static int thrd_mem_size = 15; /* 15M defaultly */ + +#define MMT_PTHRD_MM_SZ (thrd_mem_size * 0x100000) + +static inline int _get_cpu_id(int thr, __u64 core_mask) +{ + __u64 i; + int cnt = 0; + + + for (i = 1; i < 64; i ++) { + if (core_mask & (0x1ull << i)) { + if (thr == cnt) + return i; + cnt++; + } + } + + return 0; +} + +static inline int _get_one_bits(__u64 val) +{ + int count = 0; + + while (val) { + if (val % 2 == 1) + count++; + val = val / 2; + } + + return count; +} + +void mmt_show_ss_slices(struct wd_queue *q) +{ + struct wd_ss_region *rgn; + struct q_info *qinfo = q->qinfo; + int i = 0; + + TAILQ_FOREACH(rgn, qinfo->head, next) { + MMT_PRT("slice-%d:va=%p,pa=0x%llx,size=0x%lx\n", + i, rgn->va, rgn->pa, rgn->size); + i++; + } +} + +static inline unsigned long long va_to_pa(struct wd_queue *q, void *va) +{ + return (unsigned long long)wd_iova_map(q, va, 0); +} + +static inline void *pa_to_va(struct wd_queue *q, unsigned long long pa) +{ + return wd_dma_to_va(q, (void *)pa); +} + +struct mmt_queue_mempool *mmt_test_mempool_create(struct wd_queue *q, + unsigned int block_size, unsigned int block_num) +{ + void *addr; + unsigned long rsv_mm_sz; + struct mmt_queue_mempool *pool; + unsigned int bitmap_sz; + + if (block_size > 4096) { + MMT_PRT("\ncurrent blk size is bellow 4k :)"); + return NULL; + } + rsv_mm_sz = block_size * block_num; + addr = wd_reserve_memory(q, rsv_mm_sz); + if (!addr) { + MMT_PRT("\nrequest queue fail!"); + return NULL; + } + bitmap_sz = (block_num / 32 + 1) * sizeof(unsigned int); + pool = malloc(sizeof(*pool) + bitmap_sz); + if (!pool) { + MMT_PRT("\nAlloc pool handle fail!"); + return NULL; + } + memset(pool, 0, sizeof(*pool) + bitmap_sz); + pool->base = addr; + memset(addr, 0, rsv_mm_sz); + sem_init(&pool->sem, 0, 1); + pool->block_size = block_size; + pool->block_num = block_num; + pool->free_num = block_num; + pool->bitmap = (unsigned int *)(pool + 1); + pool->mem_size = rsv_mm_sz; + + return pool; +} + +void mmt_test_mempool_destroy(struct mmt_queue_mempool *pool) +{ + free(pool); +} + +void *mmt_test_alloc_buf(struct mmt_queue_mempool *pool) +{ + __u64 i = 0; + __u64 j = 0; + __u64 tmp = 0; + __u32 *pbm = NULL; + + (void)sem_wait(&pool->sem); + pbm = pool->bitmap; + tmp = pool->index; + for (; pool->index < pool->block_num; pool->index++) { + i = (pool->index >> 5); + j = (pool->index & (32 - 1)); + if ((pbm[i] & ((__u32)0x1 << j)) == 0) { + pbm[i] |= ((__u32)0x1 << j); + tmp = pool->index; + pool->index++; + (void)sem_post(&pool->sem); + return (void *)((char *)pool->base + (tmp * + pool->block_size)); + } + } + for (pool->index = 0; pool->index < tmp; pool->index++) { + i = (pool->index >> 5); + j = (pool->index & (32 - 1)); + if ((pbm[i] & ((__u32)0x1 << j)) == 0) { + pbm[i] |= ((__u32)0x1 << j); + tmp = pool->index; + pool->index++; + (void)sem_post(&pool->sem); + return (void *)((char *)pool->base + + (tmp * pool->block_size)); + + } + } + (void)sem_post(&pool->sem); + + return NULL; +} + +void mmt_test_free_buf(struct mmt_queue_mempool *pool, void *pbuf) +{ + __u32 *pbm = pool->bitmap; + __u64 offset = 0; + __u32 bit_mask = 0; + + offset = (__u64)((unsigned long)pbuf - (unsigned long)pool->base); + offset = offset / pool->block_size; + if (pool->block_num <= offset) { + MMT_PRT("offset = %lld, virtual address err!\n", offset); + return; + } + bit_mask = ~(0x1u << (offset & 31)); + (void)sem_wait(&pool->sem); + pbm[(offset >> 5)] &= bit_mask; + (void)sem_post(&pool->sem); +} + +void *mmt_sys_test_thread(void *data) +{ + struct wd_queue rsa_q, zlib_q; + int ret, cpuid; + struct mmt_pthread_dt *pdata = data; + cpu_set_t mask; + int pid = getpid(), thread_index = pdata->thread_index; + int thread_id = (int)syscall(__NR_gettid); + void *rsa_thrd_rmm, *zlib_thrd_rmm; + + CPU_ZERO(&mask); + cpuid = pdata->cpu_id; + CPU_SET(cpuid, &mask); + if (cpuid) { + ret = pthread_setaffinity_np(pthread_self(), + sizeof(mask), &mask); + if (ret < 0) { + MMT_PRT("\nProc-%d, thrd-%d:set affinity fail!", + pid, thread_id); + return NULL; + } + MMT_PRT("\nProc-%d, thrd-%d bind to cpu-%d!\n", + pid, thread_id, cpuid); + } + memset((void *)&rsa_q, 0, sizeof(struct wd_queue)); + rsa_q.capa.alg = "rsa"; + ret = wd_request_queue(&rsa_q); + if (ret) { + MMT_PRT("\nProc-%d, thrd-%d:request rsa queue fail!", + pid, thread_id); + return NULL; + } + + ret = wd_share_reserved_memory(pdata->qinfo1.q, &rsa_q); + if (ret) { + wd_release_queue(&rsa_q); + MMT_PRT("Proc-%d, thrd-%d:share mem on rsa queue fail!\n", + pid, thread_id); + return NULL; + } + rsa_thrd_rmm = pdata->qinfo1.rmm; + memset((void *)&zlib_q, 0, sizeof(struct wd_queue)); + zlib_q.capa.alg = "zlib"; + ret = wd_request_queue(&zlib_q); + if (ret) { + wd_release_queue(&rsa_q); + MMT_PRT("Proc-%d, thrd-%d:request zlib queue fail!\n", + pid, thread_id); + + return NULL; + } + ret = wd_share_reserved_memory(pdata->qinfo2.q, &zlib_q); + if (ret) { + MMT_PRT("Proc-%d, thrd-%d:share mem on zlib queue fail!\n", + pid, thread_id); + + goto fail_release; + } + zlib_thrd_rmm = pdata->qinfo2.rmm; + + MMT_PRT("Proc-%d, thrd-%d,thrd_idx-%d:rsa_rmm=%p(pa=0x%llx), zlib_rmm=%p(pa=0x%llx)!\n", + pid, thread_id, thread_index, rsa_thrd_rmm,va_to_pa(&rsa_q, rsa_thrd_rmm), + zlib_thrd_rmm, va_to_pa(&zlib_q, zlib_thrd_rmm)); + + memset(rsa_thrd_rmm, (char)thread_index, MMT_PTHRD_MM_SZ); + memset(zlib_thrd_rmm, (char)thread_index, MMT_PTHRD_MM_SZ); + +#ifdef RESERV_RELASE_TEST + usleep(200000); +#endif + +fail_release: + wd_release_queue(&rsa_q); + wd_release_queue(&zlib_q); + printf("rsa share release\n"); + return NULL; +} + +static int mmt_sys_test(int thread_num, __u64 lcore_mask, + __u64 hcore_mask, struct mmt_q_info *q1, + struct mmt_q_info *q2) +{ + int i, ret, cnt = 0; + int h_cpuid; + + if (_get_one_bits(lcore_mask) > 0) + cnt = _get_one_bits(lcore_mask); + else if (_get_one_bits(lcore_mask) == 0 && + _get_one_bits(hcore_mask) == 0) + cnt = thread_num; + for (i = 0; i < cnt; i++) { + test_thrds_data[i].thread_num = thread_num; + test_thrds_data[i].thread_index = i; + test_thrds_data[i].cpu_id = _get_cpu_id(i, lcore_mask); + test_thrds_data[i].qinfo1.q = q1->q; + test_thrds_data[i].qinfo1.rmm = q1->rmm + i * MMT_PTHRD_MM_SZ; + test_thrds_data[i].qinfo1.size = MMT_PTHRD_MM_SZ; + + test_thrds_data[i].qinfo2.q = q2->q; + test_thrds_data[i].qinfo2.rmm = q2->rmm + i * MMT_PTHRD_MM_SZ; + test_thrds_data[i].qinfo2.size = MMT_PTHRD_MM_SZ; + + + ret = pthread_create(&system_test_thrds[i], NULL, + mmt_sys_test_thread, &test_thrds_data[i]); + if (ret) { + MMT_PRT("\nCreate %dth thread fail!", i); + return ret; + } + } + for (i = 0; i < thread_num - cnt; i++) { + h_cpuid = _get_cpu_id(i, hcore_mask); + if (h_cpuid > 0) + h_cpuid += 64; + test_thrds_data[i + cnt].thread_num = thread_num; + test_thrds_data[i + cnt].thread_index = i + cnt; + test_thrds_data[i + cnt].cpu_id = h_cpuid; + + test_thrds_data[i + cnt].qinfo1.q = q1->q; + test_thrds_data[i + cnt].qinfo1.rmm = q1->rmm + (i + cnt) * MMT_PTHRD_MM_SZ; + test_thrds_data[i + cnt].qinfo1.size = MMT_PTHRD_MM_SZ; + + test_thrds_data[i + cnt].qinfo2.q = q2->q; + test_thrds_data[i + cnt].qinfo2.rmm = q2->rmm + (i + cnt) * MMT_PTHRD_MM_SZ; + test_thrds_data[i + cnt].qinfo2.size = MMT_PTHRD_MM_SZ; + + ret = pthread_create(&system_test_thrds[i + cnt], NULL, + mmt_sys_test_thread, &test_thrds_data[i + cnt]); + if (ret) { + MMT_PRT("\nCreate %dth thread fail!", i); + return ret; + } + } + + return 0; +} + +struct wd_queue rsa_q; +void *rsa_q_rmm; + +void *thrd_reserve_mm(void *data) +{ + struct mmt_q_info *pdata = data; + size_t rmm_size = pdata->size; + int pid = getpid(); + int thread_id = (int)syscall(__NR_gettid); + int ret; + + memset((void *)&rsa_q, 0, sizeof(struct wd_queue)); + rsa_q.capa.alg = "rsa"; + ret = wd_request_queue(&rsa_q); + if (ret) { + MMT_PRT("\nProc-%d, thrd-%d:request rsa queue fail!", + pid, thread_id); + return NULL; + } + + pdata->rmm = wd_reserve_memory(&rsa_q, rmm_size); + if (!pdata->rmm) { + MMT_PRT("\nreserve mem on rsa queue fail!"); + goto reserve_fail; + } + rsa_q_rmm = pdata->rmm; + MMT_PRT("rsa queue RMM info:\n"); + mmt_show_ss_slices(&rsa_q); + + MMT_PRT("Proc-%d, thrd-%d:total_rsa_rmm=%p(pa=0x%llx, size=0x%lx)\n,", \ + pid, thread_id, rsa_q_rmm,\ + va_to_pa(&rsa_q, rsa_q_rmm), rmm_size); + + usleep(90000); + +reserve_fail: + wd_release_queue(&rsa_q); + printf("rsa_reserve release\n"); + return NULL; +} + +int main(int argc, char *argv[]) +{ + int ret = 0; + struct wd_queue zlib_q; + struct mmt_q_info rsa_qinfo, zlib_qinfo; + void *zlib_q_rmm; + struct mmt_q_info rsa_data; + pthread_t rsa_id; + size_t rmm_size; + int thread_num, bits; + int i = 0; + __u64 core_mask[2]; + int pid = getpid(); + int thread_id = (int)syscall(__NR_gettid); + cpu_set_t mask; + + CPU_ZERO(&mask); + CPU_SET(0, &mask); + ret = pthread_setaffinity_np(pthread_self(), + sizeof(mask), &mask); + if (ret < 0) { + MMT_PRT("\nProc-%d, thrd-%d:set affinity fail!", + pid, thread_id); + return -EINVAL; + } + + if (!argv[1] || !argv[4]) { + MMT_PRT("please use ./test_wd_mem -t [thread_num] -c [core_mask] [-log]!\n"); + return -EINVAL; + } + + if (!strcmp(argv[1], "-t")) { + thread_num = strtoul((char *)argv[2], NULL, 10); + if (thread_num <= 0 || thread_num > TEST_MAX_THRD) { + MMT_PRT("Invalid threads num:%d!", + thread_num); + MMT_PRT("Now set threads num as 2\n"); + thread_num = 2; + } + } else { + MMT_PRT("./test_wd_mem --help get details\n"); + return -EINVAL; + } + if (strcmp(argv[3], "-c")) { + MMT_PRT("./test_hisi_hpre --help get details\n"); + return -EINVAL; + } + + if (argv[4][0] != '0' || argv[4][1] != 'x') { + MMT_PRT("Err:coremask should be hex!\n"); + return -EINVAL; + } + if (strlen(argv[4]) > 34) { + MMT_PRT("Warning: coremask is cut!\n"); + argv[4][34] = 0; + } + if (strlen(argv[4]) <= 18) { + core_mask[0] = strtoull(argv[4], NULL, 16); + if (core_mask[0] & 0x1) { + MMT_PRT("Warn:cannot bind to core 0,"); + MMT_PRT("now run without binding\n"); + core_mask[0] = 0x0; /* no binding */ + } + core_mask[1] = 0; + } else { + int offset = 0; + char *temp; + + offset = strlen(argv[4]) - 16; + core_mask[0] = strtoull(&argv[4][offset], NULL, 16); + if (core_mask[0] & 0x1) { + MMT_PRT("Warn:cannot bind to core 0,"); + MMT_PRT("now run without binding\n"); + core_mask[0] = 0x0; /* no binding */ + } + temp = malloc(64); + strcpy(temp, argv[4]); + temp[offset] = 0; + core_mask[1] = strtoull(temp, NULL, 16); + free(temp); + } + bits = _get_one_bits(core_mask[0]); + bits += _get_one_bits(core_mask[1]); + if (thread_num > bits) { + MMT_PRT("Coremask not covers all thrds,"); + MMT_PRT("Bind first %d thrds!\n", bits); + } else if (thread_num < bits) { + MMT_PRT("Coremask overflow,"); + MMT_PRT("Just try to bind all thrds!\n"); + } + if (!strcmp(argv[5], "-log")) + with_log = 1; + else + with_log = 0; + if (argv[6]) { + thrd_mem_size = strtoul((char *)argv[6], NULL, 10); + if (thrd_mem_size <= 0 || thrd_mem_size > 1000) { + MMT_PRT("Invalid threads mem size %dMB!\n", thrd_mem_size); + MMT_PRT("Now set threads num as 15MB\n"); + thrd_mem_size = 15; + } + } else + thrd_mem_size = 15; + MMT_PRT("Proc-%d: starts %d threads bind to %s", + getpid(), thread_num, argv[4]); + MMT_PRT(" lcoremask=0x%llx, hcoremask=0x%llx\n", + core_mask[0], core_mask[1]); + MMT_PRT("Threads algorithm mem size %dMB!\n", thrd_mem_size); + memset((void *)&zlib_q, 0, sizeof(struct wd_queue)); + + + rmm_size = (thread_num + 1) * MMT_PTHRD_MM_SZ; + rsa_data.size = rmm_size; + + /* reserve 150MB memory for every rsa_q in each thread */ + ret = pthread_create(&rsa_id, NULL, thrd_reserve_mm, &rsa_data); + if (ret) + { + printf("create thread rsa_reserv mm fail\n"); + return ret; + } + zlib_q.capa.alg = "zlib"; + ret = wd_request_queue(&zlib_q); + if (ret) { + MMT_PRT("\nrequest zlib queue fail!"); + return ret; + } + + /* reserve 150MB memory for every zlib_q in each thread */ + rmm_size = (thread_num + 1) * MMT_PTHRD_MM_SZ; + zlib_q_rmm = wd_reserve_memory(&zlib_q, rmm_size); + if (!zlib_q_rmm) { + MMT_PRT("\nreserve mem on zlib queue fail!"); + goto exit_fail; + } + MMT_PRT("zlib queue RMM info:\n"); + mmt_show_ss_slices(&zlib_q); + + + MMT_PRT("Proc-%d, thrd-%d:total_zlib_rmm=%p(pa=0x%llx, size=0x%lx)!\n", + pid, thread_id, + zlib_q_rmm, va_to_pa(&zlib_q, zlib_q_rmm), rmm_size); + + zlib_qinfo.q = &zlib_q; + zlib_qinfo.size = rmm_size - MMT_PTHRD_MM_SZ; + zlib_qinfo.rmm = zlib_q_rmm + MMT_PTHRD_MM_SZ; + usleep(10000); + + rsa_qinfo.q = &rsa_q; + rsa_qinfo.size = rmm_size - MMT_PTHRD_MM_SZ; + rsa_qinfo.rmm = rsa_q_rmm + MMT_PTHRD_MM_SZ; + + + ret = mmt_sys_test(thread_num, core_mask[0], core_mask[1], &rsa_qinfo, &zlib_qinfo); + if (ret) { + MMT_PRT("\nstart multiple thread memory test fail!"); + goto exit_fail; + } + + + memset(zlib_q_rmm, 0, MMT_PTHRD_MM_SZ); + + ret = pthread_join(rsa_id, NULL); + if (ret) { + MMT_PRT("\nJoin %dth thread fail!", i); + goto exit_fail; + } + + for (i = 0; i < thread_num; i++) { + ret = pthread_join(system_test_thrds[i], NULL); + if (ret) { + MMT_PRT("\nJoin %dth thread fail!", i); + goto exit_fail; + } + } + +exit_fail: + + wd_release_queue(&zlib_q); + return ret; +} diff --git a/uadk/v1/test/test_mm/test_wd_mem.h b/uadk/v1/test/test_mm/test_wd_mem.h new file mode 100644 index 0000000..8a7f561 --- /dev/null +++ b/uadk/v1/test/test_mm/test_wd_mem.h @@ -0,0 +1,80 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#ifndef __TEST_WD_MEM_H +#define ___TEST_WD_MEM_H + +#include +#include +#include +#define __USE_GNU +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../../wd.h" + +#define MMT_PRT printf +#define TEST_MAX_THRD 128 +#define MAX_TRY_TIMES 10000 +#define LOG_INTVL_NUM 8 + +struct mmt_queue_mempool *mmt_test_mempool_create(struct wd_queue *q, + unsigned int block_size, unsigned int block_num); +void mmt_test_mempool_destroy(struct mmt_queue_mempool *pool); +void *mmt_test_alloc_buf(struct mmt_queue_mempool *pool); +void mmt_test_free_buf(struct mmt_queue_mempool *pool, void *buf); + +typedef unsigned long long (*v2p)(void *v); +typedef void * (*p2v)(unsigned long long p); + +struct mmt_queue_mempool { + struct wd_queue *q; + void *base; + unsigned int *bitmap; + unsigned int block_size; + unsigned int block_num; + unsigned int mem_size; + unsigned int block_align_size; + unsigned int free_num; + unsigned int fail_times; + unsigned long long index; + sem_t sem; + int dev; + v2p virt_to_phy; + p2v phy_to_virt; +}; + +struct mmt_q_info { + struct wd_queue *q; + void *rmm; + size_t size; +}; + +struct mmt_pthread_dt { + int cpu_id; + int thread_num; + int thread_index; + struct mmt_q_info qinfo1; + struct mmt_q_info qinfo2; +}; +#endif diff --git a/uadk/v1/test/wd_sched.c b/uadk/v1/test/wd_sched.c new file mode 100644 index 0000000..f5e4669 --- /dev/null +++ b/uadk/v1/test/wd_sched.c @@ -0,0 +1,309 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#include "config.h" +#include "v1/wd_util.h" +#include "v1/test/wd_sched.h" +#include "v1/wd_bmm.h" + +#define EXTRA_SIZE 4096 +#define WD_WAIT_MS 1000 + +static int __init_cache(struct wd_scheduler *sched) +{ + int i; + int ret = -ENOMEM; + struct q_info *qinfo; + void *pool; + + sched->msgs = calloc(sched->msg_cache_num, sizeof(*sched->msgs)); + if (!sched->msgs) { + WD_ERR("calloc for sched->msgs fail!\n"); + return ret; + } + sched->stat = calloc(sched->q_num, sizeof(*sched->stat)); + if (!sched->stat) { + WD_ERR("calloc for sched->stat fail!\n"); + goto err_with_msgs; + } + qinfo = sched->qs[0].qinfo; + pool = qinfo->br.usr; + for (i = 0; i < sched->msg_cache_num; i++) { + sched->msgs[i].data_in = wd_alloc_blk(pool); + sched->msgs[i].data_out = wd_alloc_blk(pool); + if (!sched->msgs[i].data_in || !sched->msgs[i].data_out) { + dbg("not enough data ss_region memory " + "for cache %d (bs=%d)\n", i, sched->msg_data_size); + goto err_with_stat; + } + + if (sched->init_cache) + sched->init_cache(sched, i); + } + + return 0; + +err_with_stat: + free(sched->stat); + sched->stat = NULL; +err_with_msgs: + free(sched->msgs); + sched->msgs = NULL; + return ret; +} + +static void __fini_cache(struct wd_scheduler *sched) +{ + struct q_info *qinfo = sched->qs[0].qinfo; + unsigned int flags = qinfo->dev_flags; + void *pool; + int i; + + if (sched->stat) { + free(sched->stat); + sched->stat = NULL; + } + if (!(flags & WD_UACCE_DEV_PASID)) { + pool = qinfo->br.usr; + if (pool) { + for (i = 0; i < sched->msg_cache_num; i++) { + if (sched->msgs[i].data_in) + wd_free_blk(pool, sched->msgs[i].data_in); + if (sched->msgs[i].data_out) + wd_free_blk(pool, sched->msgs[i].data_out); + } + wd_blkpool_destroy(pool); + } + } + if (sched->msgs) { + free(sched->msgs); + sched->msgs = NULL; + } +} + +static int wd_sched_preinit(struct wd_scheduler *sched) +{ + int ret, i, j; + unsigned int flags = 0; + struct q_info *qinfo; + struct wd_blkpool_setup mm_setup; + void *pool; + + for (i = 0; i < sched->q_num; i++) { + ret = wd_request_queue(&sched->qs[i]); + if (ret) { + WD_ERR("fail to request queue!\n"); + goto out_with_queues; + } + } + + if (!sched->ss_region_size) + sched->ss_region_size = EXTRA_SIZE + /* add 1 page extra */ + sched->msg_cache_num * (sched->msg_data_size << 0x1); + + qinfo = sched->qs[0].qinfo; + flags = qinfo->dev_flags; + if (flags & WD_UACCE_DEV_PASID) { + sched->ss_region = malloc(sched->ss_region_size); + if (!sched->ss_region) { + WD_ERR("fail to alloc sched ss region mem!\n"); + ret = -ENOMEM; + goto out_with_queues; + } + } else { + memset(&mm_setup, 0, sizeof(mm_setup)); + mm_setup.block_size = sched->msg_data_size; + mm_setup.block_num = sched->msg_cache_num << 0x1; /* in and out */ + mm_setup.align_size = 128; + pool = wd_blkpool_create(&sched->qs[0], &mm_setup); + if (!pool) { + WD_ERR("%s(): create pool fail!\n", __func__); + ret = -ENOMEM; + goto out_with_queues; + } + qinfo->br.alloc = (void *)wd_alloc_blk; + qinfo->br.free = (void *)wd_free_blk; + qinfo->br.iova_map = (void *)wd_blk_iova_map; + qinfo->br.iova_unmap = (void *)wd_blk_iova_unmap; + qinfo->br.usr = pool; + } + + return 0; + +out_with_queues: + if (flags & WD_UACCE_DEV_PASID) { + if (sched->ss_region) { + free(sched->ss_region); + sched->ss_region = NULL; + } + } + for (j = i-1; j >= 0; j--) + wd_release_queue(&sched->qs[j]); + return ret; +} + + +int wd_sched_init(struct wd_scheduler *sched) +{ + int ret, j, k; + unsigned int flags; + struct q_info *qinfo; + + ret = wd_sched_preinit(sched); + if (ret < 0) + return -EINVAL; + + qinfo = sched->qs[0].qinfo; + flags = qinfo->dev_flags; + if (!(flags & WD_UACCE_DEV_PASID)) { + for (k = 1; k < sched->q_num; k++) { + ret = wd_share_reserved_memory(&sched->qs[0], + &sched->qs[k]); + if (ret) { + WD_ERR("fail to share queue reserved mem!\n"); + goto out_with_queues; + } + } + } + + sched->cl = sched->msg_cache_num; + + ret = __init_cache(sched); + if (ret) { + WD_ERR("fail to init caches!\n"); + goto out_with_queues; + } + + return 0; + +out_with_queues: + if (flags & WD_UACCE_DEV_PASID) { + if (sched->ss_region) { + free(sched->ss_region); + sched->ss_region = NULL; + } + } + for (j = sched->q_num - 1; j >= 0; j--) + wd_release_queue(&sched->qs[j]); + return ret; +} + +void wd_sched_fini(struct wd_scheduler *sched) +{ + int i; + struct q_info *qinfo = sched->qs[0].qinfo; + unsigned int flags = qinfo->dev_flags; + + __fini_cache(sched); + if (flags & WD_UACCE_DEV_PASID) { + if (sched->ss_region) { + free(sched->ss_region); + sched->ss_region = NULL; + } + } + + for (i = sched->q_num - 1; i >= 0; i--) + wd_release_queue(&sched->qs[i]); +} + +static int __sync_send(struct wd_scheduler *sched) +{ + int ret; + + dbg("send ci(%d) to q(%d): %p\n", sched->c_h, sched->q_h, + sched->msgs[sched->c_h].msg); + do { + sched->stat[sched->q_h].send++; + ret = wd_send(&sched->qs[sched->q_h], + sched->msgs[sched->c_h].msg); + if (ret == -EBUSY) { + usleep(1); + sched->stat[sched->q_h].send_retries++; + continue; + } + if (ret) + return ret; + } while (ret); + + sched->q_h = (sched->q_h + 1) % sched->q_num; + return 0; +} + +static int __sync_wait(struct wd_scheduler *sched) +{ + void *recv_msg = NULL; + int ret; + + dbg("recv, ci(%d) from q(%d): %p\n", sched->c_t, sched->q_t, + sched->msgs[sched->c_h].msg); + do { + sched->stat[sched->q_t].recv++; + ret = wd_recv(&sched->qs[sched->q_t], &recv_msg); + if (ret == 0) { + sched->stat[sched->q_t].recv_retries++; + continue; + } else if (ret == -WD_EIO || ret == -WD_HW_EACCESS) + return ret; + + if (recv_msg != sched->msgs[sched->c_t].msg) { + fprintf(stderr, "recv msg %p and input %p mismatch\n", + recv_msg, sched->msgs[sched->c_t].msg); + return -EINVAL; + } + } while (!ret); + + sched->q_t = (sched->q_t + 1) % sched->q_num; + return 0; +} + +/* return number of msg in the sent cache or negative errno */ +int wd_sched_work(struct wd_scheduler *sched, int remained) +{ + int ret; + +#define MOV_INDEX(id) do { \ + sched->id = (sched->id + 1) % sched->msg_cache_num; \ +} while (0) + + dbg("sched: cl=%d, data_remained=%d\n", sched->cl, remained); + + if (sched->cl && remained) { + ret = sched->input(&sched->msgs[sched->c_h], sched->priv); + if (ret) + return ret; + + ret = __sync_send(sched); + if (ret) + return ret; + + MOV_INDEX(c_h); + sched->cl--; + } else { + ret = __sync_wait(sched); + if (ret) + return ret; + + ret = sched->output(&sched->msgs[sched->c_t], sched->priv); + if (ret) + return ret; + + MOV_INDEX(c_t); + sched->cl++; + } + + return sched->cl; +} + diff --git a/uadk/v1/test/wd_sched.h b/uadk/v1/test/wd_sched.h new file mode 100644 index 0000000..7cdbf2e --- /dev/null +++ b/uadk/v1/test/wd_sched.h @@ -0,0 +1,71 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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 common drv header define the unified interface for wd */ +#ifndef __WD_SCHED_H__ +#define __WD_SCHED_H__ + +#include "../wd.h" + +struct wd_msg { + void *data_in; + void *data_out; + void *msg; +}; + +struct wd_scheduler { + struct wd_queue *qs; + int q_num; + + void *ss_region; + size_t ss_region_size; + + struct wd_msg *msgs; + int msg_cache_num; + unsigned int msg_data_size; + + /* cache head, cache tail */ + int c_h, c_t; + /* queue head, queue tail */ + int q_h, q_t; + /* cache left */ + int cl; + + void (*init_cache)(struct wd_scheduler *sched, int i); + int (*input)(struct wd_msg *msg, void *priv); + int (*output)(struct wd_msg *msg, void *priv); + + void *priv; + + /* statistic */ + struct { + int send; + int send_retries; + int recv; + int recv_retries; + } *stat; +}; + +extern int wd_sched_init(struct wd_scheduler *sched); +extern void wd_sched_fini(struct wd_scheduler *sched); +extern int wd_sched_work(struct wd_scheduler *sched, int have_input); + +static inline int wd_sched_empty(struct wd_scheduler *sched) +{ + return sched->cl == sched->msg_cache_num; +} + +#endif diff --git a/uadk/v1/uacce.h b/uadk/v1/uacce.h new file mode 100644 index 0000000..d45062e --- /dev/null +++ b/uadk/v1/uacce.h @@ -0,0 +1,86 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#ifndef _UAPI_WD_UACCE_H +#define _UAPI_WD_UACCE_H + +#include +#include + +#define WD_UACCE_CLASS_NAME "uacce" + +/** + * WD_UACCE Device Attributes: + * + * NOIOMMU: the device has no IOMMU support + * can do ssva, but no map to the dev + * IOMMU: the device has IOMMU support + * PASID: the device has IOMMU which support PASID setting + * can do ssva, mapped to dev per process + * FAULT_FROM_DEV: the device has IOMMU which can do page fault request + * no need for ssva, should be used with PASID + * KMAP_DUS: map the Device user-shared space to kernel + * DRVMAP_DUS: Driver self-maintain its DUS + * SVA: full function device + * SHARE_DOMAIN: no PASID, can do ssva only for one process and the kernel + */ +#define WD_UACCE_DEV_SVA (1<<0) +#define WD_UACCE_DEV_NOIOMMU (1<<1) +#define WD_UACCE_DEV_PASID (1<<2) +#define WD_UACCE_DEV_IOMMU (1<<7) + +/* uacce mode of the driver */ +#define WD_UACCE_MODE_NOWD_UACCE 0 /* don't use uacce */ +#define WD_UACCE_MODE_NOIOMMU 2 /* use uacce noiommu mode */ + +#define WD_UACCE_API_VER_NOIOMMU_SUBFIX "_noiommu" +#define WD_UACCE_QFR_NA ((unsigned long)-1) + +/** + * enum uacce_qfrt: queue file region type + * @WD_UACCE_QFRT_MMIO: device mmio region + * @WD_UACCE_QFRT_DUS: device user share region + * @WD_UACCE_QFRT_SS: static share memory(no-sva) + */ +enum uacce_qfrt { + WD_UACCE_QFRT_MMIO = 0, /* device mmio region */ + WD_UACCE_QFRT_DUS, /* device user share */ + WD_UACCE_QFRT_SS, /* static share memory */ + WD_UACCE_QFRT_MAX, +}; + +#define WD_UACCE_QFRT_INVALID WD_UACCE_QFRT_MAX + +/* Pass DMA SS region slice size by granularity 64KB */ +#define WD_UACCE_GRAN_SIZE 0x10000ull +#define WD_UACCE_GRAN_SHIFT 16 +#define WD_UACCE_GRAN_NUM_MASK 0xfffull + +/* + * WD_UACCE_CMD_START_Q: Start queue + */ +#define WD_UACCE_CMD_START_Q _IO('W', 0) + +/* + * WD_UACCE_CMD_PUT_Q: + * User actively stop queue and free queue resource immediately + * Optimization method since close fd may delay + */ +#define WD_UACCE_CMD_PUT_Q _IO('W', 1) +#define WD_UACCE_CMD_SHARE_SVAS _IO('W', 2) +#define WD_UACCE_CMD_GET_SS_DMA _IOR('W', 3, unsigned long) + +#endif diff --git a/uadk/v1/wd.c b/uadk/v1/wd.c new file mode 100644 index 0000000..8ac2b1a --- /dev/null +++ b/uadk/v1/wd.c @@ -0,0 +1,904 @@ +/* + * Copyright 2018-2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "v1/wd_util.h" +#include "v1/wd_adapter.h" +#include "v1/wd.h" + +#define LINUX_DEV_DIR "/dev" +#define WD_UACCE_CLASS_DIR "/sys/class/"WD_UACCE_CLASS_NAME +#define _TRY_REQUEST_TIMES 64 +#define INT_MAX_SIZE 10 +#define LINUX_CRTDIR_SIZE 1 +#define LINUX_PRTDIR_SIZE 2 +#define INSTANCE_RATIO_FOR_DEV_SCHED 4 + +#define GET_WEIGHT(distance, instances) (\ + ((instances) & 0xffff) | (((distance) & 0xffff) << 16)) +#define GET_NODE_DISTANCE(weight) (((weight) >> 16) & 0xffff) +#define GET_AVAILABLE_INSTANCES(weight) ((weight) & 0xffff) + +#ifdef WITH_LOG_FILE +FILE * flog_fd = NULL; +#endif + +wd_log log_out = NULL; + +#define container_of(ptr, type, member) ({ \ + typeof(((type *)0)->member)(*__mptr) = (ptr); \ + (type *)((char *)__mptr - offsetof(type, member)); }) + +struct dev_info { + int node_id; + int numa_dis; + int flags; + int ref; + int available_instances; + int iommu_type; + unsigned int weight; + char dev_root[PATH_STR_SIZE]; + char name[WD_NAME_SIZE]; + char api[WD_NAME_SIZE]; + char algs[MAX_ATTR_STR_SIZE]; + unsigned long qfrs_offset[WD_UACCE_QFRT_MAX]; +}; + +static int get_raw_attr(const char *dev_root, const char *attr, + char *buf, size_t sz) +{ + char attr_file[PATH_STR_SIZE]; + char attr_path[PATH_MAX]; + char *ptrRet = NULL; + int fd, size; + + size = snprintf(attr_file, PATH_STR_SIZE, "%s/%s", + dev_root, attr); + if (size <= 0) { + WD_ERR("get %s/%s path fail!\n", dev_root, attr); + return size; + } + + ptrRet = realpath(attr_file, attr_path); + if (ptrRet == NULL) + return -WD_ENODEV; + + /* The attr_file = "/sys/class/uacce/xxx" + * It's the Internal Definition File Node + */ + fd = open(attr_path, O_RDONLY, 0); + if (fd < 0) { + WD_ERR("open %s fail, errno = %d!\n", attr_path, errno); + return -ENODEV; + } + size = read(fd, buf, sz); + if (size <= 0) { + WD_ERR("read nothing at %s!\n", attr_path); + size = -ENODEV; + } + + close(fd); + return size; +} + +static int get_int_attr(struct dev_info *dinfo, const char *attr) +{ + char buf[MAX_ATTR_STR_SIZE] = {'\0'}; + int ret; + + ret = get_raw_attr(dinfo->dev_root, attr, buf, MAX_ATTR_STR_SIZE - 1); + if (ret < 0) + return ret; + + ret = strtol(buf, NULL, 10); + if (errno == ERANGE) { + WD_ERR("failed to strtol %s, out of range!\n", buf); + return -errno; + } + + return ret; +} + +/* + * Get string from an attr of sysfs. '\n' is used as a token of substring. + * So '\n' could be in the middle of the string or at the last of the string. + * Now remove the token '\n' at the end of the string to avoid confusion. + */ +static int get_str_attr(struct dev_info *dinfo, const char *attr, char *buf, + size_t buf_sz) +{ + int size; + + size = get_raw_attr(dinfo->dev_root, attr, buf, buf_sz); + if (size < 0) { + buf[0] = '\0'; + return size; + } + + if (size == buf_sz) + size = size - 1; + + buf[size] = '\0'; + while ((size > 1) && (buf[size - 1] == '\n')) { + buf[size - 1] = '\0'; + size = size - 1; + } + return size; +} + +static int get_ul_vec_attr(struct dev_info *dinfo, const char *attr, + unsigned long *vec, int vec_sz) +{ + char buf[MAX_ATTR_STR_SIZE]; + int size, i, j; + char *begin, *end; + + size = get_raw_attr(dinfo->dev_root, attr, buf, MAX_ATTR_STR_SIZE); + if (size < 0 || size >= MAX_ATTR_STR_SIZE) { + for (i = 0; i < vec_sz; i++) + vec[i] = 0; + return size; + } + + /* + * The unsigned long int max number is ULLONG_MAX 20bit + * char "18446744073709551615" When the value is + * bigger than ULLONG_MAX, It returns ULLONG_MAX + */ + buf[size] = '\0'; + begin = buf; + for (i = 0; i < vec_sz; i++) { + vec[i] = strtoul(begin, &end, 10); + if (!end) + break; + begin = end; + } + + for (j = i; j < vec_sz; j++) + vec[j] = 0; + + return 0; +} + +static bool is_alg_support(struct dev_info *dinfo, const char *alg) +{ + char *alg_save = NULL; + char *alg_tmp; + + if (!alg) + return false; + + alg_tmp = strtok_r(dinfo->algs, "\n", &alg_save); + while (alg_tmp != NULL) { + if (!strcmp(alg_tmp, alg)) + return true; + + alg_tmp = strtok_r(NULL, "\n", &alg_save); + } + + return false; +} + +static bool is_weight_more(unsigned int new, unsigned int old) +{ + unsigned int ins_new, dis_new; + unsigned int ins_old, dis_old; + + ins_new = GET_AVAILABLE_INSTANCES(new); + dis_new = GET_NODE_DISTANCE(new); + ins_old = GET_AVAILABLE_INSTANCES(old); + dis_old = GET_NODE_DISTANCE(old); + + dbg("dis_new %u, ins_new %u,dis_old %u, ins_old %u\n", + dis_new, ins_new, dis_old, ins_old); + + if (dis_new > dis_old) + return ins_new > ins_old * INSTANCE_RATIO_FOR_DEV_SCHED; + else if (dis_new == dis_old) + return ins_new > ins_old; + else + return ins_new * INSTANCE_RATIO_FOR_DEV_SCHED >= ins_old; +} + +static void get_iommu_type(struct dev_info *dinfo) +{ + if ((unsigned int)dinfo->flags & WD_UACCE_DEV_IOMMU) + dinfo->iommu_type = 1; + else + dinfo->iommu_type = 0; +} + +static int get_int_attr_all(struct dev_info *dinfo) +{ + int ret; + + /* ret == 1 means device has been isolated */ + ret = get_int_attr(dinfo, "isolate"); + if (ret < 0) + return -ENODEV; + else if (ret == 1) + return -EBUSY; + + /* ret == 0 means device has no available queues */ + ret = get_int_attr(dinfo, "available_instances"); + if (ret < 0) + return -ENODEV; + else if (ret == 0) + return -EBUSY; + + dinfo->available_instances = ret; + + ret = get_int_attr(dinfo, "numa_distance"); + if (ret < 0) + return ret; + dinfo->numa_dis = ret; + + dinfo->node_id = get_int_attr(dinfo, "node_id"); + + ret = get_int_attr(dinfo, "flags"); + if (ret < 0) + return ret; + else if ((unsigned int)ret & WD_UACCE_DEV_SVA) + return -ENODEV; + + dinfo->flags = ret; + + return 0; +} + +static int get_str_attr_all(struct dev_info *dinfo, const char *alg) +{ + int ret; + + ret = get_str_attr(dinfo, "algorithms", + dinfo->algs, MAX_ATTR_STR_SIZE); + if (ret < 0) + return ret; + + /* Add algorithm check to cut later pointless logic */ + ret = is_alg_support(dinfo, alg); + if (!ret) + return -EPFNOSUPPORT; + + ret = get_str_attr(dinfo, "api", dinfo->api, WD_NAME_SIZE); + if (ret < 0) + return ret; + + return 0; +} + +static int get_ul_vec_attr_all(struct dev_info *dinfo) +{ + int ret; + + ret = get_ul_vec_attr(dinfo, "region_mmio_size", + &dinfo->qfrs_offset[WD_UACCE_QFRT_MMIO], 1); + if (ret < 0) + return ret; + + ret = get_ul_vec_attr(dinfo, "region_dus_size", + &dinfo->qfrs_offset[WD_UACCE_QFRT_DUS], 1); + if (ret < 0) + return ret; + + return 0; +} + +static int get_dev_info(struct dev_info *dinfo, const char *alg) +{ + char buf[PATH_STR_SIZE] = {0}; + int ret; + + ret = snprintf(buf, PATH_STR_SIZE, "%s/%s", + LINUX_DEV_DIR, dinfo->name); + if (ret <= 0) { + WD_ERR("snprintf err, ret %d!\n", ret); + return -EINVAL; + } + + ret = access(buf, F_OK); + if (ret < 0) { + WD_ERR("failed to check file path %s, ret: %d\n", buf, ret); + return -ENODEV; + } + + ret = get_str_attr_all(dinfo, alg); + if (ret) + return ret; + + ret = get_int_attr_all(dinfo); + if (ret) + return ret; + + ret = get_ul_vec_attr_all(dinfo); + if (ret) + return ret; + + get_iommu_type(dinfo); + /* + * Use available_instances and numa_distance combine weight. + * | 2 bytes | 2bytes |. + * |numa_distance|available_instances|. + */ + dinfo->weight = GET_WEIGHT((__u32)dinfo->numa_dis, + (__u32)dinfo->available_instances); + + return 0; +} + +static bool copy_if_better(struct dev_info *old, struct dev_info *new, + unsigned int node_mask) +{ + bool find_node = false; + + dbg("try accelerator %s (inst_num=%d, node_id=%d)...\n", new->name, + new->available_instances, new->node_id); + + if (new->node_id >= 0 && + ((1 << (unsigned int)new->node_id) & node_mask)) + find_node = true; + + if (old && (!old->name[0] || find_node || + is_weight_more(new->weight, old->weight))) { + memcpy(old, new, sizeof(*old)); + dbg("adopted\n"); + } + + return find_node; +} + +static void pre_init_dev(struct dev_info *dinfo, const char *name) +{ + int ret; + + ret = snprintf(dinfo->name, WD_NAME_SIZE, "%s", name); + if (ret < 0) { + WD_ERR("get file name fail!\n"); + return; + } + + /* check the "attrs" file directory exists */ + ret = snprintf(dinfo->dev_root, PATH_STR_SIZE, + "%s/%s/attrs", WD_UACCE_CLASS_DIR, name); + if (ret < 0) { + WD_ERR("failed to copy dev attrs file path!\n"); + return; + } + + ret = access(dinfo->dev_root, F_OK); + if (ret < 0) { + ret = snprintf(dinfo->dev_root, PATH_STR_SIZE, + "%s/%s", WD_UACCE_CLASS_DIR, name); + if (ret < 0) + WD_ERR("failed to copy dev file path!\n"); + return; + } +} + +static int get_denoted_dev(struct wd_capa *capa, const char *dev, + struct dev_info *dinfop) +{ + pre_init_dev(dinfop, dev); + if (!get_dev_info(dinfop, capa->alg)) + return 0; + WD_ERR("%s not available, will try other devices\n", dev); + return -ENODEV; +} + +static int find_available_dev(struct dev_info *dinfop, + struct wd_capa *capa, + unsigned int node_mask) +{ + struct dirent *device; + DIR *wd_class = NULL; + bool find_node = false; + struct dev_info dinfo; + char *name; + int cnt = 0; + int ret; + + wd_class = opendir(WD_UACCE_CLASS_DIR); + if (!wd_class) { + WD_ERR("WD framework is not enabled on the system, errno = %d!\n", errno); + return -ENODEV; + } + + while (true) { + device = readdir(wd_class); + if (!device) + break; + name = device->d_name; + if (!strncmp(name, ".", LINUX_CRTDIR_SIZE) || + !strncmp(name, "..", LINUX_PRTDIR_SIZE)) + continue; + pre_init_dev(&dinfo, name); + ret = get_dev_info(&dinfo, capa->alg); + if (!ret) { + cnt++; + if (copy_if_better(dinfop, &dinfo, node_mask)) { + find_node = true; + break; + } + } else if (ret == -EPFNOSUPPORT || ret == -EBUSY || ret == -ENODEV) { + continue; + } else { + closedir(wd_class); + return ret; + } + } + + if (node_mask && !find_node) + WD_ERR("Device not available on nodemask 0x%x!\n", node_mask); + + closedir(wd_class); + return cnt; +} + +static int find_available_res(struct wd_queue *q, struct dev_info *dinfop, + int *num) +{ + struct wd_capa *capa = &q->capa; + const char *dev = q->dev_path; + int ret; + + /* As user denotes a device */ + if (dev[0] && dev[0] != '/' && !strstr(dev, "../")) { + if (!dinfop) { + WD_ERR("dinfop NULL!\n"); + return -EINVAL; + } + + if (q->node_mask) { + WD_ERR("dev and node cannot be denoted together!\n"); + return -EINVAL; + } + + if (!get_denoted_dev(capa, dev, dinfop)) + goto dev_path; + } + + ret = find_available_dev(dinfop, capa, q->node_mask); + if (ret <= 0 && dinfop) { + WD_ERR("get /%s path fail!\n", dinfop->name); + return -ENODEV; + } + + if (num) { + *num = ret; + return 0; + } + +dev_path: + if (!dinfop) { + WD_ERR("dinfop NULL!\n"); + return -EINVAL; + } + + ret = snprintf(q->dev_path, PATH_STR_SIZE, "%s/%s", + LINUX_DEV_DIR, dinfop->name); + if (ret <= 0) { + WD_ERR("snprintf err, ret %d!\n", ret); + return -EINVAL; + } + return 0; +} + +static int get_queue_from_dev(struct wd_queue *q, const struct dev_info *dev) +{ + char q_path[PATH_MAX]; + char *ptrRet = NULL; + struct q_info *qinfo; + + qinfo = q->qinfo; + ptrRet = realpath(q->dev_path, q_path); + if (ptrRet == NULL) + return -WD_ENODEV; + + qinfo->fd = open(q_path, O_RDWR | O_CLOEXEC); + if (qinfo->fd == -1) { + WD_ERR("open %s failed, errno = %d!\n", q_path, errno); + return -WD_ENODEV; + } + + qinfo->hw_type = dev->api; + qinfo->dev_flags = dev->flags; + qinfo->iommu_type = dev->iommu_type; + qinfo->dev_info = dev; + qinfo->head = &qinfo->ss_list; + __atomic_clear(&qinfo->ref, __ATOMIC_RELEASE); + TAILQ_INIT(&qinfo->ss_list); + memcpy(qinfo->qfrs_offset, dev->qfrs_offset, + sizeof(qinfo->qfrs_offset)); + + return 0; +} + +static int wd_start_queue(struct wd_queue *q) +{ + int ret; + struct q_info *qinfo = q->qinfo; + + ret = ioctl(qinfo->fd, WD_UACCE_CMD_START_Q); + if (ret) + WD_ERR("failed to start queue of %s\n", q->dev_path); + return ret; +} + +static void wd_close_queue(struct wd_queue *q) +{ + struct q_info *qinfo = q->qinfo; + + close(qinfo->fd); +} + +int wd_request_queue(struct wd_queue *q) +{ + struct dev_info *dinfop; + int try_cnt = 0; + int ret; + + if (!q) { + WD_ERR("input parameter q is NULL!\n"); + return -WD_EINVAL; + } + + dinfop = calloc(1, sizeof(struct q_info) + sizeof(struct dev_info)); + if (!dinfop) { + WD_ERR("calloc for queue info fail!\n"); + return -WD_ENOMEM; + }; + q->qinfo = dinfop + 1; + + do { + ret = find_available_res(q, dinfop, NULL); + if (ret) { + WD_ERR("cannot find available device\n"); + goto err_with_dev; + } + + ret = get_queue_from_dev(q, (const struct dev_info *)dinfop); + if (!ret) { + break; + } else { + if (try_cnt++ > _TRY_REQUEST_TIMES) { + WD_ERR("fail to get queue!\n"); + goto err_with_dev; + } + + memset(dinfop, 0, sizeof(*dinfop)); + } + } while (true); + + ret = drv_open(q); + if (ret) { + WD_ERR("failed to initialize queue by driver!\n"); + goto err_with_fd; + } + + ret = wd_start_queue(q); + if (ret) + goto err_with_drv_openned; + return ret; + +err_with_drv_openned: + drv_close(q); +err_with_fd: + wd_close_queue(q); +err_with_dev: + free(dinfop); + q->qinfo = NULL; + return ret; +} + +void wd_release_queue(struct wd_queue *q) +{ + struct wd_ss_region_list *head; + struct q_info *qinfo, *sqinfo; + + if (!q || !q->qinfo) { + WD_ERR("release queue parameter error!\n"); + return; + } + qinfo = q->qinfo; + if (__atomic_load_n(&qinfo->ref, __ATOMIC_RELAXED)) { + WD_ERR("q(%s) is busy, release fail!\n", q->capa.alg); + return; + } + head = qinfo->head; + sqinfo = container_of(head, struct q_info, ss_list); + if (sqinfo != qinfo) /* q_share */ + __atomic_sub_fetch(&sqinfo->ref, 1, __ATOMIC_RELAXED); + + if (ioctl(qinfo->fd, WD_UACCE_CMD_PUT_Q)) + WD_ERR("failed to put queue!\n"); + + drv_close(q); + + /* q_reserve */ + if (qinfo->ss_size) + drv_unmap_reserve_mem(q, qinfo->ss_va, qinfo->ss_size); + + drv_free_slice(q); + + wd_close_queue(q); + free((void *)qinfo->dev_info); + q->qinfo = NULL; +} + +int wd_send(struct wd_queue *q, void *req) +{ + if (unlikely(!q || !req)) { + WD_ERR("wd send input parameter null!\n"); + return -EINVAL; + } + return wd_burst_send(q, &req, 1); +} + +int wd_recv(struct wd_queue *q, void **resp) +{ + if (unlikely(!q || !resp)) { + WD_ERR("wd recv input parameter null!\n"); + return -EINVAL; + } + return wd_burst_recv(q, resp, 1); +} + +int wd_wait(struct wd_queue *q, __u16 ms) +{ + struct q_info *qinfo; + struct wcrypto_paras *priv; + struct pollfd fds[1]; + int ret; + + if (unlikely(!q)) + return -EINVAL; + + priv = &q->capa.priv; + if (unlikely(!priv->is_poll)) + return -EINVAL; + + qinfo = q->qinfo; + fds[0].fd = qinfo->fd; + fds[0].events = POLLIN; + + ret = poll(fds, 1, ms); + if (unlikely(ret < 0)) + return -ENODEV; + + /* return 0 for no data, 1 for new message */ + return ret; +} + +int wd_recv_sync(struct wd_queue *q, void **resp, __u16 ms) +{ + int ret; + + ret = wd_wait(q, ms); + if (likely(ret > 0)) + return wd_recv(q, resp); + + return ret; +} + +void *wd_reserve_memory(struct wd_queue *q, size_t size) +{ + if (!q || !size) { + WD_ERR("wd reserve memory: parameter err!\n"); + return NULL; + } + + return drv_reserve_mem(q, size); +} + +int wd_share_reserved_memory(struct wd_queue *q, + struct wd_queue *target_q) +{ + const struct dev_info *info, *tgt_info; + struct q_info *qinfo, *tqinfo; + int ret; + + if (!q || !target_q || !q->qinfo || !target_q->qinfo) { + WD_ERR("wd share reserved memory: parameter err!\n"); + return -WD_EINVAL; + } + + qinfo = q->qinfo; + tqinfo = target_q->qinfo; + tgt_info = tqinfo->dev_info; + info = qinfo->dev_info; + + /* Just share DMA memory from 'q' in NO-IOMMU mode */ + if (qinfo->iommu_type) { + WD_ERR("IOMMU opened, not support share mem!\n"); + return -EINVAL; + } + + if (qinfo->iommu_type != tqinfo->iommu_type) { + WD_ERR("IOMMU type mismatching as share mem!\n"); + return -WD_EINVAL; + } + if (info->node_id != tgt_info->node_id) + WD_ERR("Warn: the 2 queues is not at the same node!\n"); + + ret = ioctl(qinfo->fd, WD_UACCE_CMD_SHARE_SVAS, tqinfo->fd); + if (ret) { + WD_ERR("ioctl share dma memory fail!\n"); + return ret; + } + + tqinfo->head = qinfo->head; + __atomic_add_fetch(&qinfo->ref, 1, __ATOMIC_RELAXED); + + return 0; +} + +int wd_get_available_dev_num(const char *algorithm) +{ + struct wd_queue q; + int num = -1; + int ret; + + if (!algorithm) { + WD_ERR("algorithm is null!\n"); + return -WD_EINVAL; + } + + memset(&q, 0, sizeof(q)); + q.capa.alg = algorithm; + q.dev_path[0] = 0; + ret = find_available_res(&q, NULL, &num); + if (ret < 0) + WD_ERR("find_available_res err, ret = %d!\n", ret); + return num; +} + +int wd_get_node_id(struct wd_queue *q) +{ + const struct dev_info *dev = NULL; + struct q_info *qinfo = NULL; + + if (!q || !q->qinfo || !((struct q_info *)(q->qinfo))->dev_info) { + WD_ERR("q, info or dev_info NULL!\n"); + return -WD_EINVAL; + } + + qinfo = q->qinfo; + dev = qinfo->dev_info; + + return dev->node_id; +} + +void *wd_iova_map(struct wd_queue *q, void *va, size_t sz) +{ + struct wd_ss_region *rgn; + struct q_info *qinfo; + + if (!q || !va) { + WD_ERR("wd iova map: parameter err!\n"); + return NULL; + } + + qinfo = q->qinfo; + + TAILQ_FOREACH(rgn, qinfo->head, next) { + if (rgn->va <= va && va < rgn->va + rgn->size) + return (void *)(uintptr_t)(rgn->pa + + ((uintptr_t)va - (uintptr_t)rgn->va)); + } + + return NULL; +} + +void wd_iova_unmap(struct wd_queue *q, void *va, void *dma, size_t sz) +{ + /* For no-iommu, dma-unmap doing nothing */ +} + +void *wd_dma_to_va(struct wd_queue *q, void *dma) +{ + struct wd_ss_region *rgn; + struct q_info *qinfo; + uintptr_t va; + + if (!q || !q->qinfo || !dma) { + WD_ERR("wd dma to va, parameter err!\n"); + return NULL; + } + + qinfo = q->qinfo; + + TAILQ_FOREACH(rgn, qinfo->head, next) { + if (rgn->pa <= (uintptr_t)dma && + (uintptr_t)dma < rgn->pa + rgn->size) { + va = (uintptr_t)dma - rgn->pa + (uintptr_t)rgn->va; + return (void *)va; + } + } + + return NULL; +} + +void *wd_drv_mmap_qfr(struct wd_queue *q, enum uacce_qfrt qfrt, size_t size) +{ + struct q_info *qinfo = q->qinfo; + size_t tmp = size; + off_t off; + + off = qfrt * getpagesize(); + + if (qfrt != WD_UACCE_QFRT_SS) + tmp = qinfo->qfrs_offset[qfrt]; + + return mmap(0, tmp, PROT_READ | PROT_WRITE, + MAP_SHARED, qinfo->fd, off); +} + +void wd_drv_unmmap_qfr(struct wd_queue *q, void *addr, + enum uacce_qfrt qfrt, size_t size) +{ + struct q_info *qinfo = q->qinfo; + + if (!addr) + return; + + if (qfrt != WD_UACCE_QFRT_SS) + munmap(addr, qinfo->qfrs_offset[qfrt]); + else + munmap(addr, size); +} +int wd_register_log(wd_log log) +{ + if (!log) { + WD_ERR("input log is null!\n"); + return -WD_EINVAL; + } + + if (log_out) { + WD_ERR("can not duplicate register!\n"); + return -WD_EINVAL; + } + + log_out = log; + dbg("log register\n"); + + return WD_SUCCESS; +} + +const char *wd_get_drv(struct wd_queue *q) +{ + struct q_info *qinfo; + const struct dev_info *dev; + + if (!q || !q->qinfo) + return NULL; + + qinfo = q->qinfo; + dev = qinfo->dev_info; + + return (const char *)dev->api; +} diff --git a/uadk/v1/wd.h b/uadk/v1/wd.h new file mode 100644 index 0000000..1bd9669 --- /dev/null +++ b/uadk/v1/wd.h @@ -0,0 +1,214 @@ +/* + * Copyright 2018-2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#ifndef __WD_H +#define __WD_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "uacce.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define SYS_VAL_SIZE 16 +#define PATH_STR_SIZE 256 +#define MAX_ATTR_STR_SIZE 256 +#define WD_NAME_SIZE 64 +#define WCRYPTO_MAX_BURST_NUM 16 + +/* WD error code */ +#define WD_SUCCESS 0 +#define WD_STREAM_END 1 +#define WD_STREAM_START 2 +#define WD_EIO EIO +#define WD_EAGAIN EAGAIN +#define WD_ENOMEM ENOMEM +#define WD_EACCESS EACCESS +#define WD_EBUSY EBUSY +#define WD_ENODEV ENODEV +#define WD_EINVAL EINVAL +#define WD_ETIMEDOUT ETIMEDOUT +#define WD_ADDR_ERR 61 +#define WD_HW_EACCESS 62 +#define WD_SGL_ERR 63 +#define WD_VERIFY_ERR 64 +#define WD_OUT_EPARA 66 +#define WD_IN_EPARA 67 +#define WD_ENOPROC 68 + +typedef void (*wcrypto_cb)(const void *msg, void *tag); + +typedef void (*wd_log)(const char *format, ...); + +struct wcrypto_cb_tag { + void *ctx; /* user: context or other user relatives */ + void *tag; /* to store user tag */ + int ctx_id; /* user id: context ID or other user identifier */ +}; + +struct wcrypto_paras { + /* + * 0--encipher/compress .etc, 1 ---decipher/decomp .etc + * it not been used for HiSilicon SEC currently. + */ + __u8 direction; + __u8 is_poll; + + /* to be extended */ +}; + +enum wd_buff_type { + WD_FLAT_BUF, + WD_SGL_BUF, +}; + +/* memory APIs for Algorithm Layer */ +typedef void *(*wd_alloc)(void *usr, size_t size); +typedef void (*wd_free)(void *usr, void *va); + + /* memory VA to DMA address map */ +typedef void *(*wd_map)(void *usr, void *va, size_t sz); +typedef void (*wd_unmap)(void *usr, void *va, void *dma, size_t sz); +typedef __u32 (*wd_bufsize)(void *usr); + +/* Memory from user, it is given at ctx creating. */ +struct wd_mm_br { + wd_alloc alloc; /* Memory allocation */ + wd_free free; /* Memory free */ + wd_map iova_map; /* get iova from user space VA */ + + /* destroy the mapping between the PA of VA and iova */ + wd_unmap iova_unmap; + void *usr; /* data for the above operations */ + wd_bufsize get_bufsize; /* optional */ +}; + +/* Warpdrive data buffer */ +struct wd_dtb { + char *data; /* data/buffer start address */ + __u32 dsize; /* data size */ + __u32 bsize; /* buffer size */ +}; + +enum wcrypto_type { + WCRYPTO_RSA, + WCRYPTO_DH, + WCRYPTO_CIPHER, + WCRYPTO_DIGEST, + WCRYPTO_COMP, + WCRYPTO_EC, + WCRYPTO_RNG, + WCRYPTO_ECDH, + WCRYPTO_X25519, + WCRYPTO_X448, + WCRYPTO_ECDSA, + WCRYPTO_SM2, + WCRYPTO_AEAD, + WCRYPTO_MAX_ALG +}; + +#ifndef true +#define true 1 +#endif + +#ifndef false +#define false 0 +#endif + +#ifndef WD_ERR +#ifndef WITH_LOG_FILE +extern wd_log log_out; + +#define __WD_FILENAME__ (strrchr(__FILE__, '/') ? \ + ((char *)((uintptr_t)strrchr(__FILE__, '/') + 1)) : __FILE__) + +#define WD_ERR(format, args...) \ + (log_out ? log_out("[%s, %d, %s]:"format, \ + __WD_FILENAME__, __LINE__, __func__, ##args) : \ + fprintf(stderr, format, ##args)) +#else +extern FILE *flog_fd; +#define WD_ERR(format, args...) do { \ + if (!flog_fd) \ + flog_fd = fopen(WITH_LOG_FILE, "a+"); \ + if (flog_fd) \ + fprintf(flog_fd, format, ##args); \ + else \ + fprintf(stderr, "log %s not exists!", \ + WITH_LOG_FILE); \ +} while (0) +#endif +#endif + +#define WD_CAPA_PRIV_DATA_SIZE 64 + +/* Capabilities */ +struct wd_capa { + /* Algorithm name */ + const char *alg; + /* throughput capability */ + int throughput; + /* latency capability */ + int latency; + /* other capabilities */ + __u32 flags; + + /* For algorithm parameters, now it is defined in extending notions */ + struct wcrypto_paras priv; +}; + +struct wd_queue { + struct wd_capa capa; + /* if denote dev name, get its Q */ + char dev_path[PATH_STR_SIZE]; + /* if denote dev node mask, get its Q */ + unsigned int node_mask; + /* queue private */ + void *qinfo; +}; + +int wd_request_queue(struct wd_queue *q); +void wd_release_queue(struct wd_queue *q); +int wd_send(struct wd_queue *q, void *req); +int wd_recv(struct wd_queue *q, void **resp); +int wd_wait(struct wd_queue *q, __u16 ms); +int wd_recv_sync(struct wd_queue *q, void **resp, __u16 ms); +void *wd_reserve_memory(struct wd_queue *q, size_t size); +int wd_share_reserved_memory(struct wd_queue *q, + struct wd_queue *target_q); +int wd_get_available_dev_num(const char *algorithm); +int wd_get_node_id(struct wd_queue *q); +void *wd_iova_map(struct wd_queue *q, void *va, size_t sz); +void wd_iova_unmap(struct wd_queue *q, void *va, void *dma, size_t sz); +void *wd_dma_to_va(struct wd_queue *q, void *dma); +int wd_register_log(wd_log log); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/uadk/v1/wd_adapter.c b/uadk/v1/wd_adapter.c new file mode 100644 index 0000000..0b7b084 --- /dev/null +++ b/uadk/v1/wd_adapter.c @@ -0,0 +1,289 @@ +/* + * Copyright 2018-2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#include +#include +#include + +#include "config.h" +#include "v1/wd_util.h" +#include "v1/drv/dummy_drv.h" +#include "v1/drv/hisi_qm_udrv.h" +#include "v1/drv/hisi_rng_udrv.h" +#include "v1/wd_adapter.h" + +#define __ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask)) +#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1) + +static struct wd_drv_dio_if hw_dio_tbl[] = { { + .hw_type = "dummy_v1", + .open = dummy_set_queue_dio, + .close = dummy_unset_queue_dio, + .send = dummy_add_to_dio_q, + .recv = dummy_get_from_dio_q, + }, { + .hw_type = "dummy_v2", + .open = dummy_set_queue_dio, + .close = dummy_unset_queue_dio, + .send = dummy_add_to_dio_q, + .recv = dummy_get_from_dio_q, + }, { + .hw_type = HISI_QM_API_VER_BASE WD_UACCE_API_VER_NOIOMMU_SUBFIX, + .open = qm_init_queue, + .close = qm_uninit_queue, + .send = qm_send, + .recv = qm_recv, + .get_sgl_info = qm_get_hwsgl_info, + .init_sgl = qm_init_hwsgl_mem, + .uninit_sgl = qm_uninit_hwsgl_mem, + .sgl_merge = qm_merge_hwsgl, + }, { + .hw_type = HISI_QM_API_VER2_BASE WD_UACCE_API_VER_NOIOMMU_SUBFIX, + .open = qm_init_queue, + .close = qm_uninit_queue, + .send = qm_send, + .recv = qm_recv, + .get_sgl_info = qm_get_hwsgl_info, + .init_sgl = qm_init_hwsgl_mem, + .uninit_sgl = qm_uninit_hwsgl_mem, + .sgl_merge = qm_merge_hwsgl, + }, { + .hw_type = HISI_QM_API_VER3_BASE WD_UACCE_API_VER_NOIOMMU_SUBFIX, + .open = qm_init_queue, + .close = qm_uninit_queue, + .send = qm_send, + .recv = qm_recv, + .get_sgl_info = qm_get_hwsgl_info, + .init_sgl = qm_init_hwsgl_mem, + .uninit_sgl = qm_uninit_hwsgl_mem, + .sgl_merge = qm_merge_hwsgl, + }, { + .hw_type = HISI_QM_API_VER_BASE, + .open = qm_init_queue, + .close = qm_uninit_queue, + .send = qm_send, + .recv = qm_recv, + .get_sgl_info = qm_get_hwsgl_info, + .init_sgl = qm_init_hwsgl_mem, + .uninit_sgl = qm_uninit_hwsgl_mem, + .sgl_merge = qm_merge_hwsgl, + }, { + .hw_type = HISI_QM_API_VER2_BASE, + .open = qm_init_queue, + .close = qm_uninit_queue, + .send = qm_send, + .recv = qm_recv, + .get_sgl_info = qm_get_hwsgl_info, + .init_sgl = qm_init_hwsgl_mem, + .uninit_sgl = qm_uninit_hwsgl_mem, + .sgl_merge = qm_merge_hwsgl, + }, { + .hw_type = HISI_QM_API_VER3_BASE, + .open = qm_init_queue, + .close = qm_uninit_queue, + .send = qm_send, + .recv = qm_recv, + .get_sgl_info = qm_get_hwsgl_info, + .init_sgl = qm_init_hwsgl_mem, + .uninit_sgl = qm_uninit_hwsgl_mem, + .sgl_merge = qm_merge_hwsgl, + }, { + .hw_type = "hisi-trng-v2", + .open = rng_init_queue, + .close = rng_uninit_queue, + .send = rng_send, + .recv = rng_recv, + }, +}; + +#define MAX_HW_TYPE (sizeof(hw_dio_tbl) / sizeof(hw_dio_tbl[0])) + +int drv_open(struct wd_queue *q) +{ + struct q_info *qinfo = q->qinfo; + int i; + + /* try to find another device if the user driver is not available */ + for (i = 0; i < MAX_HW_TYPE; i++) { + if (!strcmp(qinfo->hw_type, + hw_dio_tbl[i].hw_type)) { + qinfo->hw_type_id = i; + return hw_dio_tbl[qinfo->hw_type_id].open(q); + } + } + WD_ERR("No matched driver to use (%s)!\n", qinfo->hw_type); + errno = ENODEV; + return -ENODEV; +} + +void drv_close(struct wd_queue *q) +{ + struct q_info *qinfo = q->qinfo; + + hw_dio_tbl[qinfo->hw_type_id].close(q); +} + +int drv_send(struct wd_queue *q, void **req, __u32 num) +{ + struct q_info *qinfo = q->qinfo; + + return hw_dio_tbl[qinfo->hw_type_id].send(q, req, num); +} + +int drv_recv(struct wd_queue *q, void **req, __u32 num) +{ + struct q_info *qinfo = q->qinfo; + + return hw_dio_tbl[qinfo->hw_type_id].recv(q, req, num); +} + +void drv_free_slice(struct wd_queue *q) +{ + struct q_info *qinfo = q->qinfo; + struct wd_ss_region *rgn; + + while (true) { + rgn = TAILQ_FIRST(&qinfo->ss_list); + if (!rgn) + break; + TAILQ_REMOVE(&qinfo->ss_list, rgn, next); + free(rgn); + } +} + +void drv_add_slice(struct wd_queue *q, struct wd_ss_region *rgn) +{ + struct q_info *qinfo = q->qinfo; + struct wd_ss_region *rg; + + rg = TAILQ_LAST(&qinfo->ss_list, wd_ss_region_list); + if (rg) { + if (rg->pa + rg->size == rgn->pa) { + rg->size += rgn->size; + free(rgn); + return; + } + } + + TAILQ_INSERT_TAIL(&qinfo->ss_list, rgn, next); +} + +void drv_show_ss_slices(struct wd_queue *q) +{ + struct q_info *qinfo = q->qinfo; + struct wd_ss_region *rgn; + int i = 0; + + TAILQ_FOREACH(rgn, qinfo->head, next) { + WD_ERR("slice-%d:size=0x%lx\n", i, rgn->size); + i++; + } +} + +void *drv_reserve_mem(struct wd_queue *q, size_t size) +{ + struct wd_ss_region *rgn = NULL; + struct q_info *qinfo = q->qinfo; + unsigned long info = 0; + size_t tmp = size; + unsigned long i = 0; + void *ptr = NULL; + int ret = 1; + + /* Make sure memory map granularity size align */ + if (!qinfo->iommu_type) + tmp = ALIGN(tmp, WD_UACCE_GRAN_SIZE); + + ptr = wd_drv_mmap_qfr(q, WD_UACCE_QFRT_SS, tmp); + if (ptr == MAP_FAILED) { + int value = errno; + + WD_ERR("wd drv mmap fail!(err =%d)\n", value); + return NULL; + } + + qinfo->ss_va = ptr; + qinfo->ss_size = tmp; + tmp = 0; + while (ret > 0) { + info = (unsigned long)i; + ret = ioctl(qinfo->fd, WD_UACCE_CMD_GET_SS_DMA, &info); + if (ret < 0) { + drv_show_ss_slices(q); + WD_ERR("get DMA fail!\n"); + goto err_out; + } + rgn = malloc(sizeof(*rgn)); + if (!rgn) { + WD_ERR("alloc ss region fail!\n"); + goto err_out; + } + memset(rgn, 0, sizeof(*rgn)); + + if (qinfo->iommu_type) + rgn->size = qinfo->ss_size; + else + rgn->size = (info & WD_UACCE_GRAN_NUM_MASK) << + WD_UACCE_GRAN_SHIFT; + rgn->pa = info & (~WD_UACCE_GRAN_NUM_MASK); + rgn->va = ptr + tmp; + tmp += rgn->size; + drv_add_slice(q, rgn); + i++; + } + + return ptr; + +err_out: + drv_free_slice(q); + drv_unmap_reserve_mem(q, ptr, tmp); + + return NULL; +} + +void drv_unmap_reserve_mem(struct wd_queue *q, void *addr, size_t size) +{ + wd_drv_unmmap_qfr(q, addr, WD_UACCE_QFRT_SS, size); +} + +int drv_get_sgl_info(struct wd_queue *q, struct hw_sgl_info *info) +{ + struct q_info *qinfo = q->qinfo; + + return hw_dio_tbl[qinfo->hw_type_id].get_sgl_info(q, info); +} + +int drv_init_sgl(struct wd_queue *q, void *pool, struct wd_sgl *sgl) +{ + struct q_info *qinfo = q->qinfo; + + return hw_dio_tbl[qinfo->hw_type_id].init_sgl(q, pool, sgl); +} + +int drv_uninit_sgl(struct wd_queue *q, void *pool, struct wd_sgl *sgl) +{ + struct q_info *qinfo = q->qinfo; + + return hw_dio_tbl[qinfo->hw_type_id].uninit_sgl(q, pool, sgl); +} + +int drv_sgl_merge(struct wd_queue *q, void *pool, struct wd_sgl *dst_sgl, + struct wd_sgl *src_sgl) +{ + struct q_info *qinfo = q->qinfo; + + return hw_dio_tbl[qinfo->hw_type_id].sgl_merge(q, pool, dst_sgl, src_sgl); +} diff --git a/uadk/v1/wd_adapter.h b/uadk/v1/wd_adapter.h new file mode 100644 index 0000000..bcceff2 --- /dev/null +++ b/uadk/v1/wd_adapter.h @@ -0,0 +1,75 @@ +/* + * Copyright 2018-2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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 common driver header define the unified interface for wd */ +#ifndef __WD_ADAPTER_H__ +#define __WD_ADAPTER_H__ + +#include +#include +#include +#include +#include + +#include "wd.h" +#include "wd_sgl.h" + +/* Use to describe hardware SGL, different hardware has different SGL format */ +struct hw_sgl_info { + __u32 sgl_sz; + __u32 sgl_align_sz; + __u32 sge_sz; + __u32 sge_align_sz; +}; + +struct wd_drv_dio_if { + /* vendor tag which is used to select right vendor driver */ + char *hw_type; + /* user space WD queue initialize */ + int (*open)(struct wd_queue *q); + /* user space WD queue uninitialize */ + void (*close)(struct wd_queue *q); + /* Send WCRYPTO message to WD queue */ + int (*send)(struct wd_queue *q, void **req, __u32 num); + /* Receive WCRYPTO message from WD queue */ + int (*recv)(struct wd_queue *q, void **req, __u32 num); + + /* Get hardware sgl information from WD queue */ + int (*get_sgl_info)(struct wd_queue *q, struct hw_sgl_info *info); + /* Initialize hardware sgl from WD queue */ + int (*init_sgl)(struct wd_queue *q, void *pool, struct wd_sgl *sgl); + /* Uninitialize hardware sgl from WD queue */ + int (*uninit_sgl)(struct wd_queue *q, void *pool, struct wd_sgl *sgl); + /* Merge two hardware sgls to 'dst_sgl' from WD queue */ + int (*sgl_merge)(struct wd_queue *q, void *pool, + struct wd_sgl *dst_sgl, struct wd_sgl *src_sgl); +}; + +int drv_open(struct wd_queue *q); +void drv_close(struct wd_queue *q); +int drv_send(struct wd_queue *q, void **req, __u32 num); +int drv_recv(struct wd_queue *q, void **req, __u32 num); +void drv_flush(struct wd_queue *q); +void drv_free_slice(struct wd_queue *q); +void *drv_reserve_mem(struct wd_queue *q, size_t size); +void drv_unmap_reserve_mem(struct wd_queue *q, void *addr, size_t size); +int drv_get_sgl_info(struct wd_queue *q, struct hw_sgl_info *info); +int drv_init_sgl(struct wd_queue *q, void *pool, struct wd_sgl *sgl); +int drv_uninit_sgl(struct wd_queue *q, void *pool, struct wd_sgl *sgl); +int drv_sgl_merge(struct wd_queue *q, void *pool, + struct wd_sgl *dst_sgl, struct wd_sgl *src_sgl); + +#endif diff --git a/uadk/v1/wd_aead.c b/uadk/v1/wd_aead.c new file mode 100644 index 0000000..ab1250a --- /dev/null +++ b/uadk/v1/wd_aead.c @@ -0,0 +1,698 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include + +#include +#include + +#include "wd.h" +#include "wd_util.h" +#include "wd_aead.h" + +#define MAX_AEAD_KEY_SIZE 64 +#define MAX_AEAD_MAC_SIZE 64 +#define MAX_CIPHER_KEY_SIZE 64 +#define MAX_AEAD_AUTH_SIZE 64 +#define MAX_AEAD_ASSOC_SIZE 65536 +#define MAX_HMAC_KEY_SIZE 128 +#define MAX_AEAD_RETRY_CNT 20000000 + +#define DES_KEY_SIZE 8 +#define SM4_KEY_SIZE 16 +#define SEC_3DES_2KEY_SIZE (2 * DES_KEY_SIZE) +#define SEC_3DES_3KEY_SIZE (3 * DES_KEY_SIZE) + +#define AES_BLOCK_SIZE 16 +#define GCM_BLOCK_SIZE 12 + +#define MAX_BURST_NUM 16 + +static int g_aead_mac_len[WCRYPTO_MAX_DIGEST_TYPE] = { + WCRYPTO_SM3_LEN, WCRYPTO_MD5_LEN, WCRYPTO_SHA1_LEN, + WCRYPTO_SHA256_LEN, WCRYPTO_SHA224_LEN, + WCRYPTO_SHA384_LEN, WCRYPTO_SHA512_LEN, + WCRYPTO_SHA512_224_LEN, WCRYPTO_SHA512_256_LEN +}; + +struct wcrypto_aead_cookie { + struct wcrypto_aead_tag tag; + struct wcrypto_aead_msg msg; +}; + +struct wcrypto_aead_ctx { + struct wd_cookie_pool pool; + unsigned long ctx_id; + void *ckey; + void *akey; + __u16 ckey_bytes; + __u16 akey_bytes; + __u16 auth_size; + __u16 iv_blk_size; + struct wd_queue *q; + struct wcrypto_aead_ctx_setup setup; +}; + +static void del_ctx_key(struct wcrypto_aead_ctx *ctx) +{ + struct wd_mm_br *br = &(ctx->setup.br); + __u8 tmp[MAX_CIPHER_KEY_SIZE] = { 0 }; + + /** + * When data_fmt is 'WD_SGL_BUF', 'akey' and 'ckey' is a sgl, and if u + * want to clear the SGL buffer, we can only use 'wd_sgl_cp_from_pbuf' + * whose 'pbuf' is all zero. + */ + if (ctx->ckey) { + if (ctx->setup.data_fmt == WD_FLAT_BUF) + memset(ctx->ckey, 0, MAX_CIPHER_KEY_SIZE); + else if (ctx->setup.data_fmt == WD_SGL_BUF) + wd_sgl_cp_from_pbuf(ctx->ckey, 0, tmp, MAX_CIPHER_KEY_SIZE); + } + + if (ctx->akey) { + if (ctx->setup.data_fmt == WD_FLAT_BUF) + memset(ctx->akey, 0, MAX_AEAD_KEY_SIZE); + else if (ctx->setup.data_fmt == WD_SGL_BUF) + wd_sgl_cp_from_pbuf(ctx->akey, 0, tmp, MAX_AEAD_KEY_SIZE); + } + + if (br && br->free) { + if (ctx->ckey) + br->free(br->usr, ctx->ckey); + if (ctx->akey) + br->free(br->usr, ctx->akey); + } +} + +static int get_iv_block_size(int mode) +{ + int ret; + + /* AEAD just used AES and SM4 algorithm */ + switch (mode) { + case WCRYPTO_CIPHER_CBC: + case WCRYPTO_CIPHER_CCM: + ret = AES_BLOCK_SIZE; + break; + case WCRYPTO_CIPHER_GCM: + ret = GCM_BLOCK_SIZE; + break; + default: + ret = 0; + } + + return ret; +} + +static int create_ctx_para_check(struct wd_queue *q, + struct wcrypto_aead_ctx_setup *setup) +{ + if (!q || !setup) { + WD_ERR("input param is NULL\n"); + return -WD_EINVAL; + } + + if (!setup->br.alloc || !setup->br.free || + !setup->br.iova_map || !setup->br.iova_unmap) { + WD_ERR("fail to create cipher ctx user mm br!\n"); + return -WD_EINVAL; + } + if (!q->capa.alg || strcmp(q->capa.alg, "aead")) { + WD_ERR("fail to matching algorithm! %s\n", q->capa.alg); + return -WD_EINVAL; + } + + return WD_SUCCESS; +} + +static void init_aead_cookie(struct wcrypto_aead_ctx *ctx, + struct wcrypto_aead_ctx_setup *setup) +{ + struct wcrypto_aead_cookie *cookie; + int i; + + for (i = 0; i < ctx->pool.cookies_num; i++) { + cookie = (void *)((uintptr_t)ctx->pool.cookies + + i * ctx->pool.cookies_size); + cookie->msg.alg_type = WCRYPTO_AEAD; + cookie->msg.calg = setup->calg; + cookie->msg.cmode = setup->cmode; + cookie->msg.dalg = setup->dalg; + cookie->msg.dmode = setup->dmode; + cookie->msg.data_fmt = setup->data_fmt; + cookie->tag.wcrypto_tag.ctx = ctx; + cookie->tag.wcrypto_tag.ctx_id = ctx->ctx_id; + cookie->msg.usr_data = (uintptr_t)&cookie->tag; + } +} + +static int wcrypto_setup_qinfo(struct wcrypto_aead_ctx_setup *setup, + struct q_info *qinfo, __u32 *ctx_id) +{ + int ret = -WD_EINVAL; + + /* lock at ctx creating/deleting */ + wd_spinlock(&qinfo->qlock); + if (!qinfo->br.alloc && !qinfo->br.iova_map) + memcpy(&qinfo->br, &setup->br, sizeof(qinfo->br)); + + if (qinfo->br.usr != setup->br.usr) { + WD_ERR("Err mm br in creating aead ctx!\n"); + goto unlock; + } + + if (qinfo->ctx_num >= WD_MAX_CTX_NUM) { + WD_ERR("err: create too many aead ctx!\n"); + goto unlock; + } + + ret = wd_alloc_id(qinfo->ctx_id, WD_MAX_CTX_NUM, ctx_id, 0, + WD_MAX_CTX_NUM); + if (ret) { + WD_ERR("fail to alloc ctx id!\n"); + goto unlock; + } + qinfo->ctx_num++; + ret = WD_SUCCESS; + +unlock: + wd_unspinlock(&qinfo->qlock); + return ret; +} + +/* Before initiate this context, we should get a queue from WD */ +void *wcrypto_create_aead_ctx(struct wd_queue *q, + struct wcrypto_aead_ctx_setup *setup) +{ + struct q_info *qinfo; + struct wcrypto_aead_ctx *ctx; + __u32 ctx_id = 0; + int ret; + + if (create_ctx_para_check(q, setup)) + return NULL; + + qinfo = q->qinfo; + /* lock at ctx creating/deleting */ + if (wcrypto_setup_qinfo(setup, qinfo, &ctx_id)) + return NULL; + + ctx = malloc(sizeof(struct wcrypto_aead_ctx)); + if (!ctx) { + WD_ERR("fail to alloc ctx memory!\n"); + goto free_ctx_id; + } + memset(ctx, 0, sizeof(struct wcrypto_aead_ctx)); + memcpy(&ctx->setup, setup, sizeof(ctx->setup)); + ctx->q = q; + ctx->ctx_id = ctx_id + 1; + ctx->ckey = setup->br.alloc(setup->br.usr, MAX_CIPHER_KEY_SIZE); + if (!ctx->ckey) { + WD_ERR("fail to alloc cipher ctx key!\n"); + goto free_ctx; + } + ctx->akey = setup->br.alloc(setup->br.usr, MAX_AEAD_KEY_SIZE); + if (!ctx->akey) { + WD_ERR("fail to alloc authenticate ctx key!\n"); + setup->br.free(setup->br.usr, ctx->ckey); + goto free_ctx_ckey; + } + + ctx->iv_blk_size = get_iv_block_size(setup->cmode); + ret = wd_init_cookie_pool(&ctx->pool, + sizeof(struct wcrypto_aead_cookie), WD_CTX_MSG_NUM); + if (ret) { + WD_ERR("fail to init cookie pool!\n"); + goto free_ctx_akey; + } + init_aead_cookie(ctx, setup); + + return ctx; + +free_ctx_akey: + setup->br.free(setup->br.usr, ctx->akey); +free_ctx_ckey: + setup->br.free(setup->br.usr, ctx->ckey); +free_ctx: + free(ctx); +free_ctx_id: + wd_spinlock(&qinfo->qlock); + qinfo->ctx_num--; + wd_free_id(qinfo->ctx_id, WD_MAX_CTX_NUM, ctx_id, WD_MAX_CTX_NUM); + wd_unspinlock(&qinfo->qlock); + + return NULL; +} + +int wcrypto_aead_setauthsize(void *ctx, __u16 authsize) +{ + struct wcrypto_aead_ctx *ctxt = ctx; + + if (!ctx) { + WD_ERR("input param is NULL!\n"); + return -WD_EINVAL; + } + + if (authsize > MAX_AEAD_AUTH_SIZE) { + WD_ERR("fail to check authsize!\n"); + return -WD_EINVAL; + } + + ctxt->auth_size = authsize; + + return WD_SUCCESS; +} + +int wcrypto_aead_getauthsize(void *ctx) +{ + struct wcrypto_aead_ctx *ctxt = ctx; + + if (!ctx) { + WD_ERR("input param is NULL!\n"); + return -WD_EINVAL; + } + + return ctxt->auth_size; +} + +int wcrypto_aead_get_maxauthsize(void *ctx) +{ + struct wcrypto_aead_ctx *ctxt = ctx; + + if (!ctx) { + WD_ERR("input param is NULL!\n"); + return -WD_EINVAL; + } + + if (ctxt->setup.cmode == WCRYPTO_CIPHER_CCM || + ctxt->setup.cmode == WCRYPTO_CIPHER_GCM) + return WCRYPTO_CCM_GCM_LEN; + + if (ctxt->setup.dalg >= WCRYPTO_MAX_DIGEST_TYPE) { + WD_ERR("fail to check authenticate alg!\n"); + return -WD_EINVAL; + } + + return g_aead_mac_len[ctxt->setup.dalg]; +} + +static int aes_key_len_check(__u16 ckey_len) +{ + switch (ckey_len) { + case AES_KEYSIZE_128: + case AES_KEYSIZE_192: + case AES_KEYSIZE_256: + return WD_SUCCESS; + default: + return -WD_EINVAL; + } +} + +static int cipher_key_len_check(int alg, __u16 ckey_len) +{ + int ret = WD_SUCCESS; + + switch (alg) { + case WCRYPTO_CIPHER_SM4: + if (ckey_len != SM4_KEY_SIZE) + ret = -WD_EINVAL; + break; + case WCRYPTO_CIPHER_AES: + ret = aes_key_len_check(ckey_len); + break; + default: + return -WD_EINVAL; + } + + return ret; +} + +int wcrypto_set_aead_ckey(void *ctx, __u8 *key, __u16 key_len) +{ + struct wcrypto_aead_ctx *ctxt = ctx; + int ret; + + if (!ctx || !key) { + WD_ERR("input param is NULL!\n"); + return -WD_EINVAL; + } + + ret = cipher_key_len_check(ctxt->setup.calg, key_len); + if (ret != WD_SUCCESS) { + WD_ERR("fail to check key length, alg = %u\n", ctxt->setup.calg); + return ret; + } + + ctxt->ckey_bytes = key_len; + + if (ctxt->setup.data_fmt == WD_SGL_BUF) + wd_sgl_cp_from_pbuf(ctxt->ckey, 0, key, key_len); + else + memcpy(ctxt->ckey, key, key_len); + + return ret; +} + +int wcrypto_set_aead_akey(void *ctx, __u8 *key, __u16 key_len) +{ + struct wcrypto_aead_ctx *ctxt = ctx; + + if (!ctx || !key) { + WD_ERR("input param is NULL!\n"); + return -WD_EINVAL; + } + + if (key_len == 0) + goto err_key_len; + + if (ctxt->setup.dalg > WCRYPTO_SHA256) { + if (key_len > MAX_HMAC_KEY_SIZE) + goto err_key_len; + } else { + if (key_len > MAX_HMAC_KEY_SIZE >> 1) + goto err_key_len; + } + + ctxt->akey_bytes = key_len; + + if (ctxt->setup.data_fmt == WD_SGL_BUF) + wd_sgl_cp_from_pbuf(ctxt->akey, 0, key, key_len); + else + memcpy(ctxt->akey, key, key_len); + + return WD_SUCCESS; + +err_key_len: + WD_ERR("fail to check key length!\n"); + return -WD_EINVAL; +} + +static void aead_requests_uninit(struct wcrypto_aead_msg **req, + struct wcrypto_aead_ctx *ctx, __u32 num) +{ + int i; + + for (i = 0; i < num; i++) { + if (req[i]->aiv) + ctx->setup.br.free(ctx->setup.br.usr, req[i]->aiv); + } +} + +static int check_op_data(struct wcrypto_aead_op_data **op, + struct wcrypto_aead_ctx *ctx, __u32 idx) +{ + if (unlikely(op[idx]->op_type == WCRYPTO_CIPHER_ENCRYPTION_DIGEST && + op[idx]->out_buf_bytes < op[idx]->out_bytes + ctx->auth_size)) { + WD_ERR("fail to check out buffer length %u!\n", idx); + return -WD_EINVAL; + } + + if (unlikely(op[idx]->iv_bytes != ctx->iv_blk_size || + op[idx]->iv_bytes == 0)) { + WD_ERR("fail to check IV length %u!\n", idx); + return -WD_EINVAL; + } + + if (unlikely(op[idx]->in_bytes == 0 || + (op[idx]->in_bytes & (AES_BLOCK_SIZE - 1)))) { + if (ctx->setup.cmode == WCRYPTO_CIPHER_CBC) { + WD_ERR("failed to check aead input data length!\n"); + return -WD_EINVAL; + } + } + + return 0; +} + +static int aead_requests_init(struct wcrypto_aead_msg **req, + struct wcrypto_aead_op_data **op, + struct wcrypto_aead_ctx *ctx, __u32 num) +{ + struct wd_sec_udata *udata; + int ret; + __u32 i; + + for (i = 0; i < num; i++) { + ret = check_op_data(op, ctx, i); + if (ret) + goto err_uninit_requests; + + req[i]->calg = ctx->setup.calg; + req[i]->cmode = ctx->setup.cmode; + req[i]->dalg = ctx->setup.dalg; + req[i]->dmode = ctx->setup.dmode; + req[i]->ckey = ctx->ckey; + req[i]->ckey_bytes = ctx->ckey_bytes; + req[i]->akey = ctx->akey; + req[i]->akey_bytes = ctx->akey_bytes; + req[i]->op_type = op[i]->op_type; + req[i]->iv = op[i]->iv; + req[i]->iv_bytes = op[i]->iv_bytes; + req[i]->in = op[i]->in; + req[i]->in_bytes = op[i]->in_bytes; + req[i]->out = op[i]->out; + req[i]->out_bytes = op[i]->out_bytes; + req[i]->assoc_bytes = op[i]->assoc_size; + req[i]->auth_bytes = ctx->auth_size; + udata = op[i]->priv; + if (udata && udata->key) { + req[i]->ckey = udata->key; + req[i]->ckey_bytes = udata->key_bytes; + } + + req[i]->aiv = ctx->setup.br.alloc(ctx->setup.br.usr, + MAX_AEAD_KEY_SIZE); + if (unlikely(!req[i]->aiv)) { + WD_ERR("fail to alloc auth iv memory %u!\n", i); + ret = -WD_ENOMEM; + goto err_uninit_requests; + } + } + + return WD_SUCCESS; + +err_uninit_requests: + aead_requests_uninit(req, ctx, i); + return ret; +} + +static int aead_recv_sync(struct wcrypto_aead_ctx *a_ctx, + struct wcrypto_aead_op_data **a_opdata, __u32 num) +{ + struct wcrypto_aead_msg *resp[WCRYPTO_MAX_BURST_NUM]; + __u32 recv_count = 0; + __u64 rx_cnt = 0; + __u32 i; + int ret; + + for (i = 0; i < num; i++) + resp[i] = (void *)(uintptr_t)a_ctx->ctx_id; + + while (true) { + ret = wd_burst_recv(a_ctx->q, (void **)(resp + recv_count), + num - recv_count); + if (ret > 0) { + recv_count += ret; + if (recv_count == num) + break; + + rx_cnt = 0; + } else if (ret == 0) { + if (++rx_cnt > MAX_AEAD_RETRY_CNT) { + WD_ERR("%s:wcrypto_recv timeout, num = %u, recv_count = %u!\n", + __func__, num, recv_count); + break; + } + } else { + WD_ERR("do aead wcrypto_recv error!\n"); + return ret; + } + } + + for (i = 0; i < recv_count; i++) { + a_opdata[i]->out = (void *)resp[i]->out; + a_opdata[i]->out_bytes = resp[i]->out_bytes; + a_opdata[i]->status = resp[i]->result; + } + + return recv_count; +} + +static int param_check(struct wcrypto_aead_ctx *a_ctx, + struct wcrypto_aead_op_data **a_opdata, + void **tag, __u32 num) +{ + __u32 i; + + if (unlikely(!a_ctx || !a_opdata || !num || num > WCRYPTO_MAX_BURST_NUM)) { + WD_ERR("input param err!\n"); + return -WD_EINVAL; + } + + for (i = 0; i < num; i++) { + if (unlikely(!a_opdata[i])) { + WD_ERR("aead opdata[%u] is NULL!\n", i); + return -WD_EINVAL; + } + + if (unlikely(tag && !tag[i])) { + WD_ERR("tag[%u] is NULL!\n", i); + return -WD_EINVAL; + } + } + + if (unlikely(tag && !a_ctx->setup.cb)) { + WD_ERR("aead ctx call back is NULL!\n"); + return -WD_EINVAL; + } + + return WD_SUCCESS; +} + +int wcrypto_burst_aead(void *a_ctx, struct wcrypto_aead_op_data **opdata, + void **tag, __u32 num) +{ + struct wcrypto_aead_cookie *cookies[WCRYPTO_MAX_BURST_NUM] = { NULL }; + struct wcrypto_aead_msg *req[WCRYPTO_MAX_BURST_NUM]; + struct wcrypto_aead_ctx *ctxt = a_ctx; + __u32 i; + int ret; + + if (param_check(ctxt, opdata, tag, num)) + return -WD_EINVAL; + + ret = wd_get_cookies(&ctxt->pool, (void **)cookies, num); + if (unlikely(ret)) { + WD_ERR("failed to get cookies %d!\n", ret); + return ret; + } + + for (i = 0; i < num; i++) { + cookies[i]->tag.priv = opdata[i]->priv; + req[i] = &cookies[i]->msg; + if (tag) + cookies[i]->tag.wcrypto_tag.tag = tag[i]; + } + + ret = aead_requests_init(req, opdata, ctxt, num); + if (unlikely(ret)) + goto fail_with_cookies; + + ret = wd_burst_send(ctxt->q, (void **)req, num); + if (unlikely(ret)) { + WD_ERR("failed to send req %d!\n", ret); + goto fail_with_send; + } + + if (tag) + return ret; + + ret = aead_recv_sync(ctxt, opdata, num); + +fail_with_send: + aead_requests_uninit(req, ctxt, num); +fail_with_cookies: + wd_put_cookies(&ctxt->pool, (void **)cookies, num); + return ret; +} + +int wcrypto_do_aead(void *ctx, struct wcrypto_aead_op_data *opdata, void *tag) +{ + int ret; + + if (!tag) { + ret = wcrypto_burst_aead(ctx, &opdata, NULL, 1); + if (likely(ret == 1)) + return GET_NEGATIVE(opdata->status); + if (unlikely(ret == 0)) + return -WD_ETIMEDOUT; + } else { + ret = wcrypto_burst_aead(ctx, &opdata, &tag, 1); + } + + return ret; +} + +int wcrypto_aead_poll(struct wd_queue *q, unsigned int num) +{ + struct wcrypto_aead_msg *aead_resp = NULL; + struct wcrypto_aead_ctx *ctx; + struct wcrypto_aead_tag *tag; + unsigned int tmp = num; + int count = 0; + int ret; + + if (unlikely(!q)) { + WD_ERR("queue is NULL!\n"); + return -WD_EINVAL; + } + + do { + aead_resp = NULL; + ret = wd_recv(q, (void **)&aead_resp); + if (ret == 0) + break; + else if (ret == -WD_HW_EACCESS) { + if (!aead_resp) { + WD_ERR("the aead recv err from req_cache!\n"); + return ret; + } + aead_resp->result = WD_HW_EACCESS; + } else if (ret < 0) { + WD_ERR("recv err at aead poll!\n"); + return ret; + } + count++; + tag = (void *)(uintptr_t)aead_resp->usr_data; + ctx = tag->wcrypto_tag.ctx; + ctx->setup.cb(aead_resp, tag->wcrypto_tag.tag); + aead_requests_uninit(&aead_resp, ctx, 1); + wd_put_cookies(&ctx->pool, (void **)&tag, 1); + } while (--tmp); + + return count; +} + +void wcrypto_del_aead_ctx(void *ctx) +{ + struct wcrypto_aead_ctx *ctxt; + struct q_info *qinfo; + + if (!ctx) { + WD_ERR("Delete aead ctx is NULL!\n"); + return; + } + ctxt = ctx; + qinfo = ctxt->q->qinfo; + wd_uninit_cookie_pool(&ctxt->pool); + wd_spinlock(&qinfo->qlock); + if (qinfo->ctx_num <= 0) { + wd_unspinlock(&qinfo->qlock); + WD_ERR("fail to delete aead ctx!\n"); + return; + } + wd_free_id(qinfo->ctx_id, WD_MAX_CTX_NUM, ctxt->ctx_id - 1, + WD_MAX_CTX_NUM); + if (!(--qinfo->ctx_num)) + memset(&qinfo->br, 0, sizeof(qinfo->br)); + wd_unspinlock(&qinfo->qlock); + del_ctx_key(ctxt); + free(ctx); +} diff --git a/uadk/v1/wd_aead.h b/uadk/v1/wd_aead.h new file mode 100644 index 0000000..ae5697b --- /dev/null +++ b/uadk/v1/wd_aead.h @@ -0,0 +1,213 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#ifndef __WD_AEAD_H +#define __WD_AEAD_H + +#include +#include +#include +#include "wd.h" +#include "wd_cipher.h" +#include "wd_digest.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum wcrypto_aead_op_type { + WCRYPTO_CIPHER_ENCRYPTION_DIGEST, + WCRYPTO_CIPHER_DECRYPTION_DIGEST, + WCRYPTO_DIGEST_CIPHER_ENCRYPTION, + WCRYPTO_DIGEST_CIPHER_DECRYPTION, +}; + +enum wcrypto_aead_mac_len { + WCRYPTO_CCM_GCM_LEN = 16, + WCRYPTO_SM3_LEN = 32, + WCRYPTO_MD5_LEN = 16, + WCRYPTO_SHA1_LEN = 20, + WCRYPTO_SHA256_LEN = 32, + WCRYPTO_SHA224_LEN = 28, + WCRYPTO_SHA384_LEN = 48, + WCRYPTO_SHA512_LEN = 64, + WCRYPTO_SHA512_224_LEN = 28, + WCRYPTO_SHA512_256_LEN = 32 +}; + +/** + * different contexts for different users/threads + * @cb: call back functions of user + * @calg: cipher algorithm type; denoted by enum wcrypto_cipher_alg + * @cmode: cipher algorithm mode; denoted by enum wcrypto_cipher_mode + * @dalg: digest algorithm type; denoted by enum wcrypto_digest_alg + * @dmode: digest algorithm mode; denoted by enum wcrypto_digest_mode + * @br: memory from user, it is given at ctx creating + * @data_fmt: denoted by enum wcrypto_buff_type + */ +struct wcrypto_aead_ctx_setup { + wcrypto_cb cb; + enum wcrypto_cipher_alg calg; + enum wcrypto_cipher_mode cmode; + enum wcrypto_digest_alg dalg; + enum wcrypto_digest_mode dmode; + struct wd_mm_br br; + __u16 data_fmt; +}; + +/** + * operational data per I/O operation + * AEAD encryption input: assoc data || plaintext + * AEAD encryption output: assoc data || ciphertext || auth tag + * AEAD decryption input: assoc data || ciphertext || auth tag + * AEAD decryption output: assoc data || plaintext + * @op_type:aead operation type, denoted by enum wcrypto_aead_op_type + * @status:I/O operation return status + * @in: input data address + * @out:output data address + * @iv:initialization verctor data address + * @in_bytes: input data size + * @out_bytes:output data size + * @out_buf_bytes:output buffer size + * @iv_bytes:initialization verctor data size + * @assoc_size: aead associated data size + * @priv:reserved data field segment + */ +struct wcrypto_aead_op_data { + enum wcrypto_aead_op_type op_type; + int status; + void *in; + void *out; + void *iv; + __u32 in_bytes; + __u32 out_bytes; + __u32 out_buf_bytes; + __u16 iv_bytes; + __u16 assoc_size; + void *priv; +}; + +/* AEAD message format of Warpdrive */ +struct wcrypto_aead_msg { + __u8 alg_type:4; /* Denoted by enum wcrypto_type */ + __u8 op_type:4; /* Denoted by enum wcrypto_aead_op_type */ + __u8 calg:4; /* Denoted by enum wcrypto_cipher_type */ + __u8 cmode:4; /* Denoted by enum wcrypto_cipher_mode */ + __u8 dalg:4; /* Denoted by enum wcrypto_digest_type */ + __u8 dmode:4; /* Denoted by enum wcrypto_digest_mode */ + __u8 data_fmt; /* Data format, denoted by enum wcrypto_buff_type */ + __u8 result; /* Operation result, denoted by WD error code */ + + __u16 ckey_bytes; /* Key bytes */ + __u16 akey_bytes; /* Key bytes */ + __u16 assoc_bytes; /* Input associated data bytes */ + __u16 auth_bytes; /* Output authentication bytes */ + __u16 iv_bytes; /* IV bytes */ + __u32 in_bytes; /* Input data bytes */ + __u32 out_bytes; /* Output data bytes */ + + __u8 *ckey; /* Input key VA pointer, should be DMA buffer */ + __u8 *akey; /* Input authenticate key VA pointer, should be DMA buffer */ + __u8 *iv; /* Input IV VA pointer, should be DMA buffer */ + __u8 *aiv; /* Input auth IV VA pointer, should be DMA buffer */ + __u8 *in; /* Input data VA pointer, should be DMA buffer */ + __u8 *out; /* Output data VA pointer, should be DMA buffer */ + __u64 usr_data; /* user identifier: struct wcrypto_cb_tag */ +}; + +/** + * wcrypto_create_aead_ctx() - create a aead context on the wrapdrive queue. + * @q: wrapdrive queue, need requested by user. + * @setup:setup data of user + */ +void *wcrypto_create_aead_ctx(struct wd_queue *q, + struct wcrypto_aead_ctx_setup *setup); + +/** + * wcrypto_set_aead_ckey() - set cipher key to aead context. + * @ctx: aead context, created by wcrypto_create_aead_ctx. + * @key: cipher key addr + * @key_len: cipher key length + */ +int wcrypto_set_aead_ckey(void *ctx, __u8 *key, __u16 key_len); + +/** + * wcrypto_set_aead_akey() - set authenticate key to aead context. + * @ctx: aead context, created by wcrypto_create_aead_ctx. + * @key: authenticate key addr + * @key_len: authenticate key length + */ +int wcrypto_set_aead_akey(void *ctx, __u8 *key, __u16 key_len); + +/** + * wcrypto_aead_setauthsize() - set aead authsize to aead context. + * @ctx: aead context, created by wcrypto_create_aead_ctx. + * @authsize: aead authsize + */ +int wcrypto_aead_setauthsize(void *ctx, __u16 authsize); + +/** + * wcrypto_aead_getauthsize() - obtain maximum authentication data size + * @ctx: aead context, created by wcrypto_create_aead_ctx. + * Return: authentication data size / tag size in bytes + */ +int wcrypto_aead_getauthsize(void *ctx); + +/** + * wcrypto_aead_getmaxauthsize() - obtain maximum authentication data size + * @ctx: aead context, created by wcrypto_create_aead_ctx. + * Return: max authentication data size + */ +int wcrypto_aead_get_maxauthsize(void *ctx); + +/** + * wcrypto_do_aead() - syn/asynchronous aead operation + * @ctx: context of user, created by wcrypto_create_aead_ctx. + * @opdata: operational data + * @tag: asynchronous:user_tag; synchronous:NULL. + */ +int wcrypto_do_aead(void *ctx, struct wcrypto_aead_op_data *opdata, + void *tag); + +/** + * wcrypto_burst_aead() - (a)synchronous multiple aead operations + * @a_ctx: context of user, created by wcrypto_create_aead_ctx. + * @opdata: operational data + * @tag: asynchronous:user_tag; synchronous:NULL. + * @num: operations number per calling, maximum number is WCRYPTO_MAX_BURST_NUM. + */ +int wcrypto_burst_aead(void *a_ctx, struct wcrypto_aead_op_data **opdata, + void **tag, __u32 num); + +/** + * wcrypto_aead_poll() - poll operation for asynchronous operation + * @q:wrapdrive queue + * @num:how many respondences this poll has to get, 0 means get all finishings + */ +int wcrypto_aead_poll(struct wd_queue *q, unsigned int num); + +/** + * wcrypto_del_aead_ctx() - free aead context + * @ctx: the context to be free + */ +void wcrypto_del_aead_ctx(void *ctx); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/uadk/v1/wd_bmm.c b/uadk/v1/wd_bmm.c new file mode 100644 index 0000000..8f41997 --- /dev/null +++ b/uadk/v1/wd_bmm.c @@ -0,0 +1,425 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +/* Block Memory Management (lib): A block memory algorithm */ +#include +#include +#include +#include +#include +#include +#include + +#include "wd_util.h" +#include "wd_bmm.h" + +#define __ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask)) +#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1) + +#define TAG_FREE 0x12345678 /* block is free */ +#define TAG_USED 0x87654321 /* block is busy */ + +struct wd_blk_hd { + unsigned int blk_tag; + void *blk_dma; + void *blk; + + TAILQ_ENTRY(wd_blk_hd) next; +}; + +TAILQ_HEAD(wd_blk_list, wd_blk_hd); +struct wd_blkpool { + struct wd_lock pool_lock; + unsigned int free_blk_num; + unsigned int alloc_failures; + struct wd_queue *q; + struct wd_blk_list head; + void *usr_mem_start; + void *act_start; + unsigned int act_hd_sz; + unsigned int act_blk_sz; + unsigned long act_mem_sz; + struct wd_blkpool_setup setup; +}; + +static struct wd_blk_hd *wd_blk_head(struct wd_blkpool *pool, void *blk) +{ + unsigned long offset = (unsigned long)((uintptr_t)blk - + (uintptr_t)pool->act_start); + unsigned long sz = pool->act_hd_sz + pool->act_blk_sz; + unsigned long blk_idx = offset / sz; + + return (struct wd_blk_hd *)((uintptr_t)pool->act_start + blk_idx * sz); +} + +static int pool_params_check(struct wd_blkpool_setup *setup) +{ +#define MAX_ALIGN_SIZE 0x1000 /* 4KB */ +#define MAX_BLOCK_SIZE 0x10000000 /* 256MB */ + + if (!setup->block_num || !setup->block_size || + setup->block_size > MAX_BLOCK_SIZE) { + WD_ERR("Invalid block_size or block_num(%x, %u)!\n", + setup->block_size, setup->block_num); + return -WD_EINVAL; + } + + /* check parameters, and align_size must be 2^N */ + if (setup->align_size == 0x1 || setup->align_size > MAX_ALIGN_SIZE || + setup->align_size & (setup->align_size - 0x1)) { + WD_ERR("Invalid align_size.\n"); + return -WD_EINVAL; + } + + return WD_SUCCESS; +} + +static int wd_pool_pre_layout(struct wd_queue *q, + struct wd_blkpool *p, + struct wd_blkpool_setup *sp) +{ + struct q_info *qinfo = NULL; + unsigned int asz; + int ret; + + if (!sp->br.alloc && !q) { + WD_ERR("q is NULL!\n"); + return -WD_EINVAL; + } + + if (!sp->br.alloc) + qinfo = q->qinfo; + +#define BLK_BALANCE_SZ 0x100000ul + ret = pool_params_check(sp); + if (ret) + return ret; + + asz = sp->align_size; + + /* Get actual value by align */ + p->act_hd_sz = ALIGN(sizeof(struct wd_blk_hd), asz); + p->act_blk_sz = ALIGN(sp->block_size, asz); + p->act_mem_sz = (p->act_hd_sz + p->act_blk_sz) * + (unsigned long)sp->block_num + asz; + + /* When we use WD reserve memory and the blk_sz is larger than 1M, + * in order to ensure the mem_pool to be success, + * we should to reserve more memory + */ + if (!sp->br.alloc && !qinfo->iommu_type) + p->act_mem_sz *= (1 + p->act_blk_sz / BLK_BALANCE_SZ); + + return WD_SUCCESS; +} + +static int wd_pool_init(struct wd_queue *q, struct wd_blkpool *p) +{ + __u32 blk_size = p->setup.block_size; + void *dma_start, *dma_end, *va; + struct wd_blk_hd *hd = NULL; + unsigned int dma_num = 0; + unsigned int i, act_num; + + p->act_start = (void *)ALIGN((uintptr_t)p->usr_mem_start, + p->setup.align_size); + + act_num = p->act_mem_sz / (p->act_hd_sz + p->act_blk_sz); + + /* get dma address and initialize blocks */ + for (i = 0; i < act_num; i++) { + va = (void *)((uintptr_t)p->act_start + p->act_hd_sz + + (unsigned long)(p->act_hd_sz + + p->act_blk_sz) * i); + dma_start = wd_iova_map(q, va, 0); + dma_end = wd_iova_map(q, va + blk_size - 1, 0); + if (!dma_start || !dma_end) { + WD_ERR("wd_iova_map err.\n"); + return -WD_ENOMEM; + } + + if ((uintptr_t)dma_end - (uintptr_t)dma_start != blk_size - 1) + continue; + + hd = (void *)((uintptr_t)va - p->act_hd_sz); + hd->blk_dma = dma_start; + hd->blk = va; + hd->blk_tag = TAG_FREE; + TAILQ_INSERT_TAIL(&p->head, hd, next); + + dma_num++; + + /* Never exceed user's request */ + if (dma_num == p->setup.block_num) + break; + } + + /* + * if dma_num <= (1 / 1.15) * user's block_num, we think the pool + * is created with failure. + */ +#define NUM_TIMES(x) (87 * (x) / 100) + if (dma_num <= NUM_TIMES(p->setup.block_num)) { + WD_ERR("dma_num = %u, not enough.\n", dma_num); + return -WD_EINVAL; + } + + p->free_blk_num = dma_num; + p->setup.block_num = dma_num; + + return WD_SUCCESS; +} + +static int usr_pool_init(struct wd_blkpool *p) +{ + struct wd_blkpool_setup *sp = &p->setup; + __u32 blk_size = sp->block_size; + struct wd_blk_hd *hd = NULL; + int i; + + p->act_start = (void *)ALIGN((uintptr_t)p->usr_mem_start, + sp->align_size); + for (i = 0; i < sp->block_num; i++) { + hd = p->act_start + (p->act_hd_sz + p->act_blk_sz) * i; + hd->blk = (void *)((uintptr_t)hd + p->act_hd_sz); + hd->blk_dma = sp->br.iova_map(sp->br.usr, hd->blk, blk_size); + if (!hd->blk_dma) { + WD_ERR("failed to map usr blk.\n"); + return -WD_ENOMEM; + } + hd->blk_tag = TAG_FREE; + TAILQ_INSERT_TAIL(&p->head, hd, next); + } + + p->free_blk_num = sp->block_num; + + return WD_SUCCESS; +} + +static void *pool_init(struct wd_queue *q, struct wd_blkpool *pool, + struct wd_blkpool_setup *setup) +{ + void *addr = NULL; + + /* use user's memory, and its br alloc function */ + if (setup->br.alloc && setup->br.free) { + addr = setup->br.alloc(setup->br.usr, pool->act_mem_sz); + if (!addr) { + WD_ERR("failed to allocate memory in user pool.\n"); + return NULL; + } + + pool->usr_mem_start = addr; + if (usr_pool_init(pool)) { + WD_ERR("failed to initialize user pool.\n"); + setup->br.free(setup->br.usr, addr); + return NULL; + } + } else { + /* use wd to reserve memory */ + addr = wd_reserve_memory(q, pool->act_mem_sz); + if (!addr) { + WD_ERR("wd pool failed to reserve memory.\n"); + return NULL; + } + + pool->usr_mem_start = addr; + if (wd_pool_init(q, pool)) { + WD_ERR("failed to initialize wd pool.\n"); + + /* release q will free memory */ + return NULL; + } + setup->block_num = pool->setup.block_num; + pool->q = q; + } + + return pool; +} + +void *wd_blkpool_create(struct wd_queue *q, struct wd_blkpool_setup *setup) +{ + struct wd_blkpool *pool; + int ret; + + if (!setup) { + WD_ERR("setup is NULL!\n"); + return NULL; + } + + pool = calloc(1, sizeof(*pool)); + if (!pool) { + WD_ERR("failed to malloc pool.\n"); + return NULL; + } + memcpy(&pool->setup, setup, sizeof(pool->setup)); + + ret = wd_pool_pre_layout(q, pool, setup); + if (ret) + goto err_pool_alloc; + + TAILQ_INIT(&pool->head); + + if (!pool_init(q, pool, setup)) + goto err_pool_alloc; + + return pool; + +err_pool_alloc: + free(pool); + + return NULL; +} + +void wd_blkpool_destroy(void *pool) +{ + struct wd_blkpool_setup *setup; + struct wd_blkpool *p = pool; + + if (!p) { + WD_ERR("pool destroy err, pool is NULL.\n"); + return; + } + + setup = &p->setup; + if (p->free_blk_num != setup->block_num) { + WD_ERR("Can not destroy blk pool, as it's in use.\n"); + return; + } + + if (setup->br.free) + setup->br.free(setup->br.usr, p->usr_mem_start); + + free(p); +} + +void *wd_alloc_blk(void *pool) +{ + struct wd_blkpool *p = pool; + struct wd_blk_hd *hd; + + if (unlikely(!p)) { + WD_ERR("blk alloc pool is null!\n"); + return NULL; + } + + wd_spinlock(&p->pool_lock); + + hd = TAILQ_LAST(&p->head, wd_blk_list); + if (unlikely(!hd || hd->blk_tag != TAG_FREE)) { + p->alloc_failures++; + wd_unspinlock(&p->pool_lock); + WD_ERR("Failed to malloc blk.\n"); + + return NULL; + } + + /* Delete the block buffer from free list */ + TAILQ_REMOVE(&p->head, hd, next); + p->free_blk_num--; + hd->blk_tag = TAG_USED; + wd_unspinlock(&p->pool_lock); + + return hd->blk; +} + +void wd_free_blk(void *pool, void *blk) +{ + struct wd_blkpool *p = pool; + struct wd_blk_hd *hd; + + if (unlikely(!p || !blk)) { + WD_ERR("free blk parameters err!\n"); + return; + } + + hd = wd_blk_head(p, blk); + if (unlikely(hd->blk_tag != TAG_USED)) { + WD_ERR("free block fail!\n"); + return; + } + + wd_spinlock(&p->pool_lock); + TAILQ_INSERT_TAIL(&p->head, hd, next); + p->free_blk_num++; + hd->blk_tag = TAG_FREE; + wd_unspinlock(&p->pool_lock); +} + +void *wd_blk_iova_map(void *pool, void *blk) +{ + struct wd_blk_hd *hd; + + if (unlikely(!pool || !blk)) { + WD_ERR("blk map err, pool is NULL!\n"); + return NULL; + } + + hd = wd_blk_head(pool, blk); + if (unlikely(hd->blk_tag != TAG_USED || + (uintptr_t)blk < (uintptr_t)hd->blk)) { + WD_ERR("dma map fail!\n"); + return NULL; + } + + return (void *)((uintptr_t)hd->blk_dma + ((uintptr_t)blk - + (uintptr_t)hd->blk)); +} + +void wd_blk_iova_unmap(void *pool, void *blk_dma, void *blk) +{ + /* do nothing at no-iommu mode */ +} + +int wd_get_free_blk_num(void *pool, __u32 *free_num) +{ + struct wd_blkpool *p = pool; + + if (!p || !free_num) { + WD_ERR("get_free_blk_num err, parameter err!\n"); + return -WD_EINVAL; + } + + *free_num = __atomic_load_n(&p->free_blk_num, __ATOMIC_RELAXED); + + return WD_SUCCESS; +} + +int wd_blk_alloc_failures(void *pool, __u32 *fail_num) +{ + struct wd_blkpool *p = pool; + + if (!p || !fail_num) { + WD_ERR("get_blk_alloc_failure err, pool is NULL!\n"); + return -WD_EINVAL; + } + + *fail_num = __atomic_load_n(&p->alloc_failures, __ATOMIC_RELAXED); + + return WD_SUCCESS; +} + +__u32 wd_blksize(void *pool) +{ + struct wd_blkpool *p = pool; + + if (!p) { + WD_ERR("get blk_size pool is null!\n"); + return 0; + } + + return p->act_blk_sz; +} diff --git a/uadk/v1/wd_bmm.h b/uadk/v1/wd_bmm.h new file mode 100644 index 0000000..88a8f9d --- /dev/null +++ b/uadk/v1/wd_bmm.h @@ -0,0 +1,50 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#ifndef _WD_BMM_H +#define _WD_BMM_H + +#include +#include "wd.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Memory pool creating parameters */ +struct wd_blkpool_setup { + __u32 block_size; /* Block buffer size */ + __u32 block_num; /* Block buffer number */ + __u32 align_size; /* Block buffer starting address align size */ + struct wd_mm_br br; /* memory from user if don't use WD memory */ +}; + +void *wd_blkpool_create(struct wd_queue *q, + struct wd_blkpool_setup *setup); +void wd_blkpool_destroy(void *pool); +void *wd_alloc_blk(void *pool); +void wd_free_blk(void *pool, void *blk); +int wd_get_free_blk_num(void *pool, __u32 *free_num); +int wd_blk_alloc_failures(void *pool, __u32 *fail_num); +void *wd_blk_iova_map(void *pool, void *blk); +void wd_blk_iova_unmap(void *pool, void *blk_dma, void *blk); +__u32 wd_blksize(void *pool); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/uadk/v1/wd_cipher.c b/uadk/v1/wd_cipher.c new file mode 100644 index 0000000..ad21a3a --- /dev/null +++ b/uadk/v1/wd_cipher.c @@ -0,0 +1,567 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include + +#include +#include + +#include "v1/wd.h" +#include "v1/wd_util.h" +#include "v1/wd_cipher.h" + +#define MAX_CIPHER_KEY_SIZE 64 +#define MAX_CIPHER_RETRY_CNT 20000000 + +#define DES_KEY_SIZE 8 +#define SM4_KEY_SIZE 16 +#define SEC_3DES_2KEY_SIZE (2 * DES_KEY_SIZE) +#define SEC_3DES_3KEY_SIZE (3 * DES_KEY_SIZE) + +#define CBC_3DES_BLOCK_SIZE 8 +#define CBC_AES_BLOCK_SIZE 16 +#define DES_WEAK_KEY_NUM 4 +static __u64 des_weak_key[DES_WEAK_KEY_NUM] = {0x0101010101010101, 0xFEFEFEFEFEFEFEFE, + 0xE0E0E0E0F1F1F1F1, 0x1F1F1F1F0E0E0E0E}; + +struct wcrypto_cipher_cookie { + struct wcrypto_cipher_tag tag; + struct wcrypto_cipher_msg msg; +}; + +struct wcrypto_cipher_ctx { + struct wd_cookie_pool pool; + unsigned long ctx_id; + void *key; + __u32 key_bytes; + __u32 iv_blk_size; + struct wd_queue *q; + struct wcrypto_cipher_ctx_setup setup; +}; + +static void del_ctx_key(struct wcrypto_cipher_ctx *ctx) +{ + struct wd_mm_br *br = &(ctx->setup.br); + __u8 tmp[MAX_CIPHER_KEY_SIZE] = { 0 }; + + /** + * When data_fmt is 'WD_SGL_BUF', 'akey' and 'ckey' is a sgl, and if u + * want to clear the SGL buffer, we can only use 'wd_sgl_cp_from_pbuf' + * whose 'pbuf' is all zero. + */ + if (ctx->key) { + if (ctx->setup.data_fmt == WD_FLAT_BUF) + memset(ctx->key, 0, MAX_CIPHER_KEY_SIZE); + else if (ctx->setup.data_fmt == WD_SGL_BUF) + wd_sgl_cp_from_pbuf(ctx->key, 0, tmp, MAX_CIPHER_KEY_SIZE); + } + + if (br && br->free && ctx->key) + br->free(br->usr, ctx->key); +} + +static __u32 get_iv_block_size(int alg, int mode) +{ + __u32 iv_block_size = CBC_AES_BLOCK_SIZE; + + switch (mode) { + case WCRYPTO_CIPHER_CBC: + case WCRYPTO_CIPHER_OFB: + if (alg == WCRYPTO_CIPHER_3DES || + alg == WCRYPTO_CIPHER_DES) + iv_block_size = CBC_3DES_BLOCK_SIZE; + break; + case WCRYPTO_CIPHER_XTS: + case WCRYPTO_CIPHER_CFB: + case WCRYPTO_CIPHER_CTR: + break; + default: + iv_block_size = 0; + break; + } + + return iv_block_size; +} + +static int create_ctx_para_check(struct wd_queue *q, + struct wcrypto_cipher_ctx_setup *setup) +{ + if (!q || !setup) { + WD_ERR("%s: input param err!\n", __func__); + return -WD_EINVAL; + } + + if (!setup->br.alloc || !setup->br.free || + !setup->br.iova_map || !setup->br.iova_unmap) { + WD_ERR("create cipher ctx user mm br err!\n"); + return -WD_EINVAL; + } + if (strcmp(q->capa.alg, "cipher") && + strcmp(q->capa.alg, "xts(aes)") && + strcmp(q->capa.alg, "xts(sm4)")) { + WD_ERR("%s: algorithm mismatching!\n", __func__); + return -WD_EINVAL; + } + + return WD_SUCCESS; +} + +static void init_cipher_cookie(struct wcrypto_cipher_ctx *ctx, + struct wcrypto_cipher_ctx_setup *setup) +{ + struct wcrypto_cipher_cookie *cookie; + int i; + + for (i = 0; i < ctx->pool.cookies_num; i++) { + cookie = (void *)((uintptr_t)ctx->pool.cookies + + i * ctx->pool.cookies_size); + cookie->msg.alg_type = WCRYPTO_CIPHER; + cookie->msg.alg = setup->alg; + cookie->msg.data_fmt = setup->data_fmt; + cookie->msg.mode = setup->mode; + cookie->tag.wcrypto_tag.ctx = ctx; + cookie->tag.wcrypto_tag.ctx_id = ctx->ctx_id; + cookie->msg.usr_data = (uintptr_t)&cookie->tag; + } +} + +static int setup_qinfo(struct wcrypto_cipher_ctx_setup *setup, + struct q_info *qinfo, __u32 *ctx_id) +{ + int ret; + + /* lock at ctx creating/deleting */ + wd_spinlock(&qinfo->qlock); + if (!qinfo->br.alloc && !qinfo->br.iova_map) + memcpy(&qinfo->br, &setup->br, sizeof(qinfo->br)); + + if (qinfo->br.usr != setup->br.usr) { + WD_ERR("Err mm br in creating cipher ctx!\n"); + goto unlock; + } + + if (qinfo->ctx_num >= WD_MAX_CTX_NUM) { + WD_ERR("err:create too many cipher ctx!\n"); + goto unlock; + } + + ret = wd_alloc_id(qinfo->ctx_id, WD_MAX_CTX_NUM, ctx_id, 0, + WD_MAX_CTX_NUM); + if (ret) { + WD_ERR("err: alloc ctx id fail!\n"); + goto unlock; + } + qinfo->ctx_num++; + wd_unspinlock(&qinfo->qlock); + + return 0; +unlock: + wd_unspinlock(&qinfo->qlock); + return -WD_EINVAL; +} + +/* Before initiate this context, we should get a queue from WD */ +void *wcrypto_create_cipher_ctx(struct wd_queue *q, + struct wcrypto_cipher_ctx_setup *setup) +{ + struct q_info *qinfo; + struct wcrypto_cipher_ctx *ctx; + __u32 ctx_id = 0; + int ret; + + if (create_ctx_para_check(q, setup)) + return NULL; + + qinfo = q->qinfo; + ret = setup_qinfo(setup, qinfo, &ctx_id); + if (ret) + return NULL; + + ctx = malloc(sizeof(struct wcrypto_cipher_ctx)); + if (!ctx) { + WD_ERR("Alloc ctx memory fail!\n"); + goto free_ctx_id; + } + memset(ctx, 0, sizeof(struct wcrypto_cipher_ctx)); + memcpy(&ctx->setup, setup, sizeof(ctx->setup)); + ctx->q = q; + ctx->ctx_id = ctx_id + 1; + ctx->key = setup->br.alloc(setup->br.usr, MAX_CIPHER_KEY_SIZE); + if (!ctx->key) { + WD_ERR("alloc cipher ctx key fail!\n"); + goto free_ctx; + } + + ctx->iv_blk_size = get_iv_block_size(setup->alg, setup->mode); + + ret = wd_init_cookie_pool(&ctx->pool, + sizeof(struct wcrypto_cipher_cookie), WD_CTX_MSG_NUM); + if (ret) { + WD_ERR("fail to init cookie pool!\n"); + goto free_ctx_key; + } + init_cipher_cookie(ctx, setup); + + return ctx; + +free_ctx_key: + setup->br.free(setup->br.usr, ctx->key); +free_ctx: + free(ctx); +free_ctx_id: + wd_spinlock(&qinfo->qlock); + qinfo->ctx_num--; + wd_free_id(qinfo->ctx_id, WD_MAX_CTX_NUM, ctx_id, WD_MAX_CTX_NUM); + wd_unspinlock(&qinfo->qlock); + + return NULL; +} + +static int is_des_weak_key(const __u64 *key, __u16 keylen) +{ + int i; + + for (i = 0; i < DES_WEAK_KEY_NUM; i++) + if (*key == des_weak_key[i]) + return 1; + + return 0; +} + +static int aes_key_len_check(__u16 length) +{ + switch (length) { + case AES_KEYSIZE_128: + case AES_KEYSIZE_192: + case AES_KEYSIZE_256: + return WD_SUCCESS; + default: + return -WD_EINVAL; + } +} + +static int cipher_key_len_check(struct wcrypto_cipher_ctx_setup *setup, + __u16 length) +{ + int ret = WD_SUCCESS; + + if (setup->mode == WCRYPTO_CIPHER_XTS) { + if (length != AES_KEYSIZE_128 && length != AES_KEYSIZE_256) { + WD_ERR("unsupported XTS key length, length = %u.\n", + length); + return -WD_EINVAL; + } + } + + switch (setup->alg) { + case WCRYPTO_CIPHER_SM4: + if (length != SM4_KEY_SIZE) + ret = -WD_EINVAL; + break; + case WCRYPTO_CIPHER_AES: + ret = aes_key_len_check(length); + break; + case WCRYPTO_CIPHER_DES: + if (length != DES_KEY_SIZE) + ret = -WD_EINVAL; + break; + case WCRYPTO_CIPHER_3DES: + if ((length != SEC_3DES_2KEY_SIZE) && (length != SEC_3DES_3KEY_SIZE)) + ret = -WD_EINVAL; + break; + default: + WD_ERR("cipher input alg err, alg is %d.\n", setup->alg); + return -WD_EINVAL; + } + + return ret; +} + +int wcrypto_set_cipher_key(void *ctx, __u8 *key, __u16 key_len) +{ + struct wcrypto_cipher_ctx *ctxt = ctx; + __u16 length = key_len; + int ret; + + if (!ctx || !key) { + WD_ERR("%s: input param err!\n", __func__); + return -WD_EINVAL; + } + + if (ctxt->setup.mode == WCRYPTO_CIPHER_XTS) + length = key_len >> XTS_MODE_KEY_SHIFT; + + ret = cipher_key_len_check(&ctxt->setup, length); + if (ret != WD_SUCCESS) { + WD_ERR("%s: input key length err!\n", __func__); + return ret; + } + + if (ctxt->setup.alg == WCRYPTO_CIPHER_DES && + is_des_weak_key((__u64 *)key, length)) { + WD_ERR("%s: des weak key!\n", __func__); + return -WD_EINVAL; + } + + ctxt->key_bytes = key_len; + + if (ctxt->setup.data_fmt == WD_SGL_BUF) + wd_sgl_cp_from_pbuf(ctxt->key, 0, key, key_len); + else + memcpy(ctxt->key, key, key_len); + + return ret; +} + +static int cipher_requests_init(struct wcrypto_cipher_msg **req, + struct wcrypto_cipher_op_data **op, + struct wcrypto_cipher_ctx *c, __u32 num) +{ + struct wd_sec_udata *udata; + __u32 i; + + for (i = 0; i < num; i++) { + req[i]->alg = c->setup.alg; + req[i]->mode = c->setup.mode; + req[i]->key = c->key; + req[i]->key_bytes = c->key_bytes; + req[i]->op_type = op[i]->op_type; + req[i]->iv = op[i]->iv; + req[i]->iv_bytes = op[i]->iv_bytes; + req[i]->in = op[i]->in; + req[i]->in_bytes = op[i]->in_bytes; + req[i]->out = op[i]->out; + req[i]->out_bytes = op[i]->out_bytes; + udata = op[i]->priv; + if (udata && udata->key) { + req[i]->key = udata->key; + req[i]->key_bytes = udata->key_bytes; + } + + if (unlikely(op[i]->iv_bytes != c->iv_blk_size)) { + WD_ERR("fail to check IV length %u!\n", i); + return -WD_EINVAL; + } + } + + return WD_SUCCESS; +} + +static int cipher_recv_sync(struct wcrypto_cipher_ctx *c_ctx, + struct wcrypto_cipher_op_data **c_opdata, __u32 num) +{ + struct wcrypto_cipher_msg *resp[WCRYPTO_MAX_BURST_NUM]; + __u32 recv_count = 0; + __u64 rx_cnt = 0; + __u32 i; + int ret; + + for (i = 0; i < num; i++) + resp[i] = (void *)(uintptr_t)c_ctx->ctx_id; + + while (true) { + ret = wd_burst_recv(c_ctx->q, (void **)(resp + recv_count), + num - recv_count); + if (ret > 0) { + recv_count += ret; + if (recv_count == num) + break; + + rx_cnt = 0; + } else if (ret == 0) { + if (++rx_cnt > MAX_CIPHER_RETRY_CNT) { + WD_ERR("%s:wcrypto_recv timeout, num = %u, recv_count = %u!\n", + __func__, num, recv_count); + break; + } + } else { + WD_ERR("do cipher wcrypto_recv error!\n"); + return ret; + } + } + + for (i = 0; i < recv_count; i++) { + c_opdata[i]->out = (void *)resp[i]->out; + c_opdata[i]->out_bytes = resp[i]->out_bytes; + c_opdata[i]->status = resp[i]->result; + } + + return recv_count; +} + +static int param_check(struct wcrypto_cipher_ctx *c_ctx, + struct wcrypto_cipher_op_data **c_opdata, + void **tag, __u32 num) +{ + __u32 i; + + if (unlikely(!c_ctx || !c_opdata || !num || num > WCRYPTO_MAX_BURST_NUM)) { + WD_ERR("input param err!\n"); + return -WD_EINVAL; + } + + for (i = 0; i < num; i++) { + if (unlikely(!c_opdata[i])) { + WD_ERR("cipher opdata[%u] is NULL!\n", i); + return -WD_EINVAL; + } + + if (unlikely(tag && !tag[i])) { + WD_ERR("tag[%u] is NULL!\n", i); + return -WD_EINVAL; + } + } + + if (unlikely(tag && !c_ctx->setup.cb)) { + WD_ERR("cipher ctx call back is NULL!\n"); + return -WD_EINVAL; + } + + return WD_SUCCESS; +} + +int wcrypto_burst_cipher(void *ctx, struct wcrypto_cipher_op_data **c_opdata, + void **tag, __u32 num) +{ + struct wcrypto_cipher_cookie *cookies[WCRYPTO_MAX_BURST_NUM] = {NULL}; + struct wcrypto_cipher_msg *req[WCRYPTO_MAX_BURST_NUM]; + struct wcrypto_cipher_ctx *ctxt = ctx; + __u32 i; + int ret; + + if (param_check(ctxt, c_opdata, tag, num)) + return -WD_EINVAL; + + ret = wd_get_cookies(&ctxt->pool, (void **)cookies, num); + if (unlikely(ret)) { + WD_ERR("failed to get cookies %d!\n", ret); + return ret; + } + + for (i = 0; i < num; i++) { + cookies[i]->tag.priv = c_opdata[i]->priv; + req[i] = &cookies[i]->msg; + if (tag) + cookies[i]->tag.wcrypto_tag.tag = tag[i]; + } + + ret = cipher_requests_init(req, c_opdata, ctxt, num); + if (unlikely(ret)) + goto fail_with_cookies; + + ret = wd_burst_send(ctxt->q, (void **)req, num); + if (unlikely(ret)) { + WD_ERR("failed to send req %d!\n", ret); + goto fail_with_cookies; + } + + if (tag) + return ret; + + ret = cipher_recv_sync(ctxt, c_opdata, num); + +fail_with_cookies: + wd_put_cookies(&ctxt->pool, (void **)cookies, num); + return ret; +} + +int wcrypto_do_cipher(void *ctx, struct wcrypto_cipher_op_data *opdata, + void *tag) +{ + int ret; + + if (!tag) { + ret = wcrypto_burst_cipher(ctx, &opdata, NULL, 1); + if (likely(ret == 1)) + return GET_NEGATIVE(opdata->status); + if (unlikely(ret == 0)) + return -WD_ETIMEDOUT; + } else { + ret = wcrypto_burst_cipher(ctx, &opdata, &tag, 1); + } + + return ret; +} + +int wcrypto_cipher_poll(struct wd_queue *q, unsigned int num) +{ + struct wcrypto_cipher_msg *cipher_resp = NULL; + struct wcrypto_cipher_ctx *ctx; + struct wcrypto_cipher_tag *tag; + unsigned int tmp = num; + int count = 0; + int ret; + + if (unlikely(!q)) { + WD_ERR("q is NULL!\n"); + return -WD_EINVAL; + } + + do { + cipher_resp = NULL; + ret = wd_recv(q, (void **)&cipher_resp); + if (ret == 0) + break; + else if (ret == -WD_HW_EACCESS) { + if (!cipher_resp) { + WD_ERR("the cipher recv err from req_cache!\n"); + return ret; + } + cipher_resp->result = WD_HW_EACCESS; + } else if (ret < 0) { + WD_ERR("recv err at cipher poll!\n"); + return ret; + } + count++; + tag = (void *)(uintptr_t)cipher_resp->usr_data; + ctx = tag->wcrypto_tag.ctx; + ctx->setup.cb(cipher_resp, tag->wcrypto_tag.tag); + wd_put_cookies(&ctx->pool, (void **)&tag, 1); + } while (--tmp); + + return count; +} + +void wcrypto_del_cipher_ctx(void *ctx) +{ + struct q_info *qinfo; + struct wcrypto_cipher_ctx *c_ctx; + + if (!ctx) { + WD_ERR("Delete cipher ctx is NULL!\n"); + return; + } + c_ctx = ctx; + qinfo = c_ctx->q->qinfo; + wd_uninit_cookie_pool(&c_ctx->pool); + wd_spinlock(&qinfo->qlock); + if (qinfo->ctx_num <= 0) { + wd_unspinlock(&qinfo->qlock); + WD_ERR("error:repeat del cipher ctx!\n"); + return; + } + wd_free_id(qinfo->ctx_id, WD_MAX_CTX_NUM, c_ctx->ctx_id - 1, + WD_MAX_CTX_NUM); + if (!(--qinfo->ctx_num)) + memset(&qinfo->br, 0, sizeof(qinfo->br)); + + wd_unspinlock(&qinfo->qlock); + del_ctx_key(c_ctx); + free(ctx); +} diff --git a/uadk/v1/wd_cipher.h b/uadk/v1/wd_cipher.h new file mode 100644 index 0000000..591a590 --- /dev/null +++ b/uadk/v1/wd_cipher.h @@ -0,0 +1,166 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#ifndef __WD_CIPHER_H +#define __WD_CIPHER_H + +#include +#include +#include +#include "wd.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum wcrypto_cipher_op_type { + WCRYPTO_CIPHER_ENCRYPTION, + WCRYPTO_CIPHER_DECRYPTION, +}; + +enum wcrypto_cipher_alg { + WCRYPTO_CIPHER_SM4, + WCRYPTO_CIPHER_AES, + WCRYPTO_CIPHER_DES, + WCRYPTO_CIPHER_3DES, +}; + +enum wcrypto_cipher_mode { + WCRYPTO_CIPHER_ECB, + WCRYPTO_CIPHER_CBC, + WCRYPTO_CIPHER_CTR, + WCRYPTO_CIPHER_XTS, + WCRYPTO_CIPHER_OFB, + WCRYPTO_CIPHER_CFB, + WCRYPTO_CIPHER_CCM, + WCRYPTO_CIPHER_GCM, +}; + +/** + * different contexts for different users/threads + * @cb: call back functions of user + * @alg: cipher algorithm type; denoted by enum wcrypto_cipher_alg + * @mode:cipher algorithm mode; denoted by enum wcrypto_cipher_mode + * @br: memory from user, it is given at ctx creating + * @data_fmt: data format, denoted by enum wcrypto_buff_type + */ +struct wcrypto_cipher_ctx_setup { + wcrypto_cb cb; + enum wcrypto_cipher_alg alg; + enum wcrypto_cipher_mode mode; + struct wd_mm_br br; + __u16 data_fmt; +}; + +/** + * operational data per I/O operation + * @op_type:cipher operation type, denoted by enum wcrypto_cipher_op_type + * @status:I/O operation return status + * @in: input data address + * @out:output data address + * @iv:initialization verctor data address + * @in_bytes: input data size + * @out_bytes:output data size + * @iv_bytes:initialization verctor data size + * @priv:reserved data field segment + */ +struct wcrypto_cipher_op_data { + enum wcrypto_cipher_op_type op_type; + int status; + void *in; + void *out; + void *iv; + __u32 in_bytes; + __u32 out_bytes; + __u32 iv_bytes; + void *priv; +}; + +/* Cipher message format of Warpdrive */ +struct wcrypto_cipher_msg { + __u8 alg_type:4; /* Denoted by enum wcrypto_type */ + __u8 alg:4; /* Denoted by enum wcrypto_cipher_alg */ + __u8 op_type:4; /* Denoted by enum wcrypto_cipher_op_type */ + __u8 mode:4; /* Denoted by enum wcrypto_cipher_mode */ + __u8 data_fmt; /* Data format, denoted by enum wcrypto_buff_type */ + __u8 result; /* Operation result, denoted by WD error code */ + + __u16 key_bytes; /* Key bytes */ + __u16 iv_bytes; /* IV bytes */ + __u32 in_bytes; /* Input data bytes */ + __u32 out_bytes; /* Output data bytes */ + + __u8 *key; /* Input key VA pointer, should be DMA buffer */ + __u8 *iv; /* Input IV VA pointer, should be DMA buffer */ + __u8 *in; /* Input data VA pointer, should be DMA buffer */ + __u8 *out; /* Output data VA pointer, should be DMA buffer */ + __u64 usr_data; /* user identifier: struct wcrypto_cb_tag */ +}; + +/** + * wcrypto_create_cipher_ctx() - create a cipher context on the wrapdrive queue. + * @q: wrapdrive queue, need requested by user. + * @setup:setup data of user + */ +void *wcrypto_create_cipher_ctx(struct wd_queue *q, + struct wcrypto_cipher_ctx_setup *setup); + +/** + * wcrypto_set_cipher_key() - set cipher key to cipher context. + * @ctx: cipher context, created by wcrypto_create_cipher_ctx. + * @key: cipher key addr + * @key_len: cipher key length + */ +int wcrypto_set_cipher_key(void *ctx, __u8 *key, __u16 key_len); + +/** + * wcrypto_do_cipher() - syn/asynchronous cipher operation + * @ctx: context of user, created by wcrypto_create_cipher_ctx. + * @opdata: operational data + * @tag: asynchronous:user_tag; synchronous:NULL. + */ +int wcrypto_do_cipher(void *ctx, struct wcrypto_cipher_op_data *opdata, + void *tag); + +/** + * wcrypto_cipher_poll() - poll operation for asynchronous operation + * @q:wrapdrive queue + * @num:how many respondences this poll has to get, 0 means get all finishings + */ +int wcrypto_cipher_poll(struct wd_queue *q, unsigned int num); + +/** + * wcrypto_del_cipher_ctx() - free cipher context + * @ctx: the context to be free + */ +void wcrypto_del_cipher_ctx(void *ctx); + +/** + * wcrypto_burst_cipher() - (a)synchronous multiple cipher operations + * @ctx: context of user, created by wcrypto_create_cipher_ctx. + * @c_opdata: operational data + * @tag: asynchronous:user_tag; synchronous:NULL. + * @num: operations number per calling, maximum number is WCRYPTO_MAX_BURST_NUM. + */ +int wcrypto_burst_cipher(void *ctx, struct wcrypto_cipher_op_data **c_opdata, + void **tag, __u32 num); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/uadk/v1/wd_comp.c b/uadk/v1/wd_comp.c new file mode 100644 index 0000000..9e7ec5a --- /dev/null +++ b/uadk/v1/wd_comp.c @@ -0,0 +1,358 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include "wd.h" +#include "wd_util.h" +#include "wd_comp.h" + +#define MAX_ALG_LEN 32 +#define MAX_RETRY_COUNTS 200000000 + +struct wcrypto_comp_cookie { + struct wcrypto_comp_tag tag; + struct wcrypto_comp_msg msg; +}; + +struct wcrypto_comp_ctx { + struct wd_cookie_pool pool; + unsigned long ctx_id; + void *ctx_buf; /* extra memory for stream mode */ + struct wd_queue *q; + wcrypto_cb cb; +}; + +static void fill_comp_msg(struct wcrypto_comp_ctx *ctx, + struct wcrypto_comp_msg *msg, + struct wcrypto_comp_op_data *opdata) +{ + msg->avail_out = opdata->avail_out; + msg->src = opdata->in; + msg->dst = opdata->out; + msg->in_size = opdata->in_len; + msg->flush_type = opdata->flush; + msg->stream_pos = opdata->stream_pos; + msg->isize = opdata->isize; + msg->checksum = opdata->checksum; + msg->tag = ctx->ctx_id; + msg->status = 0; +} + +static int set_comp_ctx_br(struct q_info *qinfo, struct wd_mm_br *br) +{ + if (!br->alloc || !br->free || + !br->iova_map || !br->iova_unmap) { + WD_ERR("err: invalid mm br in ctx_setup!\n"); + return -WD_EINVAL; + } + + if (qinfo->br.usr && (qinfo->br.usr != br->usr)) { + WD_ERR("err: qinfo and setup mm br.usr mismatch!\n"); + return -WD_EINVAL; + } + + if (!qinfo->br.alloc && !qinfo->br.iova_map) + memcpy(&qinfo->br, br, sizeof(qinfo->br)); + + return WD_SUCCESS; +} + +static int init_comp_ctx(struct wcrypto_comp_ctx *ctx, int ctx_id, + struct wcrypto_comp_ctx_setup *setup) +{ + int cache_num = ctx->pool.cookies_num; + struct wcrypto_comp_cookie *cookie; + int i; + + if (setup->stream_mode == WCRYPTO_COMP_STATEFUL) { + cache_num = 1; + ctx->ctx_buf = setup->br.alloc(setup->br.usr, MAX_CTX_RSV_SIZE); + if (!ctx->ctx_buf) { + WD_ERR("err: fail to alloc compress ctx buffer!\n"); + return -WD_ENOMEM; + } + } + + for (i = 0; i < cache_num; i++) { + cookie = (void *)((uintptr_t)ctx->pool.cookies + + i * ctx->pool.cookies_size); + cookie->msg.comp_lv = setup->comp_lv; + cookie->msg.op_type = setup->op_type; + cookie->msg.win_size = setup->win_size; + cookie->msg.alg_type = setup->alg_type; + cookie->msg.stream_mode = setup->stream_mode; + cookie->msg.data_fmt = setup->data_fmt; + cookie->msg.ctx_buf = ctx->ctx_buf; + cookie->tag.wcrypto_tag.ctx = ctx; + cookie->tag.wcrypto_tag.ctx_id = ctx_id; + cookie->msg.udata = (uintptr_t)&cookie->tag; + } + + ctx->cb = setup->cb; + ctx->ctx_id = ctx_id; + + return WD_SUCCESS; +} + +/** + * wcrypto_create_comp_ctx()- create a compress context on the queue. + * @q: queue, need requested by user. + * @setup: setup data of user + */ +void *wcrypto_create_comp_ctx(struct wd_queue *q, + struct wcrypto_comp_ctx_setup *setup) +{ + struct wcrypto_comp_ctx *ctx; + struct q_info *qinfo; + __u32 ctx_id = 0; + int ret; + + if (!q || !setup) { + WD_ERR("err, input parameter invalid!\n"); + return NULL; + } + + if (strcmp(q->capa.alg, "zlib") && + strcmp(q->capa.alg, "gzip") && + strcmp(q->capa.alg, "deflate") && + strcmp(q->capa.alg, "lz77_zstd")) { + WD_ERR("algorithm mismatch!\n"); + return NULL; + } + + qinfo = q->qinfo; + + /* lock at ctx creating/deleting */ + wd_spinlock(&qinfo->qlock); + + ret = set_comp_ctx_br(qinfo, &setup->br); + if (ret) { + WD_ERR("err: fail to set compress ctx br!\n"); + goto unlock; + } + + if (qinfo->ctx_num >= WD_MAX_CTX_NUM) { + WD_ERR("err: create too many compress ctx!\n"); + goto unlock; + } + + ret = wd_alloc_id(qinfo->ctx_id, WD_MAX_CTX_NUM, &ctx_id, 0, + WD_MAX_CTX_NUM); + if (ret) { + WD_ERR("err: alloc ctx id fail!\n"); + goto unlock; + } + qinfo->ctx_num++; + wd_unspinlock(&qinfo->qlock); + + ctx = calloc(1, sizeof(*ctx)); + if (!ctx) { + WD_ERR("alloc ctx fail!\n"); + goto free_ctx_id; + } + + ret = wd_init_cookie_pool(&ctx->pool, + sizeof(struct wcrypto_comp_cookie), WD_CTX_MSG_NUM); + if (ret) { + WD_ERR("fail to init cookie pool!\n"); + goto free_ctx_buf; + } + + ctx->q = q; + ret = init_comp_ctx(ctx, ctx_id + 1, setup); + if (ret) { + WD_ERR("err: fail to init compress ctx!\n"); + wd_uninit_cookie_pool(&ctx->pool); + goto free_ctx_buf; + } + + return ctx; + +free_ctx_buf: + free(ctx); +free_ctx_id: + wd_free_id(qinfo->ctx_id, WD_MAX_CTX_NUM, ctx_id, WD_MAX_CTX_NUM); + wd_spinlock(&qinfo->qlock); + qinfo->ctx_num--; +unlock: + wd_unspinlock(&qinfo->qlock); + return NULL; +} + +/** + * wcrypto_do_comp() - syn/asynchronous compressing/decompressing operation + * @ctx: context of user + * @opdata: operational data + * @tag: asynchronous:uesr_tag; synchronous:NULL. + */ +int wcrypto_do_comp(void *ctx, struct wcrypto_comp_op_data *opdata, void *tag) +{ + struct wcrypto_comp_cookie *cookie = NULL; + struct wcrypto_comp_ctx *cctx = ctx; + struct wcrypto_comp_msg *msg, *resp; + __u64 recv_count = 0; + int ret; + + if (!ctx || !opdata) { + WD_ERR("input parameter err!\n"); + return -EINVAL; + } + + ret = wd_get_cookies(&cctx->pool, (void **)&cookie, 1); + if (ret) + return ret; + + msg = &cookie->msg; + if (tag) { + if (!cctx->cb) { + WD_ERR("ctx call back is null!\n"); + ret = -WD_EINVAL; + goto err_put_cookie; + } + cookie->tag.wcrypto_tag.tag = tag; + } + + cookie->tag.priv = opdata->priv; + + fill_comp_msg(cctx, msg, opdata); + ret = wd_send(cctx->q, msg); + if (ret < 0) { + WD_ERR("wd_send err!\n"); + goto err_put_cookie; + } + + if (tag) + return ret; + + resp = (void *)(uintptr_t)cctx->ctx_id; + + do { + ret = wd_recv(cctx->q, (void **)&resp); + if (ret > 0) { + break; + } else if (!ret) { + if (++recv_count > MAX_RETRY_COUNTS) { + WD_ERR("wd_recv timeout fail!\n"); + ret = -ETIMEDOUT; + goto err_put_cookie; + } + } else { + WD_ERR("failed to recv msg: ret = %d!\n", ret); + goto err_put_cookie; + } + } while (true); + + opdata->consumed = resp->in_cons; + opdata->produced = resp->produced; + opdata->flush = resp->flush_type; + opdata->status = resp->status; + opdata->isize = resp->isize; + opdata->checksum = resp->checksum; + ret = WD_SUCCESS; + +err_put_cookie: + wd_put_cookies(&cctx->pool, (void **)&cookie, 1); + return ret; +} + +/** + * wcrypto_comp_poll() - poll operation for asynchronous operation + * @q:wrapdrive queue + * @num:how many respondences this poll has to get, 0 means get all finishings + */ +int wcrypto_comp_poll(struct wd_queue *q, unsigned int num) +{ + struct wcrypto_comp_msg *resp = NULL; + struct wcrypto_comp_ctx *ctx; + struct wcrypto_comp_tag *tag; + unsigned int tmp = num; + int count = 0; + int ret; + + if (!q) { + WD_ERR("%s(): input parameter err!\n", __func__); + return -WD_EINVAL; + } + + do { + ret = wd_recv(q, (void **)&resp); + if (ret == 0) { + break; + } else if (ret == -WD_HW_EACCESS) { + if (!resp) { + WD_ERR("recv err from req_cache!\n"); + return ret; + } + resp->status = WD_HW_EACCESS; + } else if (ret < 0) { + WD_ERR("recv err at qm receive!\n"); + return ret; + } + + count++; + tag = (void *)(uintptr_t)resp->udata; + ctx = tag->wcrypto_tag.ctx; + ctx->cb(resp, tag->wcrypto_tag.tag); + wd_put_cookies(&ctx->pool, (void **)&tag, 1); + resp = NULL; + } while (--tmp); + + return ret < 0 ? ret : count; +} + +/** + * wcrypto_del_comp_ctx() - free compress context + * @ctx: the context to be free + */ +void wcrypto_del_comp_ctx(void *ctx) +{ + struct wcrypto_comp_ctx *cctx = ctx; + struct q_info *qinfo; + struct wd_mm_br *br; + + if (!cctx) { + WD_ERR("delete compress ctx is NULL!\n"); + return; + } + + qinfo = cctx->q->qinfo; + br = &qinfo->br; + if (br && br->free && cctx->ctx_buf) + br->free(br->usr, cctx->ctx_buf); + + wd_uninit_cookie_pool(&cctx->pool); + wd_spinlock(&qinfo->qlock); + if (qinfo->ctx_num <= 0) { + wd_unspinlock(&qinfo->qlock); + WD_ERR("error: repeat delete compress ctx!\n"); + return; + } + + wd_free_id(qinfo->ctx_id, WD_MAX_CTX_NUM, cctx->ctx_id -1, + WD_MAX_CTX_NUM); + if (!(--qinfo->ctx_num)) + memset(&qinfo->br, 0, sizeof(qinfo->br)); + + wd_unspinlock(&qinfo->qlock); + + free(cctx); +} + diff --git a/uadk/v1/wd_comp.h b/uadk/v1/wd_comp.h new file mode 100644 index 0000000..580b968 --- /dev/null +++ b/uadk/v1/wd_comp.h @@ -0,0 +1,256 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#ifndef __WCRYPTO_COMP_H +#define __WCRYPTO_COMP_H + +#include +#include +#include "wd.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef unsigned char __u8; +typedef unsigned int __u32; +typedef unsigned long long __u64; + +#define ZIP_LOG(format, args...) fprintf(stderr, format, ##args) + +#define MAX_CTX_RSV_SIZE 65536 + +/* now hw not support config */ +enum wcrypto_comp_level { + WCRYPTO_COMP_L1 = 1, /* Compression level 1 */ + WCRYPTO_COMP_L2, /* Compression level 2 */ + WCRYPTO_COMP_L3, /* Compression level 3 */ + WCRYPTO_COMP_L4, /* Compression level 4 */ + WCRYPTO_COMP_L5, /* Compression level 5 */ + WCRYPTO_COMP_L6, /* Compression level 6 */ + WCRYPTO_COMP_L7, /* Compression level 7 */ + WCRYPTO_COMP_L8, /* Compression level 8 */ + WCRYPTO_COMP_L9, /* Compression level 9 */ +}; + +/* now hw not support config */ +enum wcrypto_comp_win_type { + WCRYPTO_COMP_WS_4K, /* 4k bytes window size */ + WCRYPTO_COMP_WS_8K, /* 8k bytes window size */ + WCRYPTO_COMP_WS_16K, /* 16k bytes window size */ + WCRYPTO_COMP_WS_24K, /* 24k bytes window size */ + WCRYPTO_COMP_WS_32K, /* 32k bytes window size */ +}; + +/* Flush types */ +enum wcrypto_comp_flush_type { + WCRYPTO_INVALID_FLUSH, + + /* output as much data as we can to improve performance */ + WCRYPTO_NO_FLUSH, + + /* output as bytes aligning or some other conditions satisfied */ + WCRYPTO_SYNC_FLUSH, + + /* indicates the end of the file/data */ + WCRYPTO_FINISH, +}; + +enum wcrypto_comp_alg_type { + WCRYPTO_ZLIB, + WCRYPTO_GZIP, + WCRYPTO_RAW_DEFLATE, + WCRYPTO_LZ77_ZSTD, + WCRYPTO_COMP_MAX_ALG, +}; + +/* Operational types for COMP */ +enum wcrypto_comp_optype { + WCRYPTO_DEFLATE, + WCRYPTO_INFLATE, +}; + +enum wcrypto_op_result { + WCRYPTO_STATUS_NULL, + WCRYPTO_COMP_END, + WCRYPTO_DECOMP_END, + WCRYPTO_DECOMP_END_NOSPACE, + WCRYPTO_DECOMP_NO_CRC, + WCRYPTO_DECOMP_BLK_NOSTART, + WCRYPTO_SRC_DIF_ERR, + WCRYPTO_DST_DIF_ERR, + WCRYPTO_NEGTIVE_COMP_ERR, +}; + +enum wcrypto_comp_state { + WCRYPTO_COMP_STATELESS, + WCRYPTO_COMP_STATEFUL, +}; + +enum wcrypto_stream_status { + WCRYPTO_COMP_STREAM_OLD, + WCRYPTO_COMP_STREAM_NEW, /* indicates first packet */ +}; + +/** + * different contexts for different users/threads + * @cb: call back functions of user + * @alg_type:compressing algorithm type zlib/gzip + * @op_type:operational types deflate/inflate + * @stream_mode:stateless(block)/statefull + * @comp_lv: compressing level;now reserved + * @win_size: window size of algorithm; now reserved + * @data_fmt: buffer format + * @br: memory operations from user + */ +struct wcrypto_comp_ctx_setup { + wcrypto_cb cb; + __u8 alg_type; + __u8 op_type; + __u8 stream_mode; + __u8 comp_lv; + __u16 win_size; + __u16 data_fmt; + struct wd_mm_br br; +}; + +/** + * operational out data when use zstd_lz77 in sgl format + * @literal:literals address when use zstd in sgl format + * @lit_len:avail literals size for hw when use zstd in sgl format, + * and avail literals is always <= (src_len + ZSTD_LIT_RSV_SIZE); + * @sequence:sequence address when use zstd in sgl format + * @seq_len:avail literals size for hw when use zstd in sgl format + */ +struct wcrypto_zstd_out { + void *literal; + __u32 lit_sz; + void *sequence; + __u32 seq_sz; +}; + +/** + * operational data per I/O operation + * @alg_type:compressing algorithm type zlib/gzip + * @flush:input and output, denotes flush type or data status + * @stream_pos: denotes stream start + * @status:task status current time + * @in:input data address + * @out:output data address + * @in_len:input data size + * @avail_out:avail output size for hw + * @consumed:output, denotes how many bytes are consumed this time + * @produced:output, denotes how many bytes are produced this time + * @isize:gzip isize + * @checksum: protocol checksum + * @priv: private field for extend + */ +struct wcrypto_comp_op_data { + __u8 alg_type; + __u8 flush; + __u8 stream_pos; + __u8 status; + __u8 *in; + __u8 *out; + __u32 in_len; + __u32 avail_out; + __u32 consumed; + __u32 produced; + __u32 isize; + __u32 checksum; + void *priv; +}; + +struct wcrypto_comp_msg { + __u8 alg_type; /* Denoted by enum wcrypto_comp_alg_type */ + __u8 op_type; /* Denoted by enum wcrypto_comp_op_type */ + __u8 flush_type; /* Denoted by enum wcrypto_comp_flush_type */ + __u8 stream_mode;/* Denoted by enum wcrypto_comp_state */ + __u8 stream_pos; /* Denoted by enum wcrypto_stream_status */ + __u8 comp_lv; /* Denoted by enum wcrypto_comp_level */ + __u8 data_fmt; /* Data format, denoted by enum wd_buff_type */ + __u8 win_size; /* Denoted by enum wcrypto_comp_win_type */ + __u32 in_size; /* Input data bytes */ + __u32 avail_out; /* Output buffer size */ + __u32 in_cons; /* consumed bytes of input data */ + __u32 produced; /* produced bytes of current operation */ + __u8 *src; /* Input data VA, buf should be DMA-able. */ + __u8 *dst; /* Output data VA pointer */ + __u32 tag; /* User-defined request identifier */ + __u32 status; /* Denoted by error code and enum wcrypto_op_result */ + __u32 isize; /* Denoted by gzip isize */ + __u32 checksum; /* Denoted by zlib/gzip CRC */ + void *ctx_buf; /* Denoted HW ctx cache, for stream mode */ + __u64 udata; /* Input user tag, identify data of stream/user */ +}; + +/** + * The output format defined by uadk and drivers should fill the format + * @literals_start:address of the literals data output by the hardware + * @sequences_start:address of the sequences data output by the hardware + * @lit_num:the size of literals + * @seq_num:the size of sequences + * @lit_length_overflow_cnt:the count of the literal length overflow + * @lit_length_overflow_pos:the position of the literal length overflow + * @freq:address of the frequency about sequences members + * @blk_type:the previous block status, 0 means an uncompressed block, + * 1 means a RLE block and 2 means a compressed block. + */ +struct wcrypto_lz77_zstd_format { + void *literals_start; + void *sequences_start; + __u32 lit_num; + __u32 seq_num; + __u32 lit_length_overflow_cnt; + __u32 lit_length_overflow_pos; + void *freq; + __u32 blk_type; +}; + +/** + * wcrypto_create_comp_ctx() - create a compress context on the wrapdrive queue. + * @q: wrapdrive queue, need requested by user. + * @setup:setup data of user + */ +void *wcrypto_create_comp_ctx(struct wd_queue *q, + struct wcrypto_comp_ctx_setup *setup); + +/** + * wcrypto_do_comp() - syn/asynchronous compressing/decompressing operation + * @ctx: context of user + * @opdata: operational data + * @tag: asynchronous:user_tag; synchronous:NULL. + */ +int wcrypto_do_comp(void *ctx, struct wcrypto_comp_op_data *opdata, void *tag); + +/** + * wcrypto_comp_poll() - poll operation for asynchronous operation + * @q:wrapdrive queue + * @num:how many respondences this poll has to get, 0 means get all finishings + */ +int wcrypto_comp_poll(struct wd_queue *q, unsigned int num); + +/** + * wcrypto_del_comp_ctx() - free compress context + * @ctx: the context to be free + */ +void wcrypto_del_comp_ctx(void *ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/uadk/v1/wd_dh.c b/uadk/v1/wd_dh.c new file mode 100644 index 0000000..25483c1 --- /dev/null +++ b/uadk/v1/wd_dh.c @@ -0,0 +1,455 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include + +#include +#include + +#include "wd.h" +#include "wd_util.h" +#include "wd_dh.h" + +#define WD_DH_G2 2 +#define DH_BALANCE_THRHD 1280 +#define DH_RESEND_CNT 8 +#define DH_RECV_MAX_CNT 60000000 // 1 min + +static __thread int balance; + +struct wcrypto_dh_cookie { + struct wcrypto_cb_tag tag; + struct wcrypto_dh_msg msg; +}; + +struct wcrypto_dh_ctx { + struct wd_cookie_pool pool; + __u32 key_size; + unsigned long ctx_id; + struct wd_queue *q; + struct wd_dtb g; + struct wcrypto_dh_ctx_setup setup; +}; + +static int create_ctx_param_check(struct wd_queue *q, + struct wcrypto_dh_ctx_setup *setup) +{ + if (!q || !setup) { + WD_ERR("%s(): input parameter err!\n", __func__); + return -WD_EINVAL; + } + + if (!setup->br.alloc || !setup->br.free) { + WD_ERR("create dh ctx user mm br err!\n"); + return -WD_EINVAL; + } + + if (strcmp(q->capa.alg, "dh")) { + WD_ERR("%s(): algorithm mismatch!\n", __func__); + return -WD_EINVAL; + } + + return 0; +} + +static int wcrypto_init_dh_cookie(struct wcrypto_dh_ctx *ctx) +{ + struct wcrypto_dh_ctx_setup *setup = &ctx->setup; + struct wcrypto_dh_cookie *cookie; + int ret, i; + + ret = wd_init_cookie_pool(&ctx->pool, + sizeof(struct wcrypto_dh_cookie), WD_HPRE_CTX_MSG_NUM); + if (ret) { + WD_ERR("fail to init cookie pool!\n"); + return ret; + } + + for (i = 0; i < ctx->pool.cookies_num; i++) { + cookie = (void *)((uintptr_t)ctx->pool.cookies + + i * ctx->pool.cookies_size); + cookie->msg.is_g2 = (__u8)setup->is_g2; + cookie->msg.data_fmt = setup->data_fmt; + cookie->msg.key_bytes = ctx->key_size; + cookie->msg.alg_type = WCRYPTO_DH; + cookie->tag.ctx = ctx; + cookie->tag.ctx_id = ctx->ctx_id; + cookie->msg.usr_data = (uintptr_t)&cookie->tag; + } + + return 0; +} + +static int setup_qinfo(struct wcrypto_dh_ctx_setup *setup, + struct q_info *qinfo, __u32 *ctx_id) +{ + int ret; + + wd_spinlock(&qinfo->qlock); + + if (!qinfo->br.alloc && !qinfo->br.iova_map) + memcpy(&qinfo->br, &setup->br, sizeof(setup->br)); + + if (qinfo->br.usr != setup->br.usr) { + WD_ERR("err: qinfo and setup mm br.usr mismatch!\n"); + goto unlock; + } + + if (qinfo->ctx_num >= WD_MAX_CTX_NUM) { + WD_ERR("err: create too many dh ctx!\n"); + goto unlock; + } + + ret = wd_alloc_id(qinfo->ctx_id, WD_MAX_CTX_NUM, + ctx_id, 0, WD_MAX_CTX_NUM); + if (ret) { + WD_ERR("err: alloc ctx id fail!\n"); + goto unlock; + } + qinfo->ctx_num++; + wd_unspinlock(&qinfo->qlock); + + return 0; +unlock: + wd_unspinlock(&qinfo->qlock); + + return -WD_EINVAL; +} + +/* Before initiate this context, we should get a queue from WD */ +void *wcrypto_create_dh_ctx(struct wd_queue *q, struct wcrypto_dh_ctx_setup *setup) +{ + struct wcrypto_dh_ctx *ctx; + struct q_info *qinfo; + __u32 ctx_id = 0; + int ret; + + ret = create_ctx_param_check(q, setup); + if (ret) + return NULL; + + qinfo = q->qinfo; + ret = setup_qinfo(setup, qinfo, &ctx_id); + if (ret) + return NULL; + + ctx = malloc(sizeof(struct wcrypto_dh_ctx)); + if (!ctx) { + WD_ERR("alloc ctx memory fail!\n"); + goto free_ctx_id; + } + + memset(ctx, 0, sizeof(struct wcrypto_dh_ctx)); + memcpy(&ctx->setup, setup, sizeof(*setup)); + ctx->q = q; + ctx->ctx_id = ctx_id + 1; + ctx->key_size = setup->key_bits >> BYTE_BITS_SHIFT; + + if (setup->br.get_bufsize && + setup->br.get_bufsize(setup->br.usr) < ctx->key_size) { + WD_ERR("Blk_size < need_size<0x%x>.\n", ctx->key_size); + goto free_ctx; + } + ctx->g.data = ctx->setup.br.alloc(ctx->setup.br.usr, ctx->key_size); + ctx->g.bsize = ctx->key_size; + + ret = wcrypto_init_dh_cookie(ctx); + if (ret) + goto free_ctx_gdata; + + return ctx; + +free_ctx_gdata: + setup->br.free(setup->br.usr, ctx->g.data); +free_ctx: + free(ctx); +free_ctx_id: + wd_free_id(qinfo->ctx_id, WD_MAX_CTX_NUM, ctx_id, WD_MAX_CTX_NUM); + wd_spinlock(&qinfo->qlock); + qinfo->ctx_num--; + wd_unspinlock(&qinfo->qlock); + + return NULL; +} + +bool wcrypto_dh_is_g2(const void *ctx) +{ + if (!ctx) { + WD_ERR("dh is g2 judge, ctx NULL, return false!\n"); + return false; + } + + return ((struct wcrypto_dh_ctx *)ctx)->setup.is_g2; +} + +int wcrypto_dh_key_bits(const void *ctx) +{ + if (!ctx) { + WD_ERR("get dh key bits, ctx NULL!\n"); + return 0; + } + + return ((struct wcrypto_dh_ctx *)ctx)->setup.key_bits; +} + +int wcrypto_set_dh_g(void *ctx, struct wd_dtb *g) +{ + struct wcrypto_dh_ctx *cx = ctx; + + if (!cx || !g) { + WD_ERR("parameter NULL!\n"); + return -WD_EINVAL; + } + + if (g->dsize + && g->bsize <= cx->g.bsize + && g->dsize <= cx->g.bsize) { + memset(cx->g.data, 0, g->bsize); + memcpy(cx->g.data, g->data, g->dsize); + cx->g.dsize = g->dsize; + if (*g->data != WD_DH_G2 && cx->setup.is_g2) + return -WD_EINVAL; + return WD_SUCCESS; + } + + return -WD_EINVAL; +} + +void wcrypto_get_dh_g(void *ctx, struct wd_dtb **g) +{ + if (!ctx || !g) { + WD_ERR("parameter NULL!\n"); + return; + } + + *g = &((struct wcrypto_dh_ctx *)ctx)->g; +} + +static int dh_request_init(struct wcrypto_dh_msg *req, struct wcrypto_dh_op_data *op, + struct wcrypto_dh_ctx *c) +{ + req->x_p = (__u8 *)op->x_p; + req->xbytes = (__u16)op->xbytes; + req->pbytes = (__u16)op->pbytes; + req->out = (__u8 *)op->pri; + req->op_type = op->op_type; + req->result = WD_EINVAL; + + if (op->op_type == WCRYPTO_DH_PHASE1) { + req->g = (__u8 *)c->g.data; + req->gbytes = c->g.dsize; + } else { + req->g = (__u8 *)op->pv; + req->gbytes = op->pvbytes; + } + + if (unlikely(!req->g)) { + WD_ERR("request dh g is NULL!\n"); + return -WD_EINVAL; + } + + return WD_SUCCESS; +} + +static int do_dh_prepare(struct wcrypto_dh_op_data *opdata, + struct wcrypto_dh_cookie **cookie_addr, + struct wcrypto_dh_ctx *ctxt, + struct wcrypto_dh_msg **req_addr, + void *tag) +{ + struct wcrypto_dh_cookie *cookie; + struct wcrypto_dh_msg *req; + int ret; + + if (unlikely(!ctxt || !opdata)) { + WD_ERR("input parameter err!\n"); + return -WD_EINVAL; + } + + if (unlikely(tag && !ctxt->setup.cb)) { + WD_ERR("ctx call back is null!\n"); + return -WD_EINVAL; + } + + ret = wd_get_cookies(&ctxt->pool, (void **)&cookie, 1); + if (ret) + return ret; + + if (tag) + cookie->tag.tag = tag; + + req = &cookie->msg; + ret = dh_request_init(req, opdata, ctxt); + if (unlikely(ret)) { + wd_put_cookies(&ctxt->pool, (void **)&cookie, 1); + return ret; + } + + *cookie_addr = cookie; + *req_addr = req; + + return 0; +} + +static int dh_send(struct wcrypto_dh_ctx *ctx, struct wcrypto_dh_msg *req) +{ + uint32_t tx_cnt = 0; + int ret; + + do { + ret = wd_send(ctx->q, req); + if (!ret) { + break; + } else if (ret == -WD_EBUSY) { + if (tx_cnt++ > DH_RESEND_CNT) { + WD_ERR("do dh send cnt %u, exit!\n", tx_cnt); + break; + } + + usleep(1); + } else { + WD_ERR("do dh wd_send err!\n"); + break; + } + } while (true); + + return ret; +} + +int wcrypto_do_dh(void *ctx, struct wcrypto_dh_op_data *opdata, void *tag) +{ + struct wcrypto_dh_msg *resp = NULL; + struct wcrypto_dh_ctx *ctxt = ctx; + struct wcrypto_dh_cookie *cookie; + struct wcrypto_dh_msg *req; + uint32_t rx_cnt = 0; + int ret; + + ret = do_dh_prepare(opdata, &cookie, ctxt, &req, tag); + if (unlikely(ret)) + return ret; + + ret = dh_send(ctxt, req); + if (unlikely(ret)) + goto fail_with_cookie; + + if (tag) + return ret; + + resp = (void *)(uintptr_t)ctxt->ctx_id; + + do { + ret = wd_recv(ctxt->q, (void **)&resp); + if (ret > 0) { + break; + } else if (!ret) { + if (unlikely(rx_cnt++ >= DH_RECV_MAX_CNT)) { + WD_ERR("failed to receive: timeout!\n"); + ret = -WD_ETIMEDOUT; + goto fail_with_cookie; + } + + if (balance > DH_BALANCE_THRHD) + usleep(1); + } else { + WD_ERR("do dh wd_recv err!\n"); + goto fail_with_cookie; + } + } while (true); + + balance = rx_cnt; + opdata->pri = (void *)resp->out; + opdata->pri_bytes = resp->out_bytes; + opdata->status = resp->result; + ret = GET_NEGATIVE(opdata->status); + +fail_with_cookie: + wd_put_cookies(&ctxt->pool, (void **)&cookie, 1); + return ret; +} + +int wcrypto_dh_poll(struct wd_queue *q, unsigned int num) +{ + struct wcrypto_dh_msg *resp = NULL; + struct wcrypto_dh_ctx *ctx; + struct wcrypto_cb_tag *tag; + unsigned int tmp = num; + int count = 0; + int ret; + + if (unlikely(!q)) { + WD_ERR("q is NULL!\n"); + return -WD_EINVAL; + } + + do { + ret = wd_recv(q, (void **)&resp); + if (ret == 0) + break; + else if (unlikely(ret < 0)) { + WD_ERR("receive err at dh poll!\n"); + return ret; + } + + count++; + tag = (void *)(uintptr_t)resp->usr_data; + ctx = tag->ctx; + ctx->setup.cb(resp, tag->tag); + wd_put_cookies(&ctx->pool, (void **)&tag, 1); + resp = NULL; + } while (--tmp); + + return count; +} + +void wcrypto_del_dh_ctx(void *ctx) +{ + struct wcrypto_dh_ctx_setup *st; + struct wcrypto_dh_ctx *cx; + struct q_info *qinfo; + + if (!ctx) { + WD_ERR("delete dh parameter err!\n"); + return; + } + + cx = ctx; + qinfo = cx->q->qinfo; + st = &cx->setup; + + wd_uninit_cookie_pool(&cx->pool); + wd_spinlock(&qinfo->qlock); + if (qinfo->ctx_num <= 0) { + wd_unspinlock(&qinfo->qlock); + WD_ERR("error: repeat del dh ctx!\n"); + return; + } + + wd_free_id(qinfo->ctx_id, WD_MAX_CTX_NUM, cx->ctx_id - 1, + WD_MAX_CTX_NUM); + + if (!(--qinfo->ctx_num)) + memset(&qinfo->br, 0, sizeof(qinfo->br)); + wd_unspinlock(&qinfo->qlock); + + if (st->br.free && cx->g.data) + st->br.free(st->br.usr, cx->g.data); + + free(ctx); +} diff --git a/uadk/v1/wd_dh.h b/uadk/v1/wd_dh.h new file mode 100644 index 0000000..e411830 --- /dev/null +++ b/uadk/v1/wd_dh.h @@ -0,0 +1,91 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#ifndef __WD_DH_H +#define __WD_DH_H + +#include +#include +#include "wd.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum wcrypto_dh_op_type { + WCRYPTO_DH_INVALID, /* invalid DH operation */ + WCRYPTO_DH_PHASE1, /* Phase1 DH key generate */ + WCRYPTO_DH_PHASE2 /* Phase2 DH key compute */ +}; + +struct wcrypto_dh_ctx_setup { + wcrypto_cb cb; /* call back function from user */ + __u16 data_fmt; /* data format denoted by enum wd_buff_type */ + __u16 key_bits; /* DH key bites */ + bool is_g2; /* is g2 mode or not */ + struct wd_mm_br br; /* memory operations from user */ +}; + +struct wcrypto_dh_op_data { + void *x_p; /* x and p, should be DMA buffer */ + + /* it is g, but it is PV at phase 2, should be DMA buffer */ + void *pv; + + /* phase 1&&2 output, should be DMA buffer */ + void *pri; + __u16 pri_bytes; /* output bytes */ + + __u16 pbytes; /* p bytes */ + __u16 xbytes; /* x bytes */ + __u16 pvbytes; /* pv bytes */ + enum wcrypto_dh_op_type op_type; /* operational type */ + __u32 status; /* output status */ +}; + +struct wcrypto_dh_msg { + __u8 alg_type:3; /* Denoted by enum wcrypto_type */ + __u8 op_type:2; /* Denoted by enum wcrypto_dh_op_type */ + __u8 data_fmt:1; /* Data format, denoted by enum wd_buff_type */ + __u8 is_g2:2; /* g2 mode of phase 1 */ + __u8 result; /* Data format, denoted by WD error code */ + __u16 key_bytes; /* Key size */ + __u8 *x_p; /* This is Xa and p data in order. Should be DMA buffer */ + __u8 *g; /* This is PV also at phase 2. Should be DMA buffer */ + __u8 *out; /* Result address, should be DMA buffer */ + __u16 xbytes; /* parameter Xa size */ + __u16 pbytes; /* parameter p size */ + __u16 gbytes; /* parameter g size */ + __u16 out_bytes; /* output parameter size */ + __u64 usr_data; /* user identifier: struct wcrypto_cb_tag */ +}; + +void *wcrypto_create_dh_ctx(struct wd_queue *q, struct wcrypto_dh_ctx_setup *setup); +bool wcrypto_dh_is_g2(const void *ctx); +int wcrypto_dh_key_bits(const void *ctx); + +/* Asynchronous/sync mode APIs of DH */ +int wcrypto_do_dh(void *ctx, struct wcrypto_dh_op_data *opdata, void *tag); +int wcrypto_dh_poll(struct wd_queue *q, unsigned int num); +void wcrypto_del_dh_ctx(void *ctx); +int wcrypto_set_dh_g(void *ctx, struct wd_dtb *g); +void wcrypto_get_dh_g(void *ctx, struct wd_dtb **g); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/uadk/v1/wd_digest.c b/uadk/v1/wd_digest.c new file mode 100644 index 0000000..7b01b14 --- /dev/null +++ b/uadk/v1/wd_digest.c @@ -0,0 +1,485 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include + +#include +#include + +#include "wd.h" +#include "wd_util.h" +#include "wd_digest.h" + +#define MAX_HMAC_KEY_SIZE 128 +#define MAX_DIGEST_RETRY_CNT 20000000 +#define SEC_SHA1_ALIGN_SZ 64 +#define SEC_SHA512_ALIGN_SZ 128 + +struct wcrypto_digest_cookie { + struct wcrypto_digest_tag tag; + struct wcrypto_digest_msg msg; +}; + +struct wcrypto_digest_ctx { + struct wd_cookie_pool pool; + unsigned long ctx_id; + void *key; + __u32 key_bytes; + __u64 io_bytes; + __u8 align_sz; + struct wd_queue *q; + struct wcrypto_digest_ctx_setup setup; +}; + +static int g_digest_mac_len[WCRYPTO_MAX_DIGEST_TYPE] = { + WCRYPTO_DIGEST_SM3_LEN, WCRYPTO_DIGEST_MD5_LEN, WCRYPTO_DIGEST_SHA1_LEN, + WCRYPTO_DIGEST_SHA256_LEN, WCRYPTO_DIGEST_SHA224_LEN, + WCRYPTO_DIGEST_SHA384_LEN, WCRYPTO_DIGEST_SHA512_LEN, + WCRYPTO_DIGEST_SHA512_224_LEN, WCRYPTO_DIGEST_SHA512_256_LEN +}; + +static void del_ctx_key(struct wcrypto_digest_ctx *ctx) +{ + struct wd_mm_br *br = &(ctx->setup.br); + __u8 tmp[MAX_HMAC_KEY_SIZE] = { 0 }; + + /** + * When data_fmt is 'WD_SGL_BUF', 'akey' and 'ckey' is a sgl, and if u + * want to clear the SGL buffer, we can only use 'wd_sgl_cp_from_pbuf' + * whose 'pbuf' is all zero. + */ + if (ctx->key) { + if (ctx->setup.data_fmt == WD_FLAT_BUF) + memset(ctx->key, 0, MAX_HMAC_KEY_SIZE); + else if (ctx->setup.data_fmt == WD_SGL_BUF) + wd_sgl_cp_from_pbuf(ctx->key, 0, tmp, MAX_HMAC_KEY_SIZE); + } + + if (br && br->free && ctx->key) + br->free(br->usr, ctx->key); +} + +static int create_ctx_para_check(struct wd_queue *q, + struct wcrypto_digest_ctx_setup *setup) +{ + if (!q || !setup) { + WD_ERR("%s: input param err!\n", __func__); + return -WD_EINVAL; + } + if (setup->mode == WCRYPTO_DIGEST_HMAC) { + if (!setup->br.alloc || !setup->br.free || + !setup->br.iova_map || !setup->br.iova_unmap) { + WD_ERR("create digest ctx user mm br err!\n"); + return -WD_EINVAL; + } + } + + if (strcmp(q->capa.alg, "digest")) { + WD_ERR("%s: algorithm mismatching!\n", __func__); + return -WD_EINVAL; + } + + return WD_SUCCESS; +} + +static void init_digest_cookie(struct wcrypto_digest_ctx *ctx, + struct wcrypto_digest_ctx_setup *setup) +{ + struct wcrypto_digest_cookie *cookie; + int i; + + for (i = 0; i < ctx->pool.cookies_num; i++) { + cookie = (void *)((uintptr_t)ctx->pool.cookies + + i * ctx->pool.cookies_size); + cookie->msg.alg_type = WCRYPTO_DIGEST; + cookie->msg.alg = setup->alg; + cookie->msg.mode = setup->mode; + cookie->msg.data_fmt = setup->data_fmt; + cookie->tag.long_data_len = 0; + cookie->tag.priv = NULL; + cookie->tag.wcrypto_tag.ctx = ctx; + cookie->tag.wcrypto_tag.ctx_id = ctx->ctx_id; + cookie->msg.usr_data = (uintptr_t)&cookie->tag; + } +} + +static int setup_qinfo(struct wcrypto_digest_ctx_setup *setup, + struct q_info *qinfo, __u32 *ctx_id) +{ + int ret; + + /* lock at ctx creating/deleting */ + wd_spinlock(&qinfo->qlock); + if (!qinfo->br.alloc && !qinfo->br.iova_map) + memcpy(&qinfo->br, &setup->br, sizeof(qinfo->br)); + if (qinfo->br.usr != setup->br.usr) { + WD_ERR("Err mm br in creating digest ctx!\n"); + goto unlock; + } + + if (qinfo->ctx_num >= WD_MAX_CTX_NUM) { + WD_ERR("err:create too many digest ctx!\n"); + goto unlock; + } + + ret = wd_alloc_id(qinfo->ctx_id, WD_MAX_CTX_NUM, ctx_id, 0, + WD_MAX_CTX_NUM); + if (ret) { + WD_ERR("err: alloc ctx id fail!\n"); + goto unlock; + } + qinfo->ctx_num++; + wd_unspinlock(&qinfo->qlock); + + return 0; +unlock: + wd_unspinlock(&qinfo->qlock); + return -WD_EINVAL; +} + +/* Before initiate this context, we should get a queue from WD */ +void *wcrypto_create_digest_ctx(struct wd_queue *q, + struct wcrypto_digest_ctx_setup *setup) +{ + struct q_info *qinfo; + struct wcrypto_digest_ctx *ctx; + __u32 ctx_id = 0; + int ret; + + if (create_ctx_para_check(q, setup)) + return NULL; + + qinfo = q->qinfo; + ret = setup_qinfo(setup, qinfo, &ctx_id); + if (ret) + return NULL; + + ctx = malloc(sizeof(struct wcrypto_digest_ctx)); + if (!ctx) { + WD_ERR("Alloc ctx memory fail!\n"); + goto free_ctx_id; + } + memset(ctx, 0, sizeof(struct wcrypto_digest_ctx)); + memcpy(&ctx->setup, setup, sizeof(ctx->setup)); + ctx->q = q; + ctx->ctx_id = ctx_id + 1; + if (setup->mode == WCRYPTO_DIGEST_HMAC) { + ctx->key = setup->br.alloc(setup->br.usr, MAX_HMAC_KEY_SIZE); + if (!ctx->key) { + WD_ERR("alloc digest ctx key fail!\n"); + goto free_ctx; + } + } + + if (setup->alg >= WCRYPTO_SHA512) + ctx->align_sz = SEC_SHA512_ALIGN_SZ; + else + ctx->align_sz = SEC_SHA1_ALIGN_SZ; + + ret = wd_init_cookie_pool(&ctx->pool, + sizeof(struct wcrypto_digest_cookie), WD_CTX_MSG_NUM); + if (ret) { + WD_ERR("fail to init cookie pool!\n"); + goto free_ctx_key; + } + init_digest_cookie(ctx, setup); + + return ctx; + +free_ctx_key: + if (setup->mode == WCRYPTO_DIGEST_HMAC) + setup->br.free(setup->br.usr, ctx->key); +free_ctx: + free(ctx); +free_ctx_id: + wd_spinlock(&qinfo->qlock); + qinfo->ctx_num--; + wd_free_id(qinfo->ctx_id, WD_MAX_CTX_NUM, ctx_id, WD_MAX_CTX_NUM); + wd_unspinlock(&qinfo->qlock); + + return NULL; +} + +static void digest_requests_init(struct wcrypto_digest_msg **req, + struct wcrypto_digest_op_data **op, + struct wcrypto_digest_ctx *c, __u32 num) +{ + __u32 i; + + for (i = 0; i < num; i++) { + req[i]->has_next = op[i]->has_next; + req[i]->key = c->key; + req[i]->key_bytes = c->key_bytes; + req[i]->in = op[i]->in; + req[i]->in_bytes = op[i]->in_bytes; + req[i]->out = op[i]->out; + req[i]->out_bytes = op[i]->out_bytes; + c->io_bytes += op[i]->in_bytes; + } +} + +int wcrypto_set_digest_key(void *ctx, __u8 *key, __u16 key_len) +{ + struct wcrypto_digest_ctx *ctxt = ctx; + + if (!ctx || !key) { + WD_ERR("%s(): input param err!\n", __func__); + return -WD_EINVAL; + } + + if ((ctxt->setup.alg <= WCRYPTO_SHA224 && key_len > + MAX_HMAC_KEY_SIZE >> 1) || key_len == 0 || + key_len > MAX_HMAC_KEY_SIZE) { + WD_ERR("%s: input key length err!\n", __func__); + return -WD_EINVAL; + } + + ctxt->key_bytes = key_len; + + if (ctxt->setup.data_fmt == WD_SGL_BUF) + wd_sgl_cp_from_pbuf(ctxt->key, 0, key, key_len); + else + memcpy(ctxt->key, key, key_len); + + return WD_SUCCESS; +} + +static int digest_recv_sync(struct wcrypto_digest_ctx *d_ctx, + struct wcrypto_digest_op_data **d_opdata, __u32 num) +{ + struct wcrypto_digest_msg *resp[WCRYPTO_MAX_BURST_NUM]; + __u32 recv_count = 0; + __u64 rx_cnt = 0; + __u32 i; + int ret; + + for (i = 0; i < num; i++) + resp[i] = (void *)(uintptr_t)d_ctx->ctx_id; + + while (true) { + ret = wd_burst_recv(d_ctx->q, (void **)(resp + recv_count), + num - recv_count); + if (ret > 0) { + recv_count += ret; + if (recv_count == num) + break; + + rx_cnt = 0; + } else if (ret == 0) { + if (++rx_cnt > MAX_DIGEST_RETRY_CNT) { + WD_ERR("%s:wcrypto_recv timeout, num = %u, recv_count = %u!\n", + __func__, num, recv_count); + break; + } + } else { + WD_ERR("do digest wcrypto_recv error!\n"); + return ret; + } + } + + for (i = 0; i < recv_count; i++) { + d_opdata[i]->out = (void *)resp[i]->out; + d_opdata[i]->out_bytes = resp[i]->out_bytes; + d_opdata[i]->status = resp[i]->result; + } + + return recv_count; +} + +static int param_check(struct wcrypto_digest_ctx *d_ctx, + struct wcrypto_digest_op_data **d_opdata, + void **tag, __u32 num) +{ + enum wcrypto_digest_alg alg; + __u32 i; + + if (unlikely(!d_ctx || !d_opdata || !num || num > WCRYPTO_MAX_BURST_NUM)) { + WD_ERR("input param err!\n"); + return -WD_EINVAL; + } + + alg = d_ctx->setup.alg; + + for (i = 0; i < num; i++) { + if (unlikely(!d_opdata[i])) { + WD_ERR("digest opdata[%u] is NULL!\n", i); + return -WD_EINVAL; + } + + if (unlikely(num != 1 && d_opdata[i]->has_next)) { + WD_ERR("num > 1, wcrypto_burst_digest does not support stream mode!\n"); + return -WD_EINVAL; + } + + if (unlikely(d_opdata[0]->has_next && d_opdata[0]->in_bytes % d_ctx->align_sz)) { + WD_ERR("digest stream mode must be %u-byte aligned!\n", d_ctx->align_sz); + return -WD_EINVAL; + } + if (d_opdata[i]->out_bytes == 0 || + d_opdata[i]->out_bytes > g_digest_mac_len[alg]) { + WD_ERR("failed to check digest mac length!\n"); + return -WD_EINVAL; + } + + if (unlikely(tag && !tag[i])) { + WD_ERR("tag[%u] is NULL!\n", i); + return -WD_EINVAL; + } + } + + if (unlikely(tag && !d_ctx->setup.cb)) { + WD_ERR("digest ctx call back is NULL!\n"); + return -WD_EINVAL; + } + + return WD_SUCCESS; +} + +int wcrypto_burst_digest(void *d_ctx, struct wcrypto_digest_op_data **opdata, + void **tag, __u32 num) +{ + struct wcrypto_digest_cookie *cookies[WCRYPTO_MAX_BURST_NUM] = {NULL}; + struct wcrypto_digest_msg *req[WCRYPTO_MAX_BURST_NUM] = {NULL}; + struct wcrypto_digest_ctx *ctxt = d_ctx; + __u32 i; + int ret; + + if (param_check(ctxt, opdata, tag, num)) + return -WD_EINVAL; + + ret = wd_get_cookies(&ctxt->pool, (void **)cookies, num); + if (unlikely(ret)) { + WD_ERR("failed to get cookies %d!\n", ret); + return ret; + } + + for (i = 0; i < num; i++) { + cookies[i]->tag.priv = opdata[i]->priv; + req[i] = &cookies[i]->msg; + if (tag) + cookies[i]->tag.wcrypto_tag.tag = tag[i]; + } + + digest_requests_init(req, opdata, d_ctx, num); + /* when num is 1, wcrypto_burst_digest supports stream mode */ + if (num == 1 && !opdata[0]->has_next) { + cookies[0]->tag.long_data_len = ctxt->io_bytes; + ctxt->io_bytes = 0; + } + + ret = wd_burst_send(ctxt->q, (void **)req, num); + if (unlikely(ret)) { + WD_ERR("failed to send req %d!\n", ret); + goto fail_with_cookies; + } + + if (tag) + return ret; + + ret = digest_recv_sync(ctxt, opdata, num); + +fail_with_cookies: + wd_put_cookies(&ctxt->pool, (void **)cookies, num); + return ret; +} + +int wcrypto_do_digest(void *ctx, struct wcrypto_digest_op_data *opdata, + void *tag) +{ + int ret; + + if (!tag) { + ret = wcrypto_burst_digest(ctx, &opdata, NULL, 1); + if (likely(ret == 1)) + return GET_NEGATIVE(opdata->status); + if (unlikely(ret == 0)) + return -WD_ETIMEDOUT; + } else { + ret = wcrypto_burst_digest(ctx, &opdata, &tag, 1); + } + + return ret; +} + +int wcrypto_digest_poll(struct wd_queue *q, unsigned int num) +{ + struct wcrypto_digest_msg *digest_resp = NULL; + struct wcrypto_digest_ctx *ctx; + struct wcrypto_digest_tag *tag; + unsigned int tmp = num; + int count = 0; + int ret; + + if (unlikely(!q)) { + WD_ERR("q is NULL!\n"); + return -WD_EINVAL; + } + + do { + digest_resp = NULL; + ret = wd_recv(q, (void **)&digest_resp); + if (ret == 0) + break; + else if (ret == -WD_HW_EACCESS) { + if (!digest_resp) { + WD_ERR("the digest recv err from req_cache!\n"); + return ret; + } + digest_resp->result = WD_HW_EACCESS; + } else if (ret < 0) { + WD_ERR("recv err at digest poll!\n"); + return ret; + } + + count++; + tag = (void *)(uintptr_t)digest_resp->usr_data; + ctx = tag->wcrypto_tag.ctx; + ctx->setup.cb(digest_resp, tag->wcrypto_tag.tag); + wd_put_cookies(&ctx->pool, (void **)&tag, 1); + } while (--tmp); + + return count; +} + +void wcrypto_del_digest_ctx(void *ctx) +{ + struct q_info *qinfo; + struct wcrypto_digest_ctx *d_ctx; + + if (!ctx) { + WD_ERR("Delete digest ctx is NULL!\n"); + return; + } + d_ctx = ctx; + qinfo = d_ctx->q->qinfo; + wd_uninit_cookie_pool(&d_ctx->pool); + wd_spinlock(&qinfo->qlock); + if (qinfo->ctx_num <= 0) { + wd_unspinlock(&qinfo->qlock); + WD_ERR("error: repeat del digest ctx!\n"); + return; + } + wd_free_id(qinfo->ctx_id, WD_MAX_CTX_NUM, d_ctx->ctx_id - 1, + WD_MAX_CTX_NUM); + if (!(--qinfo->ctx_num)) + memset(&qinfo->br, 0, sizeof(qinfo->br)); + wd_unspinlock(&qinfo->qlock); + del_ctx_key(d_ctx); + free(ctx); +} diff --git a/uadk/v1/wd_digest.h b/uadk/v1/wd_digest.h new file mode 100644 index 0000000..6ad4c85 --- /dev/null +++ b/uadk/v1/wd_digest.h @@ -0,0 +1,168 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#ifndef __WD_DIGEST_H +#define __WD_DIGEST_H + +#include +#include +#include +#include "wd.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum wcrypto_digest_alg { + WCRYPTO_SM3, + WCRYPTO_MD5, + WCRYPTO_SHA1, + WCRYPTO_SHA256, + WCRYPTO_SHA224, + WCRYPTO_SHA384, + WCRYPTO_SHA512, + WCRYPTO_SHA512_224, + WCRYPTO_SHA512_256, + WCRYPTO_MAX_DIGEST_TYPE, +}; + +enum wd_digest_mac_len { + WCRYPTO_DIGEST_SM3_LEN = 32, + WCRYPTO_DIGEST_MD5_LEN = 16, + WCRYPTO_DIGEST_SHA1_LEN = 20, + WCRYPTO_DIGEST_SHA256_LEN = 32, + WCRYPTO_DIGEST_SHA224_LEN = 28, + WCRYPTO_DIGEST_SHA384_LEN = 48, + WCRYPTO_DIGEST_SHA512_LEN = 64, + WCRYPTO_DIGEST_SHA512_224_LEN = 28, + WCRYPTO_DIGEST_SHA512_256_LEN = 32 +}; + +enum wcrypto_digest_mode { + WCRYPTO_DIGEST_NORMAL, + WCRYPTO_DIGEST_HMAC, +}; + +/** + * different contexts for different users/threads + * @cb: call back functions of user + * @alg: digest algorithm type; denoted by enum wcrypto_digest_alg + * @mode:digest algorithm mode; denoted by enum wcrypto_digest_mode + * @br: memory from user, it is given at ctx creating + * @data_fmt: data format, denoted by enum wcrypto_buff_type + */ +struct wcrypto_digest_ctx_setup { + wcrypto_cb cb; + enum wcrypto_digest_alg alg; + enum wcrypto_digest_mode mode; + struct wd_mm_br br; + __u16 data_fmt; +}; + +/** + * operational data per I/O operation + * @in: input data address + * @out:output data address + * @in_bytes: input data size + * @out_bytes:output data size + * @priv:reserved data field segment + * @status:I/O operation return status + * @has_next: is there next data block + */ +struct wcrypto_digest_op_data { + void *in; + void *out; + __u32 in_bytes; + __u32 out_bytes; + void *priv; + int status; + bool has_next; +}; + +/* Digest message format of Warpdrive */ +struct wcrypto_digest_msg { + __u8 alg_type; /* Denoted by enum wcrypto_type */ + __u8 alg:4; /* Denoted by enum wcrypto_digest_alg */ + __u8 has_next:1; /* is there next block data */ + __u8 mode:3; /* Denoted by enum wcrypto_digest_mode */ + __u8 data_fmt; /* Data format, denoted by enum wcrypto_buff_type */ + __u8 result; /* Operation result, denoted by WD error code */ + __u16 key_bytes; /* Key bytes */ + __u16 iv_bytes; /* IV bytes */ + + __u8 *key; /* Input key VA pointer, should be DMA buffer */ + __u8 *iv; /* Input IV VA pointer, should be DMA buffer */ + __u8 *in; /* Input data VA pointer, should be DMA buffer */ + __u8 *out; /* Output data VA pointer, should be DMA buffer */ + __u32 in_bytes; /* Input data bytes */ + __u32 out_bytes; /* Output data bytes */ + __u64 usr_data; /* user identifier: struct wcrypto_cb_tag */ +}; + +/** + * wcrypto_create_digest_ctx() - create a digest context on the wrapdrive queue. + * @q: wrapdrive queue, need requested by user. + * @setup:setup data of user + */ +void *wcrypto_create_digest_ctx(struct wd_queue *q, + struct wcrypto_digest_ctx_setup *setup); + +/** + * wcrypto_set_digest_key() - set auth key to digest context. + * @ctx: digest context, created by wcrypto_create_digest_ctx. + * @key: auth key addr + * @key_len: auth key length + */ +int wcrypto_set_digest_key(void *ctx, __u8 *key, __u16 key_len); + +/** + * wcrypto_do_digest() - syn/asynchronous digest operation + * @ctx: context of user, created by wcrypto_create_digest_ctx. + * @opdata: operational data + * @tag: asynchronous:user_tag; synchronous:NULL. + */ +int wcrypto_do_digest(void *ctx, struct wcrypto_digest_op_data *opdata, + void *tag); + +/** + * wcrypto_digest_poll() - poll operation for asynchronous operation + * @q:wrapdrive queue + * @num:how many respondences this poll has to get, 0 means get all finishings + */ +int wcrypto_digest_poll(struct wd_queue *q, unsigned int num); + +/** + * wcrypto_del_digest_ctx() - free digest context + * @ctx: the context to be free + */ +void wcrypto_del_digest_ctx(void *ctx); + +/** + * wcrypto_burst_digest() - (a)synchronous multiple digest operations + * @d_ctx: context of user, created by wcrypto_create_digest_ctx. + * @opdata: operational data + * @tag: asynchronous:user_tag; synchronous:NULL. + * @num: operations number per calling, maximum number is WCRYPTO_MAX_BURST_NUM. + */ +int wcrypto_burst_digest(void *d_ctx, struct wcrypto_digest_op_data **opdata, + void **tag, __u32 num); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/uadk/v1/wd_ecc.c b/uadk/v1/wd_ecc.c new file mode 100644 index 0000000..e108051 --- /dev/null +++ b/uadk/v1/wd_ecc.c @@ -0,0 +1,2493 @@ +/* + * Copyright 2020 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include + +#include +#include + +#include "wd.h" +#include "wd_util.h" +#include "internal/wd_ecc_curve.h" +#include "wd_ecc.h" + +#define ECC_BALANCE_THRHD 1280 +#define ECC_RECV_MAX_CNT 60000000 +#define ECC_RESEND_CNT 8 +#define BYTES_TO_BITS(bytes) ((bytes) << 3) +#define ECC_MAX_KEY_BITS 521 +#define ECC_MAX_KEY_SIZE BITS_TO_BYTES(ECC_MAX_KEY_BITS) +#define ECC_MAX_IN_NUM 4 +#define ECC_MAX_OUT_NUM 4 +#define CURVE_PARAM_NUM 6 +#define ECC_POINT_NUM 2 +#define WD_ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) +#define MAX_CURVE_SIZE (ECC_MAX_KEY_SIZE * CURVE_PARAM_NUM) +#define MAX_HASH_LENS ECC_MAX_KEY_SIZE +#define SM2_KEY_SIZE 32 + +#define CURVE_X25519 0x1 +#define CURVE_X448 0x2 +#define CURVE_SM2P256 0x3 + +static __thread int balance; + +struct curve_param_desc { + __u32 type; + __u32 prk_offset; + __u32 pbk_offset; +}; + +enum wcrypto_ecc_curve_param_type { + ECC_CURVE_P, + ECC_CURVE_A, + ECC_CURVE_B, + ECC_CURVE_N, + ECC_CURVE_G +}; + +struct wcrypto_ecc_cookie { + struct wcrypto_cb_tag tag; + struct wcrypto_ecc_msg msg; +}; + +struct wcrypto_ecc_ctx { + struct wd_cookie_pool pool; + __u32 key_size; + unsigned long ctx_id; + struct wd_queue *q; + struct wcrypto_ecc_key key; + struct wcrypto_ecc_ctx_setup setup; +}; + +struct wcrypto_ecc_curve_list { + __u32 id; + char *name; + __u32 key_bits; + __u8 data[MAX_CURVE_SIZE]; +}; + +static const struct wcrypto_ecc_curve_list g_curve_list[] = { + { + .id = CURVE_X25519, + .name = "x25519", + .key_bits = 256, + .data = X25519_256_PARAM, + }, { + .id = CURVE_X448, + .name = "x448", + .key_bits = 448, + .data = X448_448_PARAM, + }, { + .id = WCRYPTO_SECP128R1, + .name = "secp128r1", + .key_bits = 128, + .data = SECG_P128_R1_PARAM, + }, { + .id = WCRYPTO_SECP192K1, + .name = "secp192k1", + .key_bits = 192, + .data = SECG_P192_K1_PARAM, + }, { + .id = WCRYPTO_SECP256K1, + .name = "secp256k1", + .key_bits = 256, + .data = SECG_P256_K1_PARAM, + }, { + .id = WCRYPTO_BRAINPOOLP320R1, + .name = "bpP320r1", + .key_bits = 320, + .data = BRAINPOOL_P320_R1_PARAM, + }, { + .id = WCRYPTO_BRAINPOOLP384R1, + .name = "bpP384r1", + .key_bits = 384, + .data = BRAINPOOL_P384_R1_PARAM, + }, { + .id = WCRYPTO_SECP521R1, + .name = "secp521r1", + .key_bits = 521, + .data = NIST_P521_R1_PARAM, + }, { + .id = CURVE_SM2P256, + .name = "sm2", + .key_bits = 256, + .data = SM2_P256_V1_PARAM, + } +}; + +static const struct curve_param_desc g_cv_param_list[] = { + { + .type = ECC_CURVE_P, + .prk_offset = (__u32)offsetof(struct wcrypto_ecc_prikey, p), + .pbk_offset = (__u32)offsetof(struct wcrypto_ecc_pubkey, p), + }, { + .type = ECC_CURVE_A, + .prk_offset = (__u32)offsetof(struct wcrypto_ecc_prikey, a), + .pbk_offset = (__u32)offsetof(struct wcrypto_ecc_pubkey, a), + }, { + .type = ECC_CURVE_B, + .prk_offset = (__u32)offsetof(struct wcrypto_ecc_prikey, b), + .pbk_offset = (__u32)offsetof(struct wcrypto_ecc_pubkey, b), + }, { + .type = ECC_CURVE_N, + .prk_offset = (__u32)offsetof(struct wcrypto_ecc_prikey, n), + .pbk_offset = (__u32)offsetof(struct wcrypto_ecc_pubkey, n), + }, { + .type = ECC_CURVE_G, + .prk_offset = (__u32)offsetof(struct wcrypto_ecc_prikey, g), + .pbk_offset = (__u32)offsetof(struct wcrypto_ecc_pubkey, g), + } +}; + +static int trans_to_binpad(char *dst, const char *src, + __u32 b_size, __u32 d_size, const char *p_name) +{ + int i = d_size - 1; + int j; + + if (!dst || !src || !b_size || !d_size || b_size < d_size) { + WD_ERR("%s: trans to binpad parameters err!\n", p_name); + return -WD_EINVAL; + } + + if (dst == src) + return WD_SUCCESS; + + for (j = b_size - 1; j >= 0; j--, i--) { + if (i >= 0) + dst[j] = src[i]; + else + dst[j] = 0; + } + + return WD_SUCCESS; +} + +static void wd_memset_zero(void *data, __u32 mem_size) +{ + __u32 size = mem_size; + char *s = data; + + if (unlikely(!s)) + return; + + while (size--) + *s++ = 0; +} + +static void *br_alloc(struct wd_mm_br *br, __u64 size) +{ + if (unlikely(!br->alloc)) { + WD_ERR("br alloc NULL!\n"); + return NULL; + } + + if (br->get_bufsize && br->get_bufsize(br->usr) < size) { + WD_ERR("Blk_size < need_size<0x%llx>.\n", size); + return NULL; + } + + return br->alloc(br->usr, size); +} + +static void br_free(struct wd_mm_br *br, void *va) +{ + if (!br->free) { + WD_ERR("br free NULL!\n"); + return; + } + + return br->free(br->usr, va); +} + +static __u32 get_hw_keysize(__u32 ksz) +{ + __u32 size = 0; + + if (ksz <= BITS_TO_BYTES(256)) + size = BITS_TO_BYTES(256); + else if (ksz <= BITS_TO_BYTES(384)) + size = BITS_TO_BYTES(384); + else if (ksz <= BITS_TO_BYTES(576)) + size = BITS_TO_BYTES(576); + else + WD_ERR("failed to get hw keysize : ksz = %u.\n", ksz); + + return size; +} + +static __u32 get_hash_bytes(__u8 type) +{ + __u32 val = 0; + + switch (type) { + case WCRYPTO_HASH_MD4: + case WCRYPTO_HASH_MD5: + val = BITS_TO_BYTES(128); + break; + case WCRYPTO_HASH_SHA1: + val = BITS_TO_BYTES(160); + break; + case WCRYPTO_HASH_SHA224: + val = BITS_TO_BYTES(224); + break; + case WCRYPTO_HASH_SHA256: + case WCRYPTO_HASH_SM3: + val = BITS_TO_BYTES(256); + break; + case WCRYPTO_HASH_SHA384: + val = BITS_TO_BYTES(384); + break; + case WCRYPTO_HASH_SHA512: + val = BITS_TO_BYTES(512); + break; + default: + break; + } + + return val; +} + +static void init_dtb_param(void *dtb, char *start, + __u32 dsz, __u32 bsz, __u32 num) +{ + struct wd_dtb *tmp = dtb; + char *pos = start; + int i = 0; + + while (i++ < num) { + tmp->data = pos; + tmp->dsize = dsz; + tmp->bsize = bsz; + tmp += 1; + pos += bsz; + } +} + +static void init_ecc_prikey(struct wcrypto_ecc_prikey *prikey, + __u32 ksz, __u32 bsz) +{ + init_dtb_param(prikey, prikey->data, ksz, bsz, ECC_PRIKEY_PARAM_NUM); +} + +static void init_ecc_pubkey(struct wcrypto_ecc_pubkey *pubkey, + __u32 ksz, __u32 bsz) +{ + init_dtb_param(pubkey, pubkey->data, ksz, bsz, ECC_PUBKEY_PARAM_NUM); +} + +static void release_ecc_prikey(struct wcrypto_ecc_ctx *ctx) +{ + struct wcrypto_ecc_prikey *prikey = ctx->key.prikey; + struct wd_mm_br *br = &ctx->setup.br; + + wd_memset_zero(prikey->data, prikey->size); + br_free(br, prikey->data); + free(prikey); + ctx->key.prikey = NULL; +} + +static void release_ecc_pubkey(struct wcrypto_ecc_ctx *ctx) +{ + struct wcrypto_ecc_pubkey *pubkey = ctx->key.pubkey; + struct wd_mm_br *br = &ctx->setup.br; + + br_free(br, pubkey->data); + free(pubkey); + ctx->key.pubkey = NULL; +} + +static struct wcrypto_ecc_prikey *create_ecc_prikey(struct wcrypto_ecc_ctx *ctx) +{ + struct wd_mm_br *br = &ctx->setup.br; + struct wcrypto_ecc_prikey *prikey; + __u32 hsz, dsz; + void *data; + + hsz = get_hw_keysize(ctx->key_size); + prikey = malloc(sizeof(struct wcrypto_ecc_prikey)); + if (unlikely(!prikey)) { + WD_ERR("failed to malloc!\n"); + return NULL; + } + + memset(prikey, 0, sizeof(struct wcrypto_ecc_prikey)); + dsz = ECC_PRIKEY_SZ(hsz); + data = br_alloc(br, dsz); + if (unlikely(!data)) { + WD_ERR("failed to br alloc, sz = %u!\n", dsz); + free(prikey); + return NULL; + } + + memset(data, 0, dsz); + prikey->size = dsz; + prikey->data = data; + init_ecc_prikey(prikey, ctx->key_size, hsz); + + return prikey; +} + +static struct wcrypto_ecc_pubkey *create_ecc_pubkey(struct wcrypto_ecc_ctx *ctx) +{ + struct wd_mm_br *br = &ctx->setup.br; + struct wcrypto_ecc_pubkey *pubkey; + __u32 hsz, dsz; + void *data; + + hsz = get_hw_keysize(ctx->key_size); + pubkey = malloc(sizeof(struct wcrypto_ecc_pubkey)); + if (unlikely(!pubkey)) { + WD_ERR("failed to malloc!\n"); + return NULL; + } + + memset(pubkey, 0, sizeof(struct wcrypto_ecc_pubkey)); + dsz = ECC_PUBKEY_SZ(hsz); + data = br_alloc(br, dsz); + if (unlikely(!data)) { + WD_ERR("failed to br alloc, sz = %u!\n", dsz); + free(pubkey); + return NULL; + } + + memset(data, 0, dsz); + pubkey->size = dsz; + pubkey->data = data; + init_ecc_pubkey(pubkey, ctx->key_size, hsz); + + return pubkey; +} + +static void release_ecc_in(struct wcrypto_ecc_ctx *ctx, + struct wcrypto_ecc_in *ecc_in) +{ + struct wd_mm_br *br = &ctx->setup.br; + + wd_memset_zero(ecc_in->data, ecc_in->size); + br_free(br, ecc_in); +} + +static struct wcrypto_ecc_in *create_ecc_in(struct wcrypto_ecc_ctx *ctx, + __u32 num) +{ + struct wd_mm_br *br = &ctx->setup.br; + struct wcrypto_ecc_in *in; + __u32 hsz, len; + + if (unlikely(!ctx->key_size || ctx->key_size > ECC_MAX_KEY_SIZE)) { + WD_ERR("ctx key size %u error!\n", ctx->key_size); + return NULL; + } + + hsz = get_hw_keysize(ctx->key_size); + len = sizeof(struct wcrypto_ecc_in) + hsz * num; + in = br_alloc(br, len); + if (unlikely(!in)) { + WD_ERR("failed to br alloc, sz = %u!\n", len); + return NULL; + } + + memset(in, 0, len); + in->size = hsz * num; + init_dtb_param(in, in->data, ctx->key_size, hsz, num); + + return in; +} + +static struct wcrypto_ecc_in *create_sm2_sign_in(struct wcrypto_ecc_ctx *ctx, + __u32 m_len) +{ + struct wd_mm_br *br = &ctx->setup.br; + struct wd_dtb *dgst, *k, *plaintext; + struct wcrypto_ecc_in *in; + __u32 hsz; + __u64 len; + + if (unlikely(!ctx->key_size || ctx->key_size > ECC_MAX_KEY_SIZE)) { + WD_ERR("ctx key size %u error!\n", ctx->key_size); + return NULL; + } + + hsz = get_hw_keysize(ctx->key_size); + len = sizeof(struct wcrypto_ecc_in) + + ECC_SIGN_IN_PARAM_NUM * hsz + (__u64)m_len; + in = br_alloc(br, len); + if (unlikely(!in)) { + WD_ERR("failed to br alloc, sz = %llu!\n", len); + return NULL; + } + + in->size = len - sizeof(struct wcrypto_ecc_in); + dgst = (void *)in; + dgst->data = in->data; + dgst->dsize = ctx->key_size; + dgst->bsize = hsz; + + k = dgst + 1; + k->data = dgst->data + hsz; + k->dsize = ctx->key_size; + k->bsize = hsz; + + plaintext = k + 1; + plaintext->data = k->data + hsz; + plaintext->dsize = m_len; + plaintext->bsize = m_len; + + return in; +} + +static struct wcrypto_ecc_in *create_sm2_enc_in(struct wcrypto_ecc_ctx *ctx, + __u32 m_len) +{ + struct wd_mm_br *br = &ctx->setup.br; + struct wd_dtb *k, *plaintext; + struct wcrypto_ecc_in *in; + __u32 ksz = ctx->key_size; + __u64 len; + + if (unlikely(!ksz || ksz > ECC_MAX_KEY_SIZE)) { + WD_ERR("ctx key size %u error!\n", ksz); + return NULL; + } + + len = sizeof(struct wcrypto_ecc_in) + ksz + m_len; + in = br_alloc(br, len); + if (unlikely(!in)) { + WD_ERR("failed to br alloc, sz = %llu!\n", len); + return NULL; + } + + in->size = ksz + m_len; + k = (void *)in; + k->data = in->data; + k->dsize = ksz; + k->bsize = ksz; + + plaintext = k + 1; + plaintext->data = k->data + ksz; + plaintext->dsize = m_len; + plaintext->bsize = m_len; + + return in; +} + +static void *create_sm2_ciphertext(struct wcrypto_ecc_ctx *ctx, __u32 m_len, + __u64 *len, __u32 st_sz) +{ + struct wcrypto_hash_mt *hash = &ctx->setup.hash; + struct wcrypto_ecc_point *c1; + __u32 ksz = ctx->key_size; + struct wd_dtb *c3, *c2; + __u32 h_byts; + void *start; + + if (unlikely(!ksz || ksz > ECC_MAX_KEY_SIZE)) { + WD_ERR("ctx key size %u error!\n", ksz); + return NULL; + } + + h_byts = get_hash_bytes(hash->type); + if (!h_byts) { + WD_ERR("failed to get hash bytes, type = %u!\n", hash->type); + return NULL; + } + + *len = (__u64)st_sz + ECC_POINT_PARAM_NUM * (__u64)ctx->key_size + + (__u64)m_len + (__u64)h_byts; + start = br_alloc(&ctx->setup.br, *len); + if (unlikely(!start)) { + WD_ERR("failed to br alloc, sz = %llu!\n", *len); + return NULL; + } + + c1 = (struct wcrypto_ecc_point *)start; + c1->x.data = start + st_sz; + c1->x.dsize = ksz; + c1->x.bsize = ksz; + c1->y.data = c1->x.data + ksz; + c1->y.dsize = ksz; + c1->y.bsize = ksz; + + c2 = (struct wd_dtb *)(c1 + 1); + c2->data = c1->y.data + ksz; + c2->dsize = m_len; + c2->bsize = m_len; + + c3 = c2 + 1; + c3->data = c2->data + m_len; + c3->dsize = h_byts; + c3->bsize = h_byts; + + return start; +} + +static struct wcrypto_ecc_in *create_ecc_sign_in(struct wcrypto_ecc_ctx *ctx, + __u32 m_len, __u8 is_dgst) +{ + if (is_dgst) + return create_ecc_in(ctx, ECC_SIGN_IN_PARAM_NUM); + return create_sm2_sign_in(ctx, m_len); +} + +static struct wcrypto_ecc_out *create_ecc_out(struct wcrypto_ecc_ctx *ctx, + __u32 num) +{ + struct wd_mm_br *br = &ctx->setup.br; + struct wcrypto_ecc_out *out; + __u32 hsz, len; + + if (!ctx->key_size || ctx->key_size > ECC_MAX_KEY_SIZE) { + WD_ERR("ctx key size %u error!\n", ctx->key_size); + return NULL; + } + + hsz = get_hw_keysize(ctx->key_size); + len = sizeof(struct wcrypto_ecc_out) + hsz * num; + out = br_alloc(br, len); + if (unlikely(!out)) { + WD_ERR("failed to br alloc, sz = %u!\n", len); + return NULL; + } + + memset(out, 0, len); + out->size = hsz * num; + init_dtb_param(out, out->data, ctx->key_size, hsz, num); + + return out; +} + +static struct wcrypto_ecc_curve *create_ecc_curve(struct wcrypto_ecc_ctx *ctx) +{ + struct wcrypto_ecc_curve *cv; + __u32 ksize, len; + + ksize = ctx->key_size; + len = sizeof(*cv) + ksize * CURVE_PARAM_NUM; + cv = malloc(len); + if (unlikely(!cv)) { + WD_ERR("failed to malloc!\n"); + return NULL; + } + + init_dtb_param(cv, (void *)(cv + 1), ksize, ksize, CURVE_PARAM_NUM); + + return cv; +} + +static struct wcrypto_ecc_point *create_ecc_pub(struct wcrypto_ecc_ctx *ctx) +{ + struct wcrypto_ecc_point *pub; + __u32 ksize, len; + + ksize = ctx->key_size; + len = sizeof(*pub) + ksize * ECC_POINT_NUM; + pub = malloc(len); + if (unlikely(!pub)) { + WD_ERR("failed to malloc!\n"); + return NULL; + } + + init_dtb_param(pub, (void *)(pub + 1), ksize, ksize, ECC_POINT_NUM); + + return pub; +} + +static struct wd_dtb *create_ecc_d(struct wcrypto_ecc_ctx *ctx) +{ + struct wd_dtb *d; + __u32 ksize, len; + + ksize = ctx->key_size; + len = sizeof(*d) + ksize; + d = malloc(len); + if (unlikely(!d)) { + WD_ERR("failed to malloc!\n"); + return NULL; + } + + memset(d, 0, len); + init_dtb_param(d, (void *)(d + 1), ksize, ksize, 1); + + return d; +} + +static void release_ecc_curve(struct wcrypto_ecc_ctx *ctx) +{ + free(ctx->key.cv); + ctx->key.cv = NULL; +} + +static void release_ecc_pub(struct wcrypto_ecc_ctx *ctx) +{ + free(ctx->key.pub); + ctx->key.pub = NULL; +} + +static void release_ecc_d(struct wcrypto_ecc_ctx *ctx) +{ + wd_memset_zero(ctx->key.d + 1, ctx->key_size); + free(ctx->key.d); + ctx->key.d = NULL; +} + +static int set_param_single(struct wd_dtb *dst, const struct wd_dtb *src, + const char *p_name) +{ + if (unlikely(!src || !src->data)) { + WD_ERR("%s: src or data NULL!\n", p_name); + return -WD_EINVAL; + } + + if (unlikely(!src->dsize || src->dsize > dst->dsize)) { + WD_ERR("%s: src dsz = %u error, dst dsz = %u!\n", + p_name, src->dsize, dst->dsize); + return -WD_EINVAL; + } + + dst->dsize = src->dsize; + memset(dst->data, 0, dst->bsize); + memcpy(dst->data, src->data, src->dsize); + + return 0; +} + +struct wcrypto_ecc_in *wcrypto_new_ecxdh_in(void *ctx, + struct wcrypto_ecc_point *in) +{ + struct wcrypto_ecc_ctx *cx = ctx; + struct wcrypto_ecc_dh_in *dh_in; + struct wcrypto_ecc_in *ecc_in; + int ret; + + if (unlikely(!cx || !in)) { + WD_ERR("new ecc dh in parameter error!\n"); + return NULL; + } + + ecc_in = create_ecc_in(cx, ECDH_IN_PARAM_NUM); + if (unlikely(!ecc_in)) { + WD_ERR("failed to create ecc in!\n"); + return NULL; + } + + dh_in = &ecc_in->param.dh_in; + ret = set_param_single(&dh_in->pbk.x, &in->x, "ecdh in x"); + if (unlikely(ret)) { + release_ecc_in(ctx, ecc_in); + return NULL; + } + + ret = set_param_single(&dh_in->pbk.y, &in->y, "ecdh in y"); + if (unlikely(ret)) { + release_ecc_in(ctx, ecc_in); + return NULL; + } + + return ecc_in; +} + +struct wcrypto_ecc_out *wcrypto_new_ecxdh_out(void *ctx) +{ + struct wcrypto_ecc_out *ecc_out; + + if (unlikely(!ctx)) { + WD_ERR("new ecc dh out ctx NULL!\n"); + return NULL; + } + + ecc_out = create_ecc_out(ctx, ECDH_OUT_PARAM_NUM); + if (unlikely(!ecc_out)) + WD_ERR("failed to create ecc out!\n"); + + return ecc_out; +} + +int wcrypto_get_ecc_key_bits(const void *ctx) +{ + if (unlikely(!ctx)) { + WD_ERR("get ecc key bits, ctx NULL!\n"); + return -WD_EINVAL; + } + + return ((struct wcrypto_ecc_ctx *)ctx)->setup.key_bits; +} + +static int set_curve_param_single(struct wcrypto_ecc_key *key, + const struct wd_dtb *param, + __u32 type) +{ + struct wcrypto_ecc_prikey *prk = key->prikey; + struct wcrypto_ecc_pubkey *pbk = key->pubkey; + struct wd_dtb *t1, *t2; + int ret; + + t1 = (struct wd_dtb *)((char *)prk + g_cv_param_list[type].prk_offset); + t2 = (struct wd_dtb *)((char *)pbk + g_cv_param_list[type].pbk_offset); + + /* set gy */ + if (type == ECC_CURVE_G) { + ret = set_param_single(t1 + 1, param + 1, "set cv"); + if (unlikely(ret)) + return ret; + + ret = set_param_single(t2 + 1, param + 1, "set cv"); + if (unlikely(ret)) + return ret; + } + + ret = set_param_single(t1, param, "set cv"); + if (unlikely(ret)) + return ret; + + return set_param_single(t2, param, "set cv"); +} + +static int set_curve_param(struct wcrypto_ecc_key *key, + const struct wcrypto_ecc_curve *param) +{ + int ret; + + ret = set_curve_param_single(key, ¶m->p, ECC_CURVE_P); + if (unlikely(ret)) { + WD_ERR("failed to set curve param: p error!\n"); + return -WD_EINVAL; + } + + ret = set_curve_param_single(key, ¶m->a, ECC_CURVE_A); + if (unlikely(ret)) { + WD_ERR("failed to set curve param: a error!\n"); + return -WD_EINVAL; + } + + ret = set_curve_param_single(key, ¶m->b, ECC_CURVE_B); + if (unlikely(ret)) { + WD_ERR("failed to set curve param: b error!\n"); + return -WD_EINVAL; + } + + ret = set_curve_param_single(key, ¶m->n, ECC_CURVE_N); + if (unlikely(ret)) { + WD_ERR("failed to set curve param: n error!\n"); + return -WD_EINVAL; + } + + ret = set_curve_param_single(key, (void *)¶m->g, ECC_CURVE_G); + if (unlikely(ret)) { + WD_ERR("failed to set curve param: g error!\n"); + return -WD_EINVAL; + } + + return 0; +} + +static const struct wcrypto_ecc_curve_list *find_curve_list(__u32 id) +{ + int len = WD_ARRAY_SIZE(g_curve_list); + int i = 0; + + while (i < len) { + if (g_curve_list[i].id == id) + return &g_curve_list[i]; + i++; + } + + return NULL; +} + +static int fill_param_by_id(struct wcrypto_ecc_curve *c, + __u16 key_bits, __u32 id) +{ + const struct wcrypto_ecc_curve_list *item; + __u32 key_size; + + item = find_curve_list(id); + if (unlikely(!item)) { + WD_ERR("failed to find curve id %u!\n", id); + return -WD_EINVAL; + } + + if (unlikely(item->key_bits != key_bits)) { + WD_ERR("curve %u and key bits %hu not match!\n", id, key_bits); + return -WD_EINVAL; + } + + key_size = BITS_TO_BYTES(item->key_bits); + memcpy(c->p.data, item->data, CURVE_PARAM_NUM * key_size); + + return 0; +} + +static int set_key_cv(struct wcrypto_ecc_curve *dst, + struct wcrypto_ecc_curve *src) +{ + int ret; + + if (unlikely(!src)) { + WD_ERR("set key cv: input parameter NULL!\n"); + return -WD_EINVAL; + } + + ret = set_param_single(&dst->p, &src->p, "cv p"); + if (unlikely(ret)) + return ret; + + ret = set_param_single(&dst->a, &src->a, "cv a"); + if (unlikely(ret)) + return ret; + + ret = set_param_single(&dst->b, &src->b, "cv b"); + if (unlikely(ret)) + return ret; + + ret = set_param_single(&dst->g.x, &src->g.x, "cv gx"); + if (unlikely(ret)) + return ret; + + ret = set_param_single(&dst->g.y, &src->g.y, "cv gy"); + if (unlikely(ret)) + return ret; + + return set_param_single(&dst->n, &src->n, "cv n"); +} + +static int fill_user_curve_cfg(struct wcrypto_ecc_curve *param, + struct wcrypto_ecc_ctx_setup *setup, + const char *alg) +{ + struct wcrypto_ecc_curve *src_param = setup->cv.cfg.pparam; + __u32 curve_id; + int ret = 0; + + if (setup->cv.type == WCRYPTO_CV_CFG_ID) { + curve_id = setup->cv.cfg.id; + ret = fill_param_by_id(param, setup->key_bits, curve_id); + dbg("set curve id %u\n", curve_id); + } else if (setup->cv.type == WCRYPTO_CV_CFG_PARAM) { + ret = set_key_cv(param, src_param); + if (unlikely(ret)) { + WD_ERR("failed to set key cv!\n"); + return ret; + } + dbg("set curve by user param\n"); + } else { + WD_ERR("fill curve cfg:type %u error!\n", setup->cv.type); + return -WD_EINVAL; + } + + if (unlikely(!param->p.dsize || + param->p.dsize > BITS_TO_BYTES(setup->key_bits))) { + WD_ERR("fill curve cfg:dsize %u error!\n", param->p.dsize); + return -WD_EINVAL; + } + + return ret; +} + +static int create_ctx_key(struct wcrypto_ecc_ctx_setup *setup, + struct wcrypto_ecc_ctx *ctx) +{ + int ret = -WD_ENOMEM; + + ctx->key.prikey = create_ecc_prikey(ctx); + if (unlikely(!ctx->key.prikey)) + return -WD_ENOMEM; + + ctx->key.pubkey = create_ecc_pubkey(ctx); + if (unlikely(!ctx->key.pubkey)) + goto free_prikey; + + ctx->key.cv = create_ecc_curve(ctx); + if (unlikely(!ctx->key.cv)) + goto free_pubkey; + + ctx->key.pub = create_ecc_pub(ctx); + if (unlikely(!ctx->key.pub)) + goto free_curve; + + ctx->key.d = create_ecc_d(ctx); + if (unlikely(!ctx->key.d)) + goto free_pub; + + ret = fill_user_curve_cfg(ctx->key.cv, setup, ctx->q->capa.alg); + if (unlikely(ret)) { + WD_ERR("failed to fill user curve cfg!\n"); + goto free_d; + } + + ret = set_curve_param(&ctx->key, ctx->key.cv); + if (unlikely(ret)) { + WD_ERR("failed to set curve parameter!\n"); + goto free_d; + } + + return 0; + +free_d: + release_ecc_d(ctx); + +free_pub: + release_ecc_pub(ctx); + +free_curve: + release_ecc_curve(ctx); + +free_pubkey: + release_ecc_pubkey(ctx); + +free_prikey: + release_ecc_prikey(ctx); + + return ret; +} + +static void setup_curve_cfg(struct wcrypto_ecc_ctx_setup *setup, + const char *alg) +{ + if (!strcmp(alg, "x25519")) { + setup->key_bits = 256; /* x25519 fixed key width */ + setup->cv.type = WCRYPTO_CV_CFG_ID; + setup->cv.cfg.id = CURVE_X25519; + } else if (!strcmp(alg, "x448")) { + setup->key_bits = 448; /* x448 fixed key width */ + setup->cv.type = WCRYPTO_CV_CFG_ID; + setup->cv.cfg.id = CURVE_X448; + } else if ((!strcmp(alg, "sm2"))) { + setup->key_bits = 256; + setup->cv.type = WCRYPTO_CV_CFG_ID; + setup->cv.cfg.id = CURVE_SM2P256; + } +} + +static bool is_alg_support(const char *alg) +{ + if (unlikely(strcmp(alg, "ecdh") && + strcmp(alg, "ecdsa") && + strcmp(alg, "x25519") && + strcmp(alg, "x448") && + strcmp(alg, "sm2"))) + return false; + + return true; +} + +static bool is_key_width_support(__u32 key_bits) +{ + /* key bit width check */ + if (unlikely(key_bits != 128 && + key_bits != 192 && + key_bits != 256 && + key_bits != 320 && + key_bits != 384 && + key_bits != 448 && + key_bits != 521)) + return false; + + return true; +} + +static int param_check(struct wd_queue *q, struct wcrypto_ecc_ctx_setup *setup) +{ + if (unlikely(!q || !setup)) { + WD_ERR("input parameter error!\n"); + return -WD_EINVAL; + } + + if (unlikely(!setup->br.alloc || !setup->br.free)) { + WD_ERR("user mm br error!\n"); + return -WD_EINVAL; + } + + if (unlikely(!is_alg_support(q->capa.alg))) { + WD_ERR("alg %s mismatching!\n", q->capa.alg); + return -WD_EINVAL; + } + + setup_curve_cfg(setup, q->capa.alg); + + if (unlikely(!is_key_width_support(setup->key_bits))) { + WD_ERR("key_bits %u error!\n", setup->key_bits); + return -WD_EINVAL; + } + + return 0; +} + +static void del_ctx_key(struct wd_mm_br *br, + struct wcrypto_ecc_ctx *ctx) +{ + if (unlikely(!br->free)) + return; + + if (ctx->key.prikey) { + wd_memset_zero(ctx->key.prikey->data, ctx->key.prikey->size); + br->free(br->usr, ctx->key.prikey->data); + free(ctx->key.prikey); + ctx->key.prikey = NULL; + } + + if (ctx->key.pubkey) { + br->free(br->usr, ctx->key.pubkey->data); + free(ctx->key.pubkey); + ctx->key.pubkey = NULL; + } + + if (ctx->key.cv) + free(ctx->key.cv); + + if (ctx->key.pub) + free(ctx->key.pub); + + if (ctx->key.d) { + wd_memset_zero(ctx->key.d + 1, ctx->key_size); + free(ctx->key.d); + } +} + +static void init_ctx_cookies(struct wcrypto_ecc_ctx *ctx, + struct wcrypto_ecc_ctx_setup *setup) +{ + __u32 hsz = get_hw_keysize(ctx->key_size); + struct q_info *qinfo = ctx->q->qinfo; + struct wcrypto_ecc_cookie *cookie; + int i; + + for (i = 0; i < ctx->pool.cookies_num; i++) { + cookie = (void *)((uintptr_t)ctx->pool.cookies + + i * ctx->pool.cookies_size); + cookie->msg.curve_id = setup->cv.cfg.id; + cookie->msg.data_fmt = setup->data_fmt; + cookie->msg.key_bytes = hsz; + cookie->msg.hash_type = setup->hash.type; + cookie->msg.alg_type = qinfo->atype; + cookie->tag.ctx = ctx; + cookie->tag.ctx_id = ctx->ctx_id; + cookie->msg.usr_data = (uintptr_t)&cookie->tag; + } +} + +static int setup_qinfo(struct wcrypto_ecc_ctx_setup *setup, + struct q_info *qinfo, __u32 *ctx_id) +{ + int ret; + + wd_spinlock(&qinfo->qlock); + if (!qinfo->br.alloc && !qinfo->br.iova_map) + memcpy(&qinfo->br, &setup->br, sizeof(setup->br)); + if (qinfo->br.usr != setup->br.usr) { + WD_ERR("Err mm br in creating ecc ctx!\n"); + goto unlock; + } + + if (unlikely(qinfo->ctx_num >= WD_MAX_CTX_NUM)) { + WD_ERR("err:create too many ecc ctx!\n"); + goto unlock; + } + + ret = wd_alloc_id(qinfo->ctx_id, WD_MAX_CTX_NUM, ctx_id, 0, + WD_MAX_CTX_NUM); + if (unlikely(ret)) { + WD_ERR("failed to alloc ctx id!\n"); + goto unlock; + } + qinfo->ctx_num++; + wd_unspinlock(&qinfo->qlock); + + return 0; +unlock: + wd_unspinlock(&qinfo->qlock); + return -WD_EINVAL; +} + +/* Before initiate this context, we should get a queue from WD */ +void *wcrypto_create_ecc_ctx(struct wd_queue *q, + struct wcrypto_ecc_ctx_setup *setup) +{ + struct wcrypto_ecc_ctx *ctx; + struct q_info *qinfo; + __u32 cid = 0; + int ret; + + if (param_check(q, setup)) + return NULL; + + qinfo = q->qinfo; + qinfo->hash = setup->hash; + + ret = setup_qinfo(setup, qinfo, &cid); + if (ret) + return NULL; + + ctx = malloc(sizeof(struct wcrypto_ecc_ctx)); + if (unlikely(!ctx)) { + WD_ERR("failed to malloc!\n"); + goto free_ctx_id; + } + + memset(ctx, 0, sizeof(struct wcrypto_ecc_ctx)); + memcpy(&ctx->setup, setup, sizeof(*setup)); + ctx->key_size = BITS_TO_BYTES(setup->key_bits); + ctx->q = q; + ctx->ctx_id = cid + 1; + ret = wd_init_cookie_pool(&ctx->pool, + sizeof(struct wcrypto_ecc_cookie), WD_HPRE_CTX_MSG_NUM); + if (ret) { + WD_ERR("fail to init cookie pool!\n"); + goto free_ctx; + } + init_ctx_cookies(ctx, setup); + + ret = create_ctx_key(setup, ctx); + if (unlikely(ret)) { + WD_ERR("failed to create ecc ctx keys!\n"); + goto uninit_cookie; + } + + return ctx; + +uninit_cookie: + wd_uninit_cookie_pool(&ctx->pool); +free_ctx: + free(ctx); +free_ctx_id: + wd_spinlock(&qinfo->qlock); + qinfo->ctx_num--; + wd_free_id(qinfo->ctx_id, WD_MAX_CTX_NUM, cid, WD_MAX_CTX_NUM); + wd_unspinlock(&qinfo->qlock); + + return NULL; +} + +void wcrypto_del_ecc_ctx(void *ctx) +{ + struct wcrypto_ecc_ctx *cx; + struct wd_mm_br *br; + struct q_info *qinfo; + + if (unlikely(!ctx)) { + WD_ERR("Delete ecc parameter err!\n"); + return; + } + + cx = ctx; + br = &cx->setup.br; + qinfo = cx->q->qinfo; + wd_uninit_cookie_pool(&cx->pool); + wd_spinlock(&qinfo->qlock); + if (unlikely(qinfo->ctx_num <= 0)) { + WD_ERR("error:repeat del ecc ctx ctx!\n"); + wd_unspinlock(&qinfo->qlock); + return; + } + + wd_free_id(qinfo->ctx_id, WD_MAX_CTX_NUM, cx->ctx_id - 1, + WD_MAX_CTX_NUM); + if (!(--qinfo->ctx_num)) + memset(&qinfo->br, 0, sizeof(qinfo->br)); + wd_unspinlock(&qinfo->qlock); + + del_ctx_key(br, cx); + free(cx); +} + +struct wcrypto_ecc_key *wcrypto_get_ecc_key(void *ctx) +{ + struct wcrypto_ecc_ctx *cx = ctx; + + if (unlikely(!cx)) { + WD_ERR("get ecc key ctx NULL!\n"); + return NULL; + } + + return &cx->key; +} + +int wcrypto_set_ecc_prikey(struct wcrypto_ecc_key *ecc_key, + struct wd_dtb *prikey) +{ + struct wcrypto_ecc_prikey *ecc_prikey; + struct wd_dtb *d; + int ret; + + if (unlikely(!ecc_key || !prikey)) { + WD_ERR("set ecc prikey parameter NULL!\n"); + return -WD_EINVAL; + } + + ecc_prikey = ecc_key->prikey; + d = ecc_key->d; + if (unlikely(!ecc_prikey || !d)) { + WD_ERR("ecc_prikey or d NULL!\n"); + return -WD_EINVAL; + } + + ret = set_param_single(&ecc_prikey->d, prikey, "ecc set prikey d"); + if (unlikely(ret)) + return ret; + + return set_param_single(d, prikey, "ecc set d"); +} + +int wcrypto_get_ecc_prikey(struct wcrypto_ecc_key *ecc_key, + struct wd_dtb **prikey) +{ + if (unlikely(!ecc_key || !prikey)) { + WD_ERR("get ecc prikey parameter err!\n"); + return -WD_EINVAL; + } + + *prikey = ecc_key->d; + + return WD_SUCCESS; +} + +int wcrypto_set_ecc_pubkey(struct wcrypto_ecc_key *ecc_key, + struct wcrypto_ecc_point *pubkey) +{ + struct wcrypto_ecc_pubkey *ecc_pubkey; + struct wcrypto_ecc_point *pub; + int ret; + + if (unlikely(!ecc_key || !pubkey)) { + WD_ERR("set ecc pubkey parameter err!\n"); + return -WD_EINVAL; + } + + pub = ecc_key->pub; + ecc_pubkey = ecc_key->pubkey; + if (!ecc_pubkey || !pub) { + WD_ERR("ecc_pubkey or pub NULL!\n"); + return -WD_EINVAL; + } + + ret = set_param_single(&ecc_pubkey->pub.x, &pubkey->x, "ecc pubkey x"); + if (unlikely(ret)) + return ret; + + ret = set_param_single(&ecc_pubkey->pub.y, &pubkey->y, "ecc pubkey y"); + if (unlikely(ret)) + return ret; + + ret = trans_to_binpad(pub->x.data, pubkey->x.data, + pub->x.bsize, pubkey->x.dsize, "ecc pub x"); + if (unlikely(ret)) + return ret; + + return trans_to_binpad(pub->y.data, pubkey->y.data, + pub->y.bsize, pubkey->y.dsize, "ecc pub y"); +} + +int wcrypto_get_ecc_pubkey(struct wcrypto_ecc_key *ecc_key, + struct wcrypto_ecc_point **pubkey) +{ + if (unlikely(!ecc_key || !pubkey || !ecc_key->pub)) { + WD_ERR("get ecc pubkey parameter err!\n"); + return -WD_EINVAL; + } + + *pubkey = ecc_key->pub; + + return WD_SUCCESS; +} + +int wcrypto_get_ecc_curve(struct wcrypto_ecc_key *ecc_key, + struct wcrypto_ecc_curve **cv) +{ + if (unlikely(!ecc_key || !cv || !ecc_key->cv)) { + WD_ERR("get ecc pubkey parameter err!\n"); + return -WD_EINVAL; + } + + *cv = ecc_key->cv; + + return WD_SUCCESS; +} + +void wcrypto_get_ecc_prikey_params(struct wcrypto_ecc_key *key, + struct wd_dtb **p, struct wd_dtb **a, + struct wd_dtb **b, struct wd_dtb **n, + struct wcrypto_ecc_point **g, + struct wd_dtb **d) +{ + struct wcrypto_ecc_prikey *prk; + + if (unlikely(!key || !key->prikey)) { + WD_ERR("input NULL in get ecc private key parameter!\n"); + return; + } + + prk = key->prikey; + + if (p) + *p = &prk->p; + + if (a) + *a = &prk->a; + + if (b) + *b = &prk->b; + + if (n) + *n = &prk->n; + + if (g) + *g = &prk->g; + + if (d) + *d = &prk->d; +} + +void wcrypto_get_ecc_pubkey_params(struct wcrypto_ecc_key *key, + struct wd_dtb **p, struct wd_dtb **a, + struct wd_dtb **b, struct wd_dtb **n, + struct wcrypto_ecc_point **g, + struct wcrypto_ecc_point **pub) +{ + struct wcrypto_ecc_pubkey *pbk; + + if (unlikely(!key || !key->pubkey)) { + WD_ERR("input NULL in get ecc public key parameter!\n"); + return; + } + + pbk = key->pubkey; + + if (p) + *p = &pbk->p; + + if (a) + *a = &pbk->a; + + if (b) + *b = &pbk->b; + + if (n) + *n = &pbk->n; + + if (g) + *g = &pbk->g; + + if (pub) + *pub = &pbk->pub; +} + +void wcrypto_get_ecxdh_out_params(struct wcrypto_ecc_out *out, + struct wcrypto_ecc_point **key) +{ + struct wcrypto_ecc_dh_out *dh_out = (void *)out; + + if (unlikely(!dh_out)) { + WD_ERR("input NULL in get ecdh out!\n"); + return; + } + + if (key) + *key = &dh_out->out; +} + +void wcrypto_get_ecxdh_in_params(struct wcrypto_ecc_in *in, + struct wcrypto_ecc_point **pbk) +{ + struct wcrypto_ecc_dh_in *dh_in = (void *)in; + + if (!in) { + WD_ERR("input NULL in get ecdh in!\n"); + return; + } + + if (pbk) + *pbk = &dh_in->pbk; +} + +void wcrypto_del_ecc_in(void *ctx, struct wcrypto_ecc_in *in) +{ + struct wcrypto_ecc_ctx *cx = ctx; + __u32 bsz; + + if (unlikely(!ctx || !in)) { + WD_ERR("del ecc in parameter error!\n"); + return; + } + + bsz = in->size; + if (unlikely(!bsz)) { + WD_ERR("del ecc in: bsz 0!\n"); + return; + } + + wd_memset_zero(in->data, bsz); + br_free(&cx->setup.br, in); +} + +void wcrypto_del_ecc_out(void *ctx, struct wcrypto_ecc_out *out) +{ + struct wcrypto_ecc_ctx *cx = ctx; + __u32 bsz; + + if (unlikely(!ctx || !out)) { + WD_ERR("del ecc out parameter error!\n"); + return; + } + + bsz = out->size; + if (unlikely(!bsz)) { + WD_ERR("del ecc out: bsz 0!\n"); + return; + } + + wd_memset_zero(out->data, bsz); + br_free(&cx->setup.br, out); +} + +static int ecc_request_init(struct wcrypto_ecc_msg *req, + struct wcrypto_ecc_op_data *op, + struct wcrypto_ecc_ctx *c, __u8 need_hash) +{ + __u8 *key; + + req->in_bytes = (__u16)op->in_bytes; + req->out = op->out; + req->op_type = op->op_type; + req->hash_type = c->setup.hash.type; + req->result = WD_EINVAL; + + switch (req->op_type) { + case WCRYPTO_ECXDH_GEN_KEY: + case WCRYPTO_ECXDH_COMPUTE_KEY: + case WCRYPTO_ECDSA_SIGN: + case WCRYPTO_ECDSA_VERIFY: + case WCRYPTO_SM2_ENCRYPT: + case WCRYPTO_SM2_DECRYPT: + case WCRYPTO_SM2_SIGN: + case WCRYPTO_SM2_VERIFY: + case WCRYPTO_SM2_KG: + key = (__u8 *)&c->key; + break; + default: + WD_ERR("ecc request op type = %hhu error!\n", req->op_type); + return -WD_EINVAL; + } + req->key = key; + + if (req->op_type == WCRYPTO_ECXDH_GEN_KEY || + req->op_type == WCRYPTO_SM2_KG) { + struct wcrypto_ecc_point *g = NULL; + + wcrypto_get_ecc_prikey_params((void *)key, NULL, NULL, + NULL, NULL, &g, NULL); + req->in = (void *)g; + } else { + req->in = op->in; + } + + if (unlikely(!req->in || + (!req->out && (req->op_type != WCRYPTO_ECDSA_VERIFY && + req->op_type != WCRYPTO_SM2_VERIFY)))) { + WD_ERR("req in/out NULL!\n"); + return -WD_EINVAL; + } + + return WD_SUCCESS; +} + +static void msg_pack(char *dst, __u64 *out_len, + const void *src, __u32 src_len) +{ + if (unlikely(!src || !src_len)) + return; + + memcpy(dst + *out_len, src, src_len); + *out_len += src_len; +} + +static int ecc_send(struct wcrypto_ecc_ctx *ctx, struct wcrypto_ecc_msg *req) +{ + __u32 tx_cnt = 0; + int ret; + + do { + ret = wd_send(ctx->q, req); + if (!ret) { + break; + } else if (ret == -WD_EBUSY) { + if (tx_cnt++ >= ECC_RESEND_CNT) { + WD_ERR("failed to send: retry exit!\n"); + break; + } + + usleep(1); + } else if (unlikely(ret)) { + WD_ERR("failed to send: send error = %d!\n", ret); + break; + } + } while (true); + + return ret; +} + +static int ecc_sync_recv(struct wcrypto_ecc_ctx *ctx, + struct wcrypto_ecc_op_data *opdata) +{ + struct wcrypto_ecc_msg *resp; + __u32 rx_cnt = 0; + int ret; + + resp = (void *)(uintptr_t)ctx->ctx_id; + + do { + ret = wd_recv(ctx->q, (void **)&resp); + if (ret > 0) { + break; + } else if (!ret) { + if (rx_cnt++ >= ECC_RECV_MAX_CNT) { + WD_ERR("failed to recv: timeout!\n"); + return -WD_ETIMEDOUT; + } + + if (balance > ECC_BALANCE_THRHD) + usleep(1); + } else { + WD_ERR("failed to recv: error = %d!\n", ret); + return ret; + } + } while (true); + + balance = rx_cnt; + opdata->out = resp->out; + opdata->out_bytes = resp->out_bytes; + opdata->status = resp->result; + + return GET_NEGATIVE(opdata->status); +} + +static int do_ecc(void *ctx, struct wcrypto_ecc_op_data *opdata, void *tag, + __u8 need_hash) +{ + struct wcrypto_ecc_cookie *cookie = NULL; + struct wcrypto_ecc_ctx *ctxt = ctx; + struct wcrypto_ecc_msg *req; + int ret; + + if (unlikely(!ctx)) { + WD_ERR("do ecc parameter null!\n"); + return -WD_EINVAL; + } + + ret = wd_get_cookies(&ctxt->pool, (void **)&cookie, 1); + if (ret) + return ret; + + if (tag) { + if (unlikely(!ctxt->setup.cb)) { + WD_ERR("ctx call back is null!\n"); + ret = -WD_EINVAL; + goto fail_with_cookie; + } + cookie->tag.tag = tag; + } + + req = &cookie->msg; + ret = ecc_request_init(req, opdata, ctxt, need_hash); + if (ret) + goto fail_with_cookie; + + ret = ecc_send(ctxt, req); + if (unlikely(ret)) + goto fail_with_cookie; + + if (tag) + return ret; + + ret = ecc_sync_recv(ctxt, opdata); + +fail_with_cookie: + wd_put_cookies(&ctxt->pool, (void **)&cookie, 1); + return ret; +} + +static int ecc_poll(struct wd_queue *q, unsigned int num) +{ + struct wcrypto_ecc_msg *resp = NULL; + struct wcrypto_ecc_ctx *ctx; + struct wcrypto_cb_tag *tag; + unsigned int tmp = num; + int count = 0; + int ret; + + do { + ret = wd_recv(q, (void **)&resp); + if (ret == 0) + break; + else if (unlikely(ret < 0)) { + WD_ERR("failed to recv: error = %d!\n", ret); + return ret; + } + + count++; + tag = (void *)(uintptr_t)resp->usr_data; + ctx = tag->ctx; + ctx->setup.cb(resp, tag->tag); + wd_put_cookies(&ctx->pool, (void **)&tag, 1); + resp = NULL; + } while (--tmp); + + return count; +} + +int wcrypto_do_ecxdh(void *ctx, struct wcrypto_ecc_op_data *opdata, void *tag) +{ + if (unlikely(!opdata)) { + WD_ERR("do ecxdh: opdata null!\n"); + return -WD_EINVAL; + } + + if (unlikely(opdata->op_type != WCRYPTO_ECXDH_GEN_KEY && + opdata->op_type != WCRYPTO_ECXDH_COMPUTE_KEY)) { + WD_ERR("do ecxdh: op_type = %hhu error!\n", opdata->op_type); + return -WD_EINVAL; + } + + return do_ecc(ctx, opdata, tag, 0); +} + +int wcrypto_ecxdh_poll(struct wd_queue *q, unsigned int num) +{ + if (unlikely(!q || (strcmp(q->capa.alg, "x25519") && + strcmp(q->capa.alg, "x448") && + strcmp(q->capa.alg, "ecdh")))) { + WD_ERR("ecxdh poll: input parameter error!\n"); + return -WD_EINVAL; + } + + return ecc_poll(q, num); +} + +static void get_sign_out_params(struct wcrypto_ecc_out *out, + struct wd_dtb **r, struct wd_dtb **s) +{ + struct wcrypto_ecc_sign_out *sout = (void *)out; + + if (unlikely(!sout)) { + WD_ERR("input NULL in get ecc sign out!\n"); + return; + } + + if (r) + *r = &sout->r; + + if (s) + *s = &sout->s; +} + +void wcrypto_get_ecdsa_sign_out_params(struct wcrypto_ecc_out *out, + struct wd_dtb **r, struct wd_dtb **s) +{ + return get_sign_out_params(out, r, s); +} + + +static bool less_than_latter(struct wd_dtb *d, struct wd_dtb *n) +{ + int ret, shift; + + if (d->dsize != n->dsize) + return d->dsize < n->dsize; + + shift = n->bsize - n->dsize; + ret = memcmp(d->data + shift, n->data + shift, n->dsize); + return ret < 0; +} + +static bool is_all_zero(struct wd_dtb *p, struct wcrypto_ecc_ctx *ctx) +{ + int i; + + for (i = 0; i < p->dsize && i < ctx->key_size; i++) { + if (p->data[i]) + return false; + } + + return true; +} + +static bool check_k_param(struct wd_dtb *k, struct wcrypto_ecc_ctx *ctx) +{ + struct wcrypto_ecc_curve *cv = NULL; + int ret; + + if (unlikely(!k->data)) { + WD_ERR("error: k->data NULL!\n"); + return false; + } + + ret = wcrypto_get_ecc_curve(&ctx->key, &cv); + if (unlikely(ret)) { + WD_ERR("failed to get ecc curve!\n"); + return false; + } + + if (unlikely(!less_than_latter(k, &cv->n))) { + WD_ERR("error: k >= n\n"); + return false; + } + + if (unlikely(is_all_zero(k, ctx))) { + WD_ERR("error: k all zero\n"); + return false; + } + + return true; +} + +static int set_sign_in_param(struct wcrypto_ecc_sign_in *sin, + struct wd_dtb *dgst, + struct wd_dtb *k, + struct wd_dtb *plaintext, + struct wcrypto_ecc_ctx *ctx) +{ + int ret; + + if (k) { + if (unlikely(!check_k_param(k, ctx))) + return -WD_EINVAL; + + ret = set_param_single(&sin->k, k, "ecc sgn k"); + if (unlikely(ret)) + return ret; + } + + if (dgst) { + ret = set_param_single(&sin->dgst, dgst, "ecc sgn dgst"); + if (unlikely(ret)) + return ret; + } + + if (plaintext && plaintext->dsize) { + ret = set_param_single(&sin->plaintext, plaintext, "ecc sgn m"); + if (unlikely(ret)) + return ret; + } + + return 0; +} + +static int generate_random(struct wcrypto_ecc_ctx *ctx, struct wd_dtb *k) +{ + struct wcrypto_rand_mt *rand_mt = &ctx->setup.rand; + int ret; + + ret = rand_mt->cb(k->data, k->dsize, rand_mt->usr); + if (unlikely(ret)) + WD_ERR("failed to rand cb: ret = %d!\n", ret); + + return ret; +} + +static int sm2_compute_za_hash(__u8 *za, __u32 *len, struct wd_dtb *id, + struct wcrypto_ecc_ctx *ctx) +{ + __u32 key_size = BITS_TO_BYTES(ctx->setup.key_bits); + struct wcrypto_hash_mt *hash = &ctx->setup.hash; + struct wcrypto_ecc_point *pub = ctx->key.pub; + struct wcrypto_ecc_curve *cv = ctx->key.cv; + __u16 id_bytes = 0; + __u16 id_bits = 0; + __u64 in_len = 0; + __u32 hash_bytes; + char *p_in; + __u64 lens; + __u8 temp; + int ret; + + if (id && (!BYTES_TO_BITS(id->dsize) || !id->data || + BYTES_TO_BITS(id->dsize) > UINT16_MAX)) { + WD_ERR("id error: lens = %u!\n", id->dsize); + return -WD_EINVAL; + } + + if (id) { + id_bits = BYTES_TO_BITS(id->dsize); + id_bytes = id->dsize; + } + + /* ZA = h(ENTL || ID || a || b || xG || yG || xA || yA) */ + lens = sizeof(__u16) + id_bytes + CURVE_PARAM_NUM * key_size; + p_in = malloc(lens); + if (unlikely(!p_in)) + return -WD_ENOMEM; + + memset(p_in, 0, lens); + temp = id_bits >> 8; + msg_pack(p_in, &in_len, &temp, sizeof(__u8)); + temp = id_bits & 0xFF; + msg_pack(p_in, &in_len, &temp, sizeof(__u8)); + if (id) + msg_pack(p_in, &in_len, id->data, id_bytes); + msg_pack(p_in, &in_len, cv->a.data, key_size); + msg_pack(p_in, &in_len, cv->b.data, key_size); + msg_pack(p_in, &in_len, cv->g.x.data, key_size); + msg_pack(p_in, &in_len, cv->g.y.data, key_size); + msg_pack(p_in, &in_len, pub->x.data, key_size); + msg_pack(p_in, &in_len, pub->y.data, key_size); + + hash_bytes = get_hash_bytes(hash->type); + *len = hash_bytes; + ret = hash->cb((const char *)p_in, in_len, + (void *)za, hash_bytes, hash->usr); + + free(p_in); + + return ret; +} + +static int sm2_compute_digest(void *ctx, struct wd_dtb *hash_msg, + struct wd_dtb *plaintext, struct wd_dtb *id) +{ + struct wcrypto_ecc_ctx *cx = ctx; + struct wcrypto_hash_mt *hash = &cx->setup.hash; + __u8 za[SM2_KEY_SIZE] = {0}; + __u32 za_len = SM2_KEY_SIZE; + __u32 hash_bytes; + __u64 in_len = 0; + char *p_in; + __u64 lens; + int ret; + + hash_bytes = get_hash_bytes(hash->type); + if (unlikely(!hash_bytes || hash_bytes > SM2_KEY_SIZE)) { + WD_ERR("hash type = %u error!\n", hash->type); + return -WD_EINVAL; + } + + ret = sm2_compute_za_hash(za, &za_len, id, ctx); + if (unlikely(ret)) { + WD_ERR("failed to compute za, ret = %d!\n", ret); + return ret; + } + + lens = plaintext->dsize + hash_bytes; + p_in = malloc(lens); + if (unlikely(!p_in)) + return -WD_ENOMEM; + + /* e = h(ZA || M) */ + memset(p_in, 0, lens); + msg_pack(p_in, &in_len, za, za_len); + msg_pack(p_in, &in_len, plaintext->data, plaintext->dsize); + hash_msg->dsize = hash_bytes; + ret = hash->cb((const char *)p_in, in_len, hash_msg->data, + hash_bytes, hash->usr); + if (unlikely(ret)) + WD_ERR("failed to compute e, ret = %d!\n", ret); + + free(p_in); + + return ret; +} + +static struct wcrypto_ecc_in *new_sign_in(struct wcrypto_ecc_ctx *ctx, + struct wd_dtb *e, struct wd_dtb *k, + struct wd_dtb *id, __u8 is_dgst) +{ + struct wcrypto_ecc_ctx *cx = ctx; + struct wcrypto_ecc_sign_in *sin; + struct wd_dtb *plaintext = NULL; + struct wd_dtb *hash_msg = NULL; + struct wcrypto_ecc_in *ecc_in; + int ret; + + if (unlikely(!ctx || !e)) { + WD_ERR("failed to new ecc sign in: ctx or e NULL!\n"); + return NULL; + } + + ecc_in = create_ecc_sign_in(cx, e->dsize, is_dgst); + if (unlikely(!ecc_in)) + return NULL; + + sin = &ecc_in->param.sin; + if (!k && cx->setup.rand.cb) { + ret = generate_random(cx, &sin->k); + if (unlikely(ret)) + goto release_in; + } + + sin->k_set = 0; + sin->dgst_set = 0; + if (k || cx->setup.rand.cb) + sin->k_set = 1; + + if (!is_dgst) { + plaintext = e; + if (cx->setup.hash.cb) { + ret = sm2_compute_digest(cx, &sin->dgst, e, id); + if (unlikely(ret)) + goto release_in; + sin->dgst_set = 1; + } + } else { + hash_msg = e; + sin->dgst_set = 1; + } + + ret = set_sign_in_param(sin, hash_msg, k, plaintext, ctx); + if (unlikely(ret)) + goto release_in; + + return ecc_in; + +release_in: + release_ecc_in(ctx, ecc_in); + + return NULL; +} + +struct wcrypto_ecc_in *wcrypto_new_ecdsa_sign_in(void *ctx, + struct wd_dtb *dgst, + struct wd_dtb *k) +{ + return new_sign_in(ctx, dgst, k, NULL, 1); +} + +static int set_verf_in_param(struct wcrypto_ecc_verf_in *vin, + struct wd_dtb *dgst, + struct wd_dtb *r, + struct wd_dtb *s, + struct wd_dtb *plaintext) +{ + int ret; + + if (dgst) { + ret = set_param_single(&vin->dgst, dgst, "ecc vrf dgst"); + if (unlikely(ret)) + return ret; + } + + if (plaintext && plaintext->dsize) { + ret = set_param_single(&vin->plaintext, plaintext, "ecc vrf m"); + if (unlikely(ret)) + return ret; + } + + ret = set_param_single(&vin->s, s, "ecc vrf s"); + if (unlikely(ret)) + return ret; + + return set_param_single(&vin->r, r, "ecc vrf r"); +} + +static struct wcrypto_ecc_in *create_sm2_verf_in(struct wcrypto_ecc_ctx *ctx, + __u32 m_len) +{ + struct wd_dtb *dgst, *s, *r, *plaintext; + struct wd_mm_br *br = &ctx->setup.br; + struct wcrypto_ecc_in *in; + __u64 len; + __u32 hsz; + + if (unlikely(!ctx->key_size || ctx->key_size > ECC_MAX_KEY_SIZE)) { + WD_ERR("ctx key size %u error!\n", ctx->key_size); + return NULL; + } + + hsz = get_hw_keysize(ctx->key_size); + len = sizeof(struct wcrypto_ecc_in) + ECC_VERF_IN_PARAM_NUM * hsz + + (__u64)m_len; + in = br_alloc(br, len); + if (unlikely(!in)) { + WD_ERR("failed to br alloc, sz = %llu!\n", len); + return NULL; + } + + memset(in, 0, len); + in->size = len - sizeof(struct wcrypto_ecc_in); + dgst = (void *)in; + dgst->data = in->data; + dgst->dsize = ctx->key_size; + dgst->bsize = hsz; + + s = dgst + 1; + s->data = dgst->data + hsz; + s->dsize = ctx->key_size; + s->bsize = hsz; + + r = s + 1; + r->data = s->data + hsz; + r->dsize = ctx->key_size; + r->bsize = hsz; + + plaintext = r + 1; + plaintext->data = r->data + hsz; + plaintext->dsize = m_len; + plaintext->bsize = m_len; + + return in; +} + +static struct wcrypto_ecc_in *create_ecc_verf_in(struct wcrypto_ecc_ctx *ctx, + __u32 m_len, __u8 is_dgst) +{ + if (is_dgst) + return create_ecc_in(ctx, ECC_VERF_IN_PARAM_NUM); + else + return create_sm2_verf_in(ctx, m_len); +} + +static struct wcrypto_ecc_in *new_verf_in(void *ctx, + struct wd_dtb *e, + struct wd_dtb *r, + struct wd_dtb *s, + struct wd_dtb *id, + __u8 is_dgst) +{ + struct wcrypto_ecc_ctx *cx = ctx; + struct wcrypto_ecc_verf_in *vin; + struct wd_dtb *plaintext = NULL; + struct wd_dtb *hash_msg = NULL; + struct wcrypto_ecc_in *ecc_in; + int ret; + + if (!cx || !r || !e || !s) { + WD_ERR("new ecc verf in parameter error!\n"); + return NULL; + } + + ecc_in = create_ecc_verf_in(cx, e->dsize, is_dgst); + if (unlikely(!ecc_in)) + return NULL; + + vin = &ecc_in->param.vin; + vin->dgst_set = 0; + if (!is_dgst) { + plaintext = e; + if (cx->setup.hash.cb) { + ret = sm2_compute_digest(cx, &vin->dgst, e, id); + if (unlikely(ret)) + goto release_in; + vin->dgst_set = 1; + } + } else { + hash_msg = e; + vin->dgst_set = 1; + } + + ret = set_verf_in_param(vin, hash_msg, r, s, plaintext); + if (unlikely(ret)) + goto release_in; + + return ecc_in; + +release_in: + release_ecc_in(ctx, ecc_in); + + return NULL; +} + +struct wcrypto_ecc_in *wcrypto_new_ecdsa_verf_in(void *ctx, + struct wd_dtb *dgst, + struct wd_dtb *r, + struct wd_dtb *s) +{ + return new_verf_in(ctx, dgst, r, s, NULL, 1); +} + +struct wcrypto_ecc_out *wcrypto_new_ecdsa_sign_out(void *ctx) +{ + struct wcrypto_ecc_out *ecc_out; + + if (unlikely(!ctx)) { + WD_ERR("new ecc sout ctx NULL!\n"); + return NULL; + } + + ecc_out = create_ecc_out(ctx, ECC_SIGN_OUT_PARAM_NUM); + if (unlikely(!ecc_out)) + WD_ERR("create ecc out err!\n"); + + return ecc_out; +} + +void wcrypto_get_ecdsa_verf_in_params(struct wcrypto_ecc_in *in, + struct wd_dtb **dgst, + struct wd_dtb **r, + struct wd_dtb **s) +{ + struct wcrypto_ecc_verf_in *vin = (void *)in; + + if (unlikely(!in)) { + WD_ERR("input NULL in get verf in!\n"); + return; + } + + if (dgst) + *dgst = &vin->dgst; + + if (r) + *r = &vin->r; + + if (s) + *s = &vin->s; +} + +void wcrypto_get_ecdsa_sign_in_params(struct wcrypto_ecc_in *in, + struct wd_dtb **dgst, + struct wd_dtb **k) +{ + struct wcrypto_ecc_sign_in *sin = (void *)in; + + if (unlikely(!in)) { + WD_ERR("input NULL in get sign in!\n"); + return; + } + + if (dgst) + *dgst = &sin->dgst; + + if (k) + *k = &sin->k; +} + +int wcrypto_do_ecdsa(void *ctx, struct wcrypto_ecc_op_data *opdata, void *tag) +{ + if (unlikely(!opdata)) { + WD_ERR("do ecdsa: opdata null!\n"); + return -WD_EINVAL; + } + + if (unlikely(opdata->op_type != WCRYPTO_ECDSA_SIGN && + opdata->op_type != WCRYPTO_ECDSA_VERIFY)) { + WD_ERR("do ecdsa: op_type = %hhu error!\n", opdata->op_type); + return -WD_EINVAL; + } + + return do_ecc(ctx, opdata, tag, 0); +} + +int wcrypto_ecdsa_poll(struct wd_queue *q, unsigned int num) +{ + if (unlikely(!q || strcmp(q->capa.alg, "ecdsa"))) { + WD_ERR("sm2 poll: input parameter error!\n"); + return -WD_EINVAL; + } + + return ecc_poll(q, num); +} + +struct wcrypto_ecc_in *wcrypto_new_sm2_sign_in(void *ctx, + struct wd_dtb *e, + struct wd_dtb *k, + struct wd_dtb *id, + __u8 is_dgst) +{ + return new_sign_in(ctx, e, k, id, is_dgst); +} + +struct wcrypto_ecc_in *wcrypto_new_sm2_verf_in(void *ctx, + struct wd_dtb *e, + struct wd_dtb *r, + struct wd_dtb *s, + struct wd_dtb *id, + __u8 is_dgst) +{ + return new_verf_in(ctx, e, r, s, id, is_dgst); +} + +struct wcrypto_ecc_out *wcrypto_new_sm2_sign_out(void *ctx) +{ + return wcrypto_new_ecdsa_sign_out(ctx); +} + +void wcrypto_get_sm2_sign_out_params(struct wcrypto_ecc_out *out, + struct wd_dtb **r, + struct wd_dtb **s) +{ + return get_sign_out_params(out, r, s); +} + +struct wcrypto_ecc_out *wcrypto_new_sm2_kg_out(void *ctx) +{ + struct wcrypto_ecc_out *ecc_out; + + if (unlikely(!ctx)) { + WD_ERR("new sm2 kg out ctx NULL!\n"); + return NULL; + } + + ecc_out = create_ecc_out(ctx, SM2_KG_OUT_PARAM_NUM); + if (unlikely(!ecc_out)) + WD_ERR("failed to create ecc out!\n"); + + return ecc_out; +} + +void wcrypto_get_sm2_kg_out_params(struct wcrypto_ecc_out *out, + struct wd_dtb **privkey, + struct wcrypto_ecc_point **pubkey) +{ + struct wcrypto_sm2_kg_out *kout = (void *)out; + + if (unlikely(!kout)) { + WD_ERR("input NULL in get sm2 kg out!\n"); + return; + } + + if (privkey) + *privkey = &kout->priv; + + if (pubkey) + *pubkey = &kout->pub; +} + +struct wcrypto_ecc_in *wcrypto_new_sm2_enc_in(void *ctx, + struct wd_dtb *k, + struct wd_dtb *plaintext) +{ + struct wcrypto_ecc_ctx *cx = ctx; + struct wcrypto_sm2_enc_in *ein; + struct wcrypto_ecc_in *ecc_in; + int ret; + + if (unlikely(!cx || !plaintext)) { + WD_ERR("new sm2 enc in parameter error!\n"); + return NULL; + } + + ecc_in = create_sm2_enc_in(cx, plaintext->dsize); + if (unlikely(!ecc_in)) { + WD_ERR("failed to create sm2 enc in!\n"); + return NULL; + } + + ein = &ecc_in->param.ein; + if (!k && cx->setup.rand.cb) { + ret = generate_random(cx, &ein->k); + if (unlikely(ret)) + goto fail_set_param; + } + + if (k || cx->setup.rand.cb) + ein->k_set = 1; + + if (k) { + if (unlikely(!check_k_param(k, ctx))) + goto fail_set_param; + + ret = set_param_single(&ein->k, k, "sm2 enc k"); + if (unlikely(ret)) + goto fail_set_param; + } + + ret = set_param_single(&ein->plaintext, plaintext, "sm2 enc m"); + if (unlikely(ret)) + goto fail_set_param; + + return ecc_in; + +fail_set_param: + release_ecc_in(ctx, ecc_in); + + return NULL; +} + +struct wcrypto_ecc_in *wcrypto_new_sm2_dec_in(void *ctx, + struct wcrypto_ecc_point *c1, + struct wd_dtb *c2, + struct wd_dtb *c3) +{ + __u32 struct_size = sizeof(struct wcrypto_ecc_in); + struct wcrypto_ecc_ctx *cx = ctx; + struct wcrypto_sm2_dec_in *din; + struct wcrypto_ecc_in *ecc_in; + __u64 len = 0; + int ret; + + if (unlikely(!cx || !c1 || !c2 || !c3)) { + WD_ERR("new sm2 dec in parameter error!\n"); + return NULL; + } + + ecc_in = create_sm2_ciphertext(cx, c2->dsize, &len, struct_size); + if (unlikely(!ecc_in)) { + WD_ERR("failed to create sm2 dec in!\n"); + return NULL; + } + ecc_in->size = len - struct_size; + + din = &ecc_in->param.din; + ret = set_param_single(&din->c1.x, &c1->x, "sm2 dec c1 x"); + if (unlikely(ret)) + goto fail_set_param; + + ret = set_param_single(&din->c1.y, &c1->y, "sm2 dec c1 y"); + if (unlikely(ret)) + goto fail_set_param; + + ret = set_param_single(&din->c2, c2, "sm2 dec c2"); + if (unlikely(ret)) + goto fail_set_param; + + ret = set_param_single(&din->c3, c3, "sm2 dec c3"); + if (unlikely(ret)) + goto fail_set_param; + + return ecc_in; + +fail_set_param: + release_ecc_in(ctx, ecc_in); + + return NULL; +} + +struct wcrypto_ecc_out *wcrypto_new_sm2_enc_out(void *ctx, __u32 plaintext_len) +{ + __u32 struct_size = sizeof(struct wcrypto_ecc_out); + struct wcrypto_ecc_ctx *cx = ctx; + struct wcrypto_ecc_out *ecc_out; + __u64 len = 0; + + if (unlikely(!cx)) { + WD_ERR("new ecc sout ctx NULL!\n"); + return NULL; + } + + ecc_out = create_sm2_ciphertext(cx, plaintext_len, &len, struct_size); + if (unlikely(!ecc_out)) { + WD_ERR("failed to create sm2 enc out!\n"); + return NULL; + } + ecc_out->size = len - struct_size; + + return ecc_out; +} + +struct wcrypto_ecc_out *wcrypto_new_sm2_dec_out(void *ctx, __u32 plaintext_len) +{ + struct wcrypto_ecc_ctx *cx = ctx; + struct wcrypto_sm2_dec_out *dout; + struct wcrypto_ecc_out *ecc_out; + struct wd_mm_br *br; + __u64 len; + + if (unlikely(!ctx)) { + WD_ERR("new ecc sout ctx NULL!\n"); + return NULL; + } + + if (unlikely(!cx->key_size || cx->key_size > ECC_MAX_KEY_SIZE)) { + WD_ERR("ctx key size %u error!\n", cx->key_size); + return NULL; + } + + br = &cx->setup.br; + len = sizeof(*ecc_out) + plaintext_len; + ecc_out = br_alloc(br, len); + if (unlikely(!ecc_out)) { + WD_ERR("failed to br alloc, sz = %llu!\n", len); + return NULL; + } + memset(ecc_out, 0, len); + ecc_out->size = plaintext_len; + dout = &ecc_out->param.dout; + dout->plaintext.data = ecc_out->data; + dout->plaintext.dsize = plaintext_len; + dout->plaintext.bsize = plaintext_len; + + return ecc_out; +} + +void wcrypto_get_sm2_enc_out_params(struct wcrypto_ecc_out *out, + struct wcrypto_ecc_point **c1, + struct wd_dtb **c2, + struct wd_dtb **c3) +{ + struct wcrypto_sm2_enc_out *eout = (void *)out; + + if (unlikely(!eout)) { + WD_ERR("input NULL in get sm2 enc out!\n"); + return; + } + + if (c1) + *c1 = &eout->c1; + + if (c2) + *c2 = &eout->c2; + + if (c3) + *c3 = &eout->c3; +} + +void wcrypto_get_sm2_dec_out_params(struct wcrypto_ecc_out *out, + struct wd_dtb **plaintext) +{ + struct wcrypto_sm2_dec_out *dout = (void *)out; + + if (unlikely(!dout)) { + WD_ERR("input NULL in get sm2 dec out!\n"); + return; + } + + if (plaintext) + *plaintext = &dout->plaintext; +} + +int wcrypto_do_sm2(void *ctx, struct wcrypto_ecc_op_data *opdata, void *tag) +{ + struct wcrypto_ecc_out *out; + struct wcrypto_ecc_in *in; + + if (unlikely(!opdata)) { + WD_ERR("do sm2: opdata null!\n"); + return -WD_EINVAL; + } + + if (unlikely(opdata->op_type != WCRYPTO_SM2_SIGN && + opdata->op_type != WCRYPTO_SM2_VERIFY && + opdata->op_type != WCRYPTO_SM2_KG && + opdata->op_type != WCRYPTO_SM2_ENCRYPT && + opdata->op_type != WCRYPTO_SM2_DECRYPT)) { + WD_ERR("do sm2: op_type = %hhu error!\n", opdata->op_type); + return -WD_EINVAL; + } + + in = opdata->in; + out = opdata->out; + if (opdata->op_type == WCRYPTO_SM2_ENCRYPT && + out->param.eout.c2.dsize != in->param.ein.plaintext.dsize) { + WD_ERR("do sm2: enc output c2 size != input plaintext size!\n"); + return -WD_EINVAL; + } else if (opdata->op_type == WCRYPTO_SM2_DECRYPT && + out->param.dout.plaintext.dsize != in->param.din.c2.dsize) { + WD_ERR("do sm2: dec output plaintext size != input c2 size!\n"); + return -WD_EINVAL; + } + + return do_ecc(ctx, opdata, tag, 0); +} + +int wcrypto_sm2_poll(struct wd_queue *q, unsigned int num) +{ + if (unlikely(!q || strcmp(q->capa.alg, "sm2"))) { + WD_ERR("sm2 poll: input parameter error!\n"); + return -WD_EINVAL; + } + + return ecc_poll(q, num); +} diff --git a/uadk/v1/wd_ecc.h b/uadk/v1/wd_ecc.h new file mode 100644 index 0000000..84998ed --- /dev/null +++ b/uadk/v1/wd_ecc.h @@ -0,0 +1,273 @@ +/* + * Copyright 2020 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ +#ifndef __WD_ECC_H +#define __WD_ECC_H + +#include +#include +#include +#include "wd.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int (*wcrypto_rand)(char *out, size_t out_len, void *usr); +typedef int (*wcrypto_hash)(const char *in, size_t in_len, + char *out, size_t out_len, void *usr); + +struct wcrypto_ecc_in; /* ecc input parameters */ +struct wcrypto_ecc_key; /* ecc key parameters */ +struct wcrypto_ecc_out; /* ecc output parameters */ + +struct wcrypto_ecc_point { + struct wd_dtb x; /* x affine coordinates */ + struct wd_dtb y; /* y affine coordinates */ +}; + +/* ECC operational types */ +enum wcrypto_ecc_op_type { + WCRYPTO_EC_OP_INVALID, /* invalid ecc operation */ + WCRYPTO_ECXDH_GEN_KEY, /* ECDH/X448/X25519 generate public key */ + WCRYPTO_ECXDH_COMPUTE_KEY, /* ECDH/X448/X25519 compute share key */ + WCRYPTO_ECDSA_SIGN, /* ECDSA sign */ + WCRYPTO_ECDSA_VERIFY, /* ECDSA verify */ + WCRYPTO_SM2_SIGN, /* SM2 sign */ + WCRYPTO_SM2_VERIFY, /* SM2 verify */ + WCRYPTO_SM2_ENCRYPT, /* SM2 encrypt */ + WCRYPTO_SM2_DECRYPT, /* SM2 decrypt */ + WCRYPTO_SM2_KG, /* SM2 key generate */ + WCRYPTO_EC_OP_MAX /* max operation */ +}; + +/* ECC operational types */ +enum wcrypto_ecc_curve_id { + WCRYPTO_SECP128R1 = 0x10, /* SECG 128 bit prime field */ + WCRYPTO_SECP192K1 = 0x11, /* SECG 192 bit prime field */ + WCRYPTO_SECP256K1 = 0x12, /* SECG 256 bit prime field */ + WCRYPTO_BRAINPOOLP320R1 = 0x13, /* RFC5639 320 bit prime field */ + WCRYPTO_BRAINPOOLP384R1 = 0x14, /* RFC5639 384 bit prime field */ + WCRYPTO_SECP521R1 = 0x15, /* NIST/SECG 521 bit prime field */ +}; + +/* ECC hash callback function types */ +enum wcrypto_ecc_hash_type { + WCRYPTO_HASH_SM3, + WCRYPTO_HASH_SHA1, + WCRYPTO_HASH_SHA224, + WCRYPTO_HASH_SHA256, + WCRYPTO_HASH_SHA384, + WCRYPTO_HASH_SHA512, + WCRYPTO_HASH_MD4, + WCRYPTO_HASH_MD5, + WCRYPTO_HASH_MAX +}; + +struct wcrypto_ecc_curve { + struct wd_dtb p; /* Prime field p */ + struct wd_dtb a; /* Elliptic curve equation a parameter */ + struct wd_dtb b; /* Elliptic curve equation b parameter */ + struct wcrypto_ecc_point g; /* Elliptic curve G point */ + struct wd_dtb n; /* Elliptic curve order */ +}; + +enum wcrypto_ecc_curve_cfg_type { + WCRYPTO_CV_CFG_ID, /* set curve parameter by denote curve ID */ + WCRYPTO_CV_CFG_PARAM /* set curve parameter by denote curve parameter */ +}; + +struct wcrypto_ecc_curve_cfg { + __u32 type; /* denoted by enum wcrypto_ecc_curve_cfg_type */ + union { + enum wcrypto_ecc_curve_id id; /* if WCRYPTO_CV_CFG_ID */ + struct wcrypto_ecc_curve *pparam; /* if WCRYPTO_CV_CFG_PARAM */ + } cfg; + __u8 resv[4]; /* reserve */ +}; + +struct wcrypto_rand_mt { + wcrypto_rand cb; /* rand callback */ + void *usr; /* user private parameter */ +}; + +struct wcrypto_hash_mt { + wcrypto_hash cb; /* hash callback */ + void *usr; /* user private parameter */ + __u8 type; /* hash type, denoted by enum wcrypto_ecc_hash_type */ + __u8 rsv[3]; /* reserve */ +}; + +/* ECC context setting up input parameters from user */ +struct wcrypto_ecc_ctx_setup { + wcrypto_cb cb; /* call back function from user */ + __u16 data_fmt; /* data format denoted by enum wd_buff_type */ + __u16 key_bits; /* ECC key bits */ + struct wcrypto_ecc_curve_cfg cv; /* curve config denoted by user */ + struct wd_mm_br br; /* memory operations from user */ + struct wcrypto_rand_mt rand; /* rand method from user */ + struct wcrypto_hash_mt hash; /* hash method from user */ +}; + +struct wcrypto_ecc_op_data { + enum wcrypto_ecc_op_type op_type; /* ecc operation type */ + int status; /* ecc operation status */ + void *in; /* ecc operation input address, should be DMA-able */ + void *out; /* ecc operation output address, should be DMA-able */ + __u32 in_bytes; /* ecc operation input bytes */ + __u32 out_bytes; /* ecc operation output bytes */ +}; + +/* ECC message format of Warpdrive */ +struct wcrypto_ecc_msg { + __u8 alg_type:4; /* Denoted by enum wcrypto_type */ + __u8 op_type:4; /* Denoted by enum wcrypto_ecc_op_type */ + __u8 curve_id:7; /* Ec curve denoted by enum wcrypto_ecc_curve_type */ + __u8 data_fmt:1; /* Data format, denoted by enum wd_buff_type */ + __u8 mtype; /* not used, reserve */ + __u8 result; /* alg op error code */ + __u16 key_bytes; /* key bytes */ + __u16 in_bytes; /* Input data bytes */ + __u16 out_bytes; /* Output data bytes */ + __u8 hash_type; /* hash method denoted by enum wcrypto_ecc_hash_type */ + __u8 *in; /* Input data VA, should be DMA buffer */ + __u8 *out; /* Output data VA, should be DMA buffer */ + __u8 *key; /* Input key VA, should be DMA buffer */ + /* + * Input user tag, used for identify data stream/user: + * struct wcrypto_cb_tag + */ + __u64 usr_data; +}; + +int wcrypto_get_ecc_key_bits(const void *ctx); +void *wcrypto_create_ecc_ctx(struct wd_queue *q, + struct wcrypto_ecc_ctx_setup *setup); +void wcrypto_del_ecc_ctx(void *ctx); +struct wcrypto_ecc_key *wcrypto_get_ecc_key(void *ctx); +int wcrypto_set_ecc_prikey(struct wcrypto_ecc_key *ecc_key, + struct wd_dtb *prikey); +int wcrypto_get_ecc_prikey(struct wcrypto_ecc_key *ecc_key, + struct wd_dtb **prikey); +int wcrypto_set_ecc_pubkey(struct wcrypto_ecc_key *ecc_key, + struct wcrypto_ecc_point *pubkey); +int wcrypto_get_ecc_pubkey(struct wcrypto_ecc_key *ecc_key, + struct wcrypto_ecc_point **pubkey); +void wcrypto_del_ecc_in(void *ctx, struct wcrypto_ecc_in *in); +void wcrypto_del_ecc_out(void *ctx, struct wcrypto_ecc_out *out); +void wcrypto_get_ecc_prikey_params(struct wcrypto_ecc_key *key, + struct wd_dtb **p, struct wd_dtb **a, + struct wd_dtb **b, struct wd_dtb **n, + struct wcrypto_ecc_point **g, + struct wd_dtb **d); +void wcrypto_get_ecc_pubkey_params(struct wcrypto_ecc_key *key, + struct wd_dtb **p, struct wd_dtb **a, + struct wd_dtb **b, struct wd_dtb **n, + struct wcrypto_ecc_point **g, + struct wcrypto_ecc_point **pub); + +/* APIs For ECDH */ +void wcrypto_get_ecxdh_in_params(struct wcrypto_ecc_in *in, + struct wcrypto_ecc_point **pbk); +void wcrypto_get_ecxdh_out_params(struct wcrypto_ecc_out *out, + struct wcrypto_ecc_point **key); +struct wcrypto_ecc_in *wcrypto_new_ecxdh_in(void *ctx, + struct wcrypto_ecc_point *in); +struct wcrypto_ecc_out *wcrypto_new_ecxdh_out(void *ctx); +/** + * This is a pair of asynchronous mode ECDH/ECDSA/SM2 API as tag is not NULL, + * or it is synchronous mode + */ +int wcrypto_do_ecxdh(void *ctx, struct wcrypto_ecc_op_data *opdata, void *tag); +int wcrypto_ecxdh_poll(struct wd_queue *q, unsigned int num); + + +/* APIs For ECDSA sign/verf */ +struct wcrypto_ecc_in *wcrypto_new_ecdsa_sign_in(void *ctx, + struct wd_dtb *dgst, + struct wd_dtb *k); +struct wcrypto_ecc_in *wcrypto_new_ecdsa_verf_in(void *ctx, + struct wd_dtb *dgst, + struct wd_dtb *r, + struct wd_dtb *s); +struct wcrypto_ecc_out *wcrypto_new_ecdsa_sign_out(void *ctx); +void wcrypto_get_ecdsa_sign_in_params(struct wcrypto_ecc_in *in, + struct wd_dtb **dgst, + struct wd_dtb **k); +void wcrypto_get_ecdsa_verf_in_params(struct wcrypto_ecc_in *in, + struct wd_dtb **dgst, + struct wd_dtb **r, + struct wd_dtb **s); +void wcrypto_get_ecdsa_sign_out_params(struct wcrypto_ecc_out *out, + struct wd_dtb **r, + struct wd_dtb **s); + +/** + * This is a pair of asynchronous mode ECDSA API as tag is not NULL, + * or it is synchronous mode + */ +int wcrypto_do_ecdsa(void *ctx, struct wcrypto_ecc_op_data *opdata, void *tag); +int wcrypto_ecdsa_poll(struct wd_queue *q, unsigned int num); + +/* APIs For SM2 sign/verf/kg */ +struct wcrypto_ecc_in *wcrypto_new_sm2_sign_in(void *ctx, + struct wd_dtb *e, + struct wd_dtb *k, + struct wd_dtb *id, + __u8 is_dgst); +struct wcrypto_ecc_in *wcrypto_new_sm2_verf_in(void *ctx, + struct wd_dtb *e, + struct wd_dtb *r, + struct wd_dtb *s, + struct wd_dtb *id, + __u8 is_dgst); +struct wcrypto_ecc_out *wcrypto_new_sm2_sign_out(void *ctx); + +void wcrypto_get_sm2_sign_out_params(struct wcrypto_ecc_out *out, + struct wd_dtb **r, + struct wd_dtb **s); + +struct wcrypto_ecc_in *wcrypto_new_sm2_enc_in(void *ctx, + struct wd_dtb *k, + struct wd_dtb *plaintext); +struct wcrypto_ecc_in *wcrypto_new_sm2_dec_in(void *ctx, + struct wcrypto_ecc_point *c1, + struct wd_dtb *c2, + struct wd_dtb *c3); +struct wcrypto_ecc_out *wcrypto_new_sm2_enc_out(void *ctx, __u32 plaintext_len); +struct wcrypto_ecc_out *wcrypto_new_sm2_dec_out(void *ctx, __u32 plaintext_len); +struct wcrypto_ecc_out *wcrypto_new_sm2_kg_out(void *ctx); +void wcrypto_get_sm2_kg_out_params(struct wcrypto_ecc_out *out, + struct wd_dtb **privkey, + struct wcrypto_ecc_point **pubkey); +void wcrypto_get_sm2_enc_out_params(struct wcrypto_ecc_out *out, + struct wcrypto_ecc_point **c1, + struct wd_dtb **c2, + struct wd_dtb **c3); +void wcrypto_get_sm2_dec_out_params(struct wcrypto_ecc_out *out, + struct wd_dtb **plaintext); + + +/** + * This is a pair of asynchronous mode SM2 API as tag is not NULL, + * or it is synchronous mode + */ +int wcrypto_do_sm2(void *ctx, struct wcrypto_ecc_op_data *opdata, void *tag); +int wcrypto_sm2_poll(struct wd_queue *q, unsigned int num); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/uadk/v1/wd_rng.c b/uadk/v1/wd_rng.c new file mode 100644 index 0000000..2077578 --- /dev/null +++ b/uadk/v1/wd_rng.c @@ -0,0 +1,289 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include + +#include +#include + +#include "wd.h" +#include "wd_util.h" +#include "wd_rng.h" + +#define MAX_NUM 10 +#define RNG_RESEND_CNT 8 +#define RNG_RECV_CNT 8 + +struct wcrypto_rng_cookie { + struct wcrypto_cb_tag tag; + struct wcrypto_rng_msg msg; +}; + +struct wcrypto_rng_ctx { + struct wd_cookie_pool pool; + unsigned long ctx_id; + struct wd_queue *q; + struct wcrypto_rng_ctx_setup setup; +}; + +static int wcrypto_setup_qinfo(struct wcrypto_rng_ctx_setup *setup, + struct wd_queue *q, __u32 *ctx_id) +{ + struct q_info *qinfo; + int ret = -WD_EINVAL; + + if (!q || !setup) { + WD_ERR("input parameter err!\n"); + return ret; + } + + if (strcmp(q->capa.alg, "trng")) { + WD_ERR("algorithm mismatch!\n"); + return ret; + } + qinfo = q->qinfo; + /* lock at ctx creating */ + wd_spinlock(&qinfo->qlock); + if (qinfo->ctx_num >= WD_MAX_CTX_NUM) { + WD_ERR("create too many trng ctx!\n"); + goto unlock; + } + + ret = wd_alloc_id(qinfo->ctx_id, WD_MAX_CTX_NUM, ctx_id, 0, + WD_MAX_CTX_NUM); + if (ret) { + WD_ERR("err: alloc ctx id fail!\n"); + goto unlock; + } + qinfo->ctx_num++; + ret = WD_SUCCESS; +unlock: + wd_unspinlock(&qinfo->qlock); + return ret; +} + +void *wcrypto_create_rng_ctx(struct wd_queue *q, + struct wcrypto_rng_ctx_setup *setup) +{ + struct wcrypto_rng_cookie *cookie; + struct wcrypto_rng_ctx *ctx; + struct q_info *qinfo; + __u32 ctx_id = 0; + int i, ret; + + if (wcrypto_setup_qinfo(setup, q, &ctx_id)) + return NULL; + + ctx = calloc(1, sizeof(struct wcrypto_rng_ctx)); + if (!ctx) { + WD_ERR("alloc ctx memory fail!\n"); + goto free_ctx_id; + } + memcpy(&ctx->setup, setup, sizeof(*setup)); + ctx->q = q; + ctx->ctx_id = ctx_id + 1; + + ret = wd_init_cookie_pool(&ctx->pool, + sizeof(struct wcrypto_rng_cookie), WD_RNG_CTX_MSG_NUM); + if (ret) { + WD_ERR("fail to init cookie pool!\n"); + free(ctx); + goto free_ctx_id; + } + for (i = 0; i < ctx->pool.cookies_num; i++) { + cookie = (void *)((uintptr_t)ctx->pool.cookies + + i * ctx->pool.cookies_size); + cookie->msg.alg_type = WCRYPTO_RNG; + cookie->tag.ctx = ctx; + cookie->tag.ctx_id = ctx->ctx_id; + cookie->msg.usr_tag = (uintptr_t)&cookie->tag; + } + + return ctx; + +free_ctx_id: + qinfo = q->qinfo; + wd_spinlock(&qinfo->qlock); + qinfo->ctx_num--; + wd_free_id(qinfo->ctx_id, WD_MAX_CTX_NUM, ctx_id, WD_MAX_CTX_NUM); + wd_unspinlock(&qinfo->qlock); + + return NULL; +} + +void wcrypto_del_rng_ctx(void *ctx) +{ + struct wcrypto_rng_ctx *cx; + struct q_info *qinfo; + + if (!ctx) { + WD_ERR("delete trng ctx is NULL!\n"); + return; + } + + cx = ctx; + qinfo = cx->q->qinfo; + + wd_uninit_cookie_pool(&cx->pool); + wd_spinlock(&qinfo->qlock); + wd_free_id(qinfo->ctx_id, WD_MAX_CTX_NUM, cx->ctx_id - 1, + WD_MAX_CTX_NUM); + qinfo->ctx_num--; + if (qinfo->ctx_num < 0) { + wd_unspinlock(&qinfo->qlock); + WD_ERR("repeat delete trng ctx!\n"); + return; + } + wd_unspinlock(&qinfo->qlock); + + free(ctx); +} + +int wcrypto_rng_poll(struct wd_queue *q, unsigned int num) +{ + struct wcrypto_rng_msg *resp = NULL; + struct wcrypto_rng_ctx *ctx; + struct wcrypto_cb_tag *tag; + unsigned int tmp = num; + int count = 0; + int ret; + + if (!q) { + WD_ERR("%s(): input parameter err!\n", __func__); + return -WD_EINVAL; + } + + do { + ret = wd_recv(q, (void **)&resp); + if (!ret) + break; + + if (ret < 0) { + WD_ERR("recv err at trng poll!\n"); + return ret; + } + + count++; + tag = (void *)(uintptr_t)resp->usr_tag; + ctx = tag->ctx; + ctx->setup.cb(resp, tag->tag); + wd_put_cookies(&ctx->pool, (void **)&tag, 1); + resp = NULL; + } while (--tmp); + + return count; +} + +static int wcrypto_do_prepare(struct wcrypto_rng_cookie **cookie_addr, + struct wcrypto_rng_op_data *opdata, + struct wcrypto_rng_msg **req_addr, + struct wcrypto_rng_ctx *ctxt, + void *tag) +{ + struct wcrypto_rng_cookie *cookie; + struct wcrypto_rng_msg *req; + int ret; + + if (!ctxt || !opdata) { + WD_ERR("input parameter err!\n"); + return -WD_EINVAL; + } + + ret = wd_get_cookies(&ctxt->pool, (void **)&cookie, 1); + if (ret) + return ret; + + if (tag) { + if (!ctxt->setup.cb) { + WD_ERR("ctx call back is null!\n"); + wd_put_cookies(&ctxt->pool, (void **)&cookie, 1); + return -WD_EINVAL; + } + cookie->tag.tag = tag; + } + + req = &cookie->msg; + req->in_bytes = opdata->in_bytes; + req->out = opdata->out; + *cookie_addr = cookie; + *req_addr = req; + + return 0; +} + +int wcrypto_do_rng(void *ctx, struct wcrypto_rng_op_data *opdata, void *tag) +{ + struct wcrypto_rng_ctx *ctxt = ctx; + struct wcrypto_rng_cookie *cookie; + struct wcrypto_rng_msg *req; + struct wcrypto_rng_msg *resp; + uint32_t tx_cnt = 0; + uint32_t rx_cnt = 0; + int ret = 0; + + ret = wcrypto_do_prepare(&cookie, opdata, &req, ctxt, tag); + if (ret) + return ret; + + do { + ret = wd_send(ctxt->q, req); + if (!ret) { + break; + } else if (ret == -WD_EBUSY) { + if (++tx_cnt > RNG_RESEND_CNT) { + WD_ERR("do trng send cnt %u, exit!\n", tx_cnt); + goto fail_with_cookie; + } + + usleep(1); + } else { + WD_ERR("do rng wd_send err!\n"); + goto fail_with_cookie; + } + } while (true); + + if (tag) + return ret; + + resp = (void *)(uintptr_t)ctxt->ctx_id; + + do { + ret = wd_recv(ctxt->q, (void **)&resp); + if (ret > 0) { + break; + } else if (!ret) { + if (++rx_cnt > RNG_RECV_CNT) { + WD_ERR("do trng recv cnt %u, exit!\n", rx_cnt); + ret = -WD_ETIMEDOUT; + goto fail_with_cookie; + } + + usleep(1); + } else { + WD_ERR("do trng recv err!\n"); + goto fail_with_cookie; + } + } while (true); + + opdata->out_bytes = resp->out_bytes; + ret = WD_SUCCESS; +fail_with_cookie: + wd_put_cookies(&ctxt->pool, (void **)&cookie, 1); + return ret; +} diff --git a/uadk/v1/wd_rng.h b/uadk/v1/wd_rng.h new file mode 100644 index 0000000..fcde26d --- /dev/null +++ b/uadk/v1/wd_rng.h @@ -0,0 +1,76 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#ifndef __WD_RNG_H +#define __WD_RNG_H + +#include "wd.h" +#include "wd_digest.h" +#include "wd_cipher.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct wcrypto_rng_ctx_setup { + wcrypto_cb cb; + __u16 data_fmt; /* Data format, denoted by enum wd_buff_type */ + enum wcrypto_type type; /* Please refer to the definition of enum */ + enum wcrypto_cipher_alg calg; /* DRBG cipher algorithm */ + enum wcrypto_cipher_mode cmode; /* DRBG cipher mode */ + enum wcrypto_digest_alg dalg; /* DRBG digest algorithm */ + enum wcrypto_digest_mode dmode; /* DRBG digest mode */ +}; + +struct wcrypto_rng_msg { + __u8 alg_type; /* Denoted by enum wcrypto_type */ + __u8 op_type; /* Denoted by enum wcrypto_rng_op_type */ + __u8 data_fmt; /* Data format, denoted by enum wd_buff_type */ + __u8 result; /* Data format, denoted by WD error code */ + __u8 *out; /* Result address */ + __u8 *in; /* Input address */ + __u32 out_bytes; /* output bytes */ + __u32 in_bytes; /* input bytes */ + __u64 usr_tag; /* user identifier */ +}; + +enum wcrypto_rng_op_type { + WCRYPTO_RNG_INVALID, /* Invalid RNG operational type */ + WCRYPTO_DRBG_RESEED, /* seed operation */ + WCRYPTO_DRBG_GEN, /* deterministic random number generation */ + WCRYPTO_TRNG_GEN, /* true random number generation */ +}; + +struct wcrypto_rng_op_data { + enum wcrypto_rng_op_type op_type; + __u32 status; /* Operation result status */ + void *in; /* input */ + void *out; /* output */ + __u32 in_bytes; /* input bytes */ + __u32 out_bytes; /* output bytes */ +}; + +void *wcrypto_create_rng_ctx(struct wd_queue *q, + struct wcrypto_rng_ctx_setup *setup); +void wcrypto_del_rng_ctx(void *ctx); +int wcrypto_do_rng(void *ctx, struct wcrypto_rng_op_data *opdata, void *tag); +int wcrypto_rng_poll(struct wd_queue *q, unsigned int num); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/uadk/v1/wd_rsa.c b/uadk/v1/wd_rsa.c new file mode 100644 index 0000000..f0cdda7 --- /dev/null +++ b/uadk/v1/wd_rsa.c @@ -0,0 +1,1113 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include + +#include +#include + +#include "wd.h" +#include "wd_util.h" +#include "wd_rsa.h" + +#define RSA_BALANCE_THRHD 1280 +#define RSA_RESEND_CNT 8 +#define RSA_MAX_KEY_SIZE 512 +#define RSA_RECV_MAX_CNT 60000000 // 1 min + + +static __thread int balance; + +struct wcrypto_rsa_cookie { + struct wcrypto_cb_tag tag; + struct wcrypto_rsa_msg msg; +}; + +struct wcrypto_rsa_ctx { + struct wd_cookie_pool pool; + __u32 key_size; + unsigned long ctx_id; + struct wd_queue *q; + struct wcrypto_rsa_pubkey *pubkey; + struct wcrypto_rsa_prikey *prikey; + struct wcrypto_rsa_ctx_setup setup; +}; + +struct wcrypto_rsa_kg_in { + __u8 *e; + __u8 *p; + __u8 *q; + __u32 ebytes; + __u32 pbytes; + __u32 qbytes; + __u32 key_size; + void *data[]; +}; + +struct wcrypto_rsa_kg_out { + __u8 *d; + __u8 *n; + __u8 *qinv; + __u8 *dq; + __u8 *dp; + __u32 key_size; + __u32 dbytes; + __u32 nbytes; + __u32 dpbytes; + __u32 dqbytes; + __u32 qinvbytes; + __u32 size; + void *data[]; +}; + +struct wcrypto_rsa_pubkey { + struct wd_dtb n; + struct wd_dtb e; + __u32 key_size; + void *data[]; +}; + +struct wcrypto_rsa_prikey1 { + struct wd_dtb n; + struct wd_dtb d; + __u32 key_size; + void *data[]; +}; + +/* RSA crt private key */ +struct wcrypto_rsa_prikey2 { + struct wd_dtb p; + struct wd_dtb q; + struct wd_dtb dp; + struct wd_dtb dq; + struct wd_dtb qinv; + __u32 key_size; + void *data[]; +}; + +struct wcrypto_rsa_prikey { + struct wcrypto_rsa_prikey1 pkey1; + struct wcrypto_rsa_prikey2 pkey2; +}; + +/* RSA CRT private key parameter types */ +enum wcrypto_rsa_crt_prikey_para { + WD_CRT_PRIKEY_DQ, + WD_CRT_PRIKEY_DP, + WD_CRT_PRIKEY_QINV, + WD_CRT_PRIKEY_Q, + WD_CRT_PRIKEY_P +}; + +int wcrypto_rsa_kg_in_data(struct wcrypto_rsa_kg_in *ki, char **data) +{ + if (!ki || !data) { + WD_ERR("parameter is NULL!\n"); + return -WD_EINVAL; + } + + *data = (char *)ki->data; + return (int)GEN_PARAMS_SZ(ki->key_size); +} + +int wcrypto_rsa_kg_out_data(struct wcrypto_rsa_kg_out *ko, char **data) +{ + if (!ko || !data) { + WD_ERR("parameter is NULL!\n"); + return -WD_EINVAL; + } + + *data = (char *)ko->data; + + return (int)ko->size; +} + +static int kg_in_param_check(void *ctx, struct wd_dtb *e, + struct wd_dtb *p, struct wd_dtb *q) +{ + struct wcrypto_rsa_kg_in *kg_in; + struct wcrypto_rsa_ctx *c = ctx; + struct wd_mm_br *br; + int kg_in_size; + + if (unlikely(!c || !e || !p || !q)) { + WD_ERR("ctx br->alloc kg_in memory fail!\n"); + return -WD_EINVAL; + } + + if (unlikely(!c->key_size || c->key_size > RSA_MAX_KEY_SIZE)) { + WD_ERR("key size err at create kg in!\n"); + return -WD_EINVAL; + } + + if (unlikely(e->dsize > c->key_size)) { + WD_ERR("e para err at create kg in!\n"); + return -WD_EINVAL; + } + if (unlikely(p->dsize > CRT_PARAM_SZ(c->key_size))) { + WD_ERR("p para err at create kg in!\n"); + return -WD_EINVAL; + } + if (unlikely(q->dsize > CRT_PARAM_SZ(c->key_size))) { + WD_ERR("q para err at create kg in!\n"); + return -WD_EINVAL; + } + + br = &c->setup.br; + if (unlikely(!br->alloc)) { + WD_ERR("new kg in user mm br err!\n"); + return -WD_EINVAL; + } + + kg_in_size = GEN_PARAMS_SZ(c->key_size); + if (unlikely(br->get_bufsize && + br->get_bufsize(br->usr) < (kg_in_size + sizeof(*kg_in)))) { + WD_ERR("Blk_size < need_size<0x%lx>.\n", (kg_in_size + sizeof(*kg_in))); + return -WD_EINVAL; + } + + return 0; +} + +/* Create a RSA key generate operation input with parameter e, p and q */ +struct wcrypto_rsa_kg_in *wcrypto_new_kg_in(void *ctx, struct wd_dtb *e, + struct wd_dtb *p, struct wd_dtb *q) +{ + struct wcrypto_rsa_kg_in *kg_in; + struct wcrypto_rsa_ctx *c = ctx; + struct wd_mm_br *br; + int kg_in_size, ret; + + ret = kg_in_param_check(ctx, e, p, q); + if (unlikely(ret)) + return NULL; + + br = &c->setup.br; + kg_in_size = GEN_PARAMS_SZ(c->key_size); + kg_in = br->alloc(br->usr, kg_in_size + sizeof(*kg_in)); + if (unlikely(!kg_in)) { + WD_ERR("ctx br->alloc kg_in memory fail!\n"); + return NULL; + } + memset(kg_in, 0, kg_in_size + sizeof(*kg_in)); + kg_in->key_size = c->key_size; + kg_in->ebytes = e->dsize; + kg_in->pbytes = p->dsize; + kg_in->qbytes = q->dsize; + kg_in->e = (void *)kg_in->data; + kg_in->p = (void *)kg_in->e + c->key_size; + kg_in->q = (void *)kg_in->p + CRT_PARAM_SZ(c->key_size); + + memcpy(kg_in->e, e->data, e->dsize); + memcpy(kg_in->p, p->data, p->dsize); + memcpy(kg_in->q, q->data, q->dsize); + + return kg_in; +} + +void wcrypto_get_rsa_kg_in_params(struct wcrypto_rsa_kg_in *kin, struct wd_dtb *e, + struct wd_dtb *q, struct wd_dtb *p) +{ + if (!kin || !e || !q || !p) { + WD_ERR("para err at get input parameters key generate !\n"); + return; + } + + e->bsize = kin->key_size; + e->dsize = kin->ebytes; + e->data = (void *)kin->e; + q->bsize = CRT_PARAM_SZ(kin->key_size); + q->dsize = kin->qbytes; + q->data = (void *)kin->q; + p->bsize = CRT_PARAM_SZ(kin->key_size); + p->dsize = kin->pbytes; + p->data = (void *)kin->p; +} + +static void del_kg(void *ctx, void *k) +{ + struct wcrypto_rsa_ctx *c = ctx; + struct wd_mm_br *br; + + if (!c || !k) { + WD_ERR("delete key generate parameters err!\n"); + return; + } + + br = &c->setup.br; + if (br->free) + br->free(br->usr, k); +} + +void wcrypto_del_kg_in(void *ctx, struct wcrypto_rsa_kg_in *ki) +{ + del_kg(ctx, ki); +} + +struct wcrypto_rsa_kg_out *wcrypto_new_kg_out(void *ctx) +{ + struct wcrypto_rsa_kg_out *kg_out; + struct wcrypto_rsa_ctx *c = ctx; + struct wd_mm_br *br; + int kg_out_size; + __u32 kz; + + if (unlikely(!c)) { + WD_ERR("ctx null at new rsa key gen out!\n"); + return NULL; + } + + kz = c->key_size; + if (unlikely(!kz || kz > RSA_MAX_KEY_SIZE)) { + WD_ERR("new kg out key size error!\n"); + return NULL; + } + + if (c->setup.is_crt) + kg_out_size = CRT_GEN_PARAMS_SZ(c->key_size); + else + kg_out_size = GEN_PARAMS_SZ(c->key_size); + + br = &c->setup.br; + if (unlikely(!br->alloc)) { + WD_ERR("new kg out user mm br err!\n"); + return NULL; + } + if (unlikely(br->get_bufsize && + br->get_bufsize(br->usr) < kg_out_size + sizeof(*kg_out))) { + WD_ERR("blk_size < need_size<0x%lx>.\n", kg_out_size + sizeof(*kg_out)); + return NULL; + } + kg_out = br->alloc(br->usr, kg_out_size + sizeof(*kg_out)); + if (unlikely(!kg_out)) { + WD_ERR("ctx br->alloc kg_in memory fail!\n"); + return NULL; + } + + memset(kg_out, 0, kg_out_size + sizeof(*kg_out)); + kg_out->key_size = kz; + kg_out->d = (void *)kg_out->data; + kg_out->n = kg_out->d + kz; + kg_out->size = (__u32)kg_out_size; + if (c->setup.is_crt) { + kg_out->qinv = (void *)kg_out->n + kz; + kg_out->dq = kg_out->qinv + CRT_PARAM_SZ(kz); + kg_out->dp = kg_out->dq + CRT_PARAM_SZ(kz); + } + + return kg_out; +} + +void wcrypto_del_kg_out(void *ctx, struct wcrypto_rsa_kg_out *kout) +{ + del_kg(ctx, kout); +} + +void wcrypto_get_rsa_kg_out_params(struct wcrypto_rsa_kg_out *kout, struct wd_dtb *d, + struct wd_dtb *n) +{ + if (!kout) { + WD_ERR("input null at get key gen parameters!\n"); + return; + } + + if (d && kout->d) { + d->bsize = kout->key_size; + d->dsize = kout->dbytes; + d->data = (void *)kout->d; + } + + if (n && kout->n) { + n->bsize = kout->key_size; + n->dsize = kout->nbytes; + n->data = (void *)kout->n; + } +} + +void wcrypto_get_rsa_kg_out_crt_params(struct wcrypto_rsa_kg_out *kout, + struct wd_dtb *qinv, + struct wd_dtb *dq, struct wd_dtb *dp) +{ + if (!kout || !qinv || !dq || !dp) { + WD_ERR("input null at get key gen crt para!\n"); + return; + } + + if (qinv && kout->qinv) { + qinv->bsize = CRT_PARAM_SZ(kout->key_size); + qinv->dsize = kout->qinvbytes; + qinv->data = (void *)kout->qinv; + } + + if (dq && kout->dq) { + dq->bsize = CRT_PARAM_SZ(kout->key_size); + dq->dsize = kout->dqbytes; + dq->data = (void *)kout->dq; + } + + if (dp && kout->dp) { + dp->bsize = CRT_PARAM_SZ(kout->key_size); + dp->dsize = kout->dpbytes; + dp->data = (void *)kout->dp; + } +} + +void wcrypto_set_rsa_kg_out_crt_psz(struct wcrypto_rsa_kg_out *kout, + size_t qinv_sz, + size_t dq_sz, + size_t dp_sz) +{ + kout->qinvbytes = qinv_sz; + kout->dqbytes = dq_sz; + kout->dpbytes = dp_sz; +} + +void wcrypto_set_rsa_kg_out_psz(struct wcrypto_rsa_kg_out *kout, + size_t d_sz, + size_t n_sz) +{ + kout->dbytes = d_sz; + kout->nbytes = n_sz; +} + +static void init_pkey2(struct wcrypto_rsa_prikey2 *pkey2, __u32 ksz) +{ + int hlf_ksz = CRT_PARAM_SZ(ksz); + + pkey2->dq.data = (char *)pkey2->data; + pkey2->dp.data = pkey2->dq.data + hlf_ksz; + pkey2->q.data = pkey2->dp.data + hlf_ksz; + pkey2->p.data = pkey2->q.data + hlf_ksz; + pkey2->qinv.data = pkey2->p.data + hlf_ksz; + pkey2->dq.bsize = hlf_ksz; + pkey2->dp.bsize = hlf_ksz; + pkey2->q.bsize = hlf_ksz; + pkey2->p.bsize = hlf_ksz; + pkey2->qinv.bsize = hlf_ksz; + pkey2->key_size = ksz; +} + +static void init_pkey1(struct wcrypto_rsa_prikey1 *pkey1, __u32 ksz) +{ + pkey1->d.data = (char *)pkey1->data; + pkey1->n.data = pkey1->d.data + ksz; + pkey1->d.bsize = ksz; + pkey1->n.bsize = ksz; + pkey1->key_size = ksz; +} + +static void init_pubkey(struct wcrypto_rsa_pubkey *pubkey, __u32 ksz) +{ + pubkey->e.data = (char *)pubkey->data; + pubkey->n.data = pubkey->e.data + ksz; + pubkey->e.bsize = ksz; + pubkey->n.bsize = ksz; + pubkey->key_size = ksz; +} + +static int create_ctx_key(struct wcrypto_rsa_ctx_setup *setup, + struct wcrypto_rsa_ctx *ctx) +{ + struct wd_mm_br *br = &setup->br; + struct wcrypto_rsa_prikey2 *pkey2; + struct wcrypto_rsa_prikey1 *pkey1; + int len; + + if (setup->is_crt) { + len = sizeof(struct wcrypto_rsa_prikey) + + CRT_PARAMS_SZ(ctx->key_size); + if (br->get_bufsize && br->get_bufsize(br->usr) < len) { + WD_ERR("Blk_size < need_size<0x%x>.\n", len); + return -WD_ENOMEM; + } + ctx->prikey = br->alloc(br->usr, len); + if (!ctx->prikey) { + WD_ERR("alloc prikey2 fail!\n"); + return -WD_ENOMEM; + } + pkey2 = &ctx->prikey->pkey2; + memset(ctx->prikey, 0, len); + init_pkey2(pkey2, ctx->key_size); + } else { + len = sizeof(struct wcrypto_rsa_prikey) + + GEN_PARAMS_SZ(ctx->key_size); + if (br->get_bufsize && br->get_bufsize(br->usr) < len) { + WD_ERR("Blk_size < need_size<0x%x>.\n", len); + return -WD_ENOMEM; + } + ctx->prikey = br->alloc(br->usr, len); + if (!ctx->prikey) { + WD_ERR("alloc prikey1 fail!\n"); + return -WD_ENOMEM; + } + pkey1 = &ctx->prikey->pkey1; + memset(ctx->prikey, 0, len); + init_pkey1(pkey1, ctx->key_size); + } + + len = sizeof(struct wcrypto_rsa_pubkey) + GEN_PARAMS_SZ(ctx->key_size); + if (br->get_bufsize && br->get_bufsize(br->usr) < len) { + br->free(br->usr, ctx->prikey); + WD_ERR("Blk_size < need_size<0x%x>.\n", len); + return -WD_ENOMEM; + } + ctx->pubkey = br->alloc(br->usr, len); + if (!ctx->pubkey) { + br->free(br->usr, ctx->prikey); + WD_ERR("alloc pubkey fail!\n"); + return -WD_ENOMEM; + } + + memset(ctx->pubkey, 0, len); + init_pubkey(ctx->pubkey, ctx->key_size); + + return WD_SUCCESS; +} + +static void del_ctx_key(struct wcrypto_rsa_ctx_setup *setup, + struct wcrypto_rsa_ctx *ctx) +{ + struct wd_mm_br *br = &setup->br; + + if (br && br->free) { + if (ctx->prikey) + br->free(br->usr, ctx->prikey); + if (ctx->pubkey) + br->free(br->usr, ctx->pubkey); + } +} + +struct wcrypto_rsa_ctx *create_ctx(struct wcrypto_rsa_ctx_setup *setup, int ctx_id) +{ + struct wcrypto_rsa_cookie *cookie; + struct wcrypto_rsa_ctx *ctx; + int i, ret; + + ctx = calloc(1, sizeof(struct wcrypto_rsa_ctx)); + if (!ctx) + return ctx; + + ret = wd_init_cookie_pool(&ctx->pool, + sizeof(struct wcrypto_rsa_cookie), WD_HPRE_CTX_MSG_NUM); + if (ret) { + WD_ERR("fail to init cookie pool!\n"); + free(ctx); + return NULL; + } + + memcpy(&ctx->setup, setup, sizeof(*setup)); + ctx->ctx_id = ctx_id; + ctx->key_size = setup->key_bits >> BYTE_BITS_SHIFT; + for (i = 0; i < ctx->pool.cookies_num; i++) { + cookie = (void *)((uintptr_t)ctx->pool.cookies + + i * ctx->pool.cookies_size); + if (setup->is_crt) + cookie->msg.key_type = WCRYPTO_RSA_PRIKEY2; + else + cookie->msg.key_type = WCRYPTO_RSA_PRIKEY1; + cookie->msg.data_fmt = setup->data_fmt; + cookie->msg.key_bytes = ctx->key_size; + cookie->msg.alg_type = WCRYPTO_RSA; + cookie->tag.ctx = ctx; + cookie->tag.ctx_id = ctx_id; + cookie->msg.usr_data = (uintptr_t)&cookie->tag; + } + + return ctx; +} + +static void del_ctx(struct wcrypto_rsa_ctx *c) +{ + if (!c) + return; + + wd_uninit_cookie_pool(&c->pool); + free(c); +} + +static int check_q_setup(struct wd_queue *q, struct wcrypto_rsa_ctx_setup *setup) +{ + if (!q || !setup) { + WD_ERR("create rsa ctx input parameter err!\n"); + return -WD_EINVAL; + } + + if (!setup->br.alloc || !setup->br.free) { + WD_ERR("create rsa ctx user mm br err!\n"); + return -WD_EINVAL; + } + + if (strcmp(q->capa.alg, "rsa")) { + WD_ERR("create rsa ctx algorithm mismatching!\n"); + return -WD_EINVAL; + } + + return 0; +} + +/* Before initiate this context, we should get a queue from WD */ +void *wcrypto_create_rsa_ctx(struct wd_queue *q, struct wcrypto_rsa_ctx_setup *setup) +{ + struct wcrypto_rsa_ctx *ctx; + struct q_info *qinfo; + __u32 cid = 0; + int ret; + + ret = check_q_setup(q, setup); + if (ret) + return NULL; + + qinfo = q->qinfo; + /* lock at ctx creating/deleting */ + wd_spinlock(&qinfo->qlock); + if (!qinfo->br.alloc && !qinfo->br.iova_map) + memcpy(&qinfo->br, &setup->br, sizeof(setup->br)); + if (qinfo->br.usr != setup->br.usr) { + WD_ERR("Err mm br in creating rsa ctx!\n"); + goto unlock; + } + + if (qinfo->ctx_num >= WD_MAX_CTX_NUM) { + WD_ERR("err:create too many rsa ctx!\n"); + goto unlock; + } + + ret = wd_alloc_id(qinfo->ctx_id, WD_MAX_CTX_NUM, &cid, 0, + WD_MAX_CTX_NUM); + if (ret) { + WD_ERR("err: alloc ctx id fail!\n"); + goto unlock; + } + qinfo->ctx_num++; + wd_unspinlock(&qinfo->qlock); + + ctx = create_ctx(setup, cid + 1); + if (!ctx) { + WD_ERR("create rsa ctx fail!\n"); + goto free_ctx_id; + } + ctx->q = q; + ret = create_ctx_key(setup, ctx); + if (ret) { + WD_ERR("fail creating rsa ctx keys!\n"); + goto delete_ctx; + } + + return ctx; + +delete_ctx: + del_ctx(ctx); +free_ctx_id: + wd_spinlock(&qinfo->qlock); + wd_free_id(qinfo->ctx_id, WD_MAX_CTX_NUM, cid, WD_MAX_CTX_NUM); + qinfo->ctx_num--; +unlock: + wd_unspinlock(&qinfo->qlock); + + return NULL; +} + +bool wcrypto_rsa_is_crt(const void *ctx) +{ + if (!ctx) { + WD_ERR("rsa is crt judge, ctx NULL, return false!\n"); + return false; + } + + return ((struct wcrypto_rsa_ctx *)ctx)->setup.is_crt; +} + +int wcrypto_rsa_key_bits(const void *ctx) +{ + if (!ctx) { + WD_ERR("get rsa key bits, ctx NULL!\n"); + return 0; + } + + return ((struct wcrypto_rsa_ctx *)ctx)->setup.key_bits; +} + +int wcrypto_set_rsa_pubkey_params(void *ctx, struct wd_dtb *e, struct wd_dtb *n) +{ + struct wcrypto_rsa_ctx *c = ctx; + + if (!ctx) { + WD_ERR("ctx NULL in set rsa public key!\n"); + return -WD_EINVAL; + } + + if (e) { + if (e->dsize > c->pubkey->key_size || !e->data) { + WD_ERR("e err in set rsa public key!\n"); + return -WD_EINVAL; + } + + c->pubkey->e.dsize = e->dsize; + memset(c->pubkey->e.data, 0, c->pubkey->e.bsize); + memcpy(c->pubkey->e.data, e->data, e->dsize); + } + + if (n) { + if (n->dsize > c->pubkey->key_size || !n->data) { + WD_ERR("n err in set rsa public key!\n"); + return -WD_EINVAL; + } + + c->pubkey->n.dsize = n->dsize; + memset(c->pubkey->n.data, 0, c->pubkey->n.bsize); + memcpy(c->pubkey->n.data, n->data, n->dsize); + } + return WD_SUCCESS; +} + +void wcrypto_get_rsa_pubkey_params(struct wcrypto_rsa_pubkey *pbk, struct wd_dtb **e, + struct wd_dtb **n) +{ + if (!pbk) { + WD_ERR("input NULL in get rsa public key!\n"); + return; + } + if (e) + *e = &pbk->e; + + if (n) + *n = &pbk->n; +} + +int wcrypto_set_rsa_prikey_params(void *ctx, struct wd_dtb *d, struct wd_dtb *n) +{ + struct wcrypto_rsa_prikey1 *pkey1; + struct wcrypto_rsa_ctx *c = ctx; + + if (!ctx || wcrypto_rsa_is_crt(ctx)) { + WD_ERR("ctx err in set rsa private key1!\n"); + return -WD_EINVAL; + } + pkey1 = &c->prikey->pkey1; + if (d) { + if (d->dsize > pkey1->key_size || !d->data) { + WD_ERR("d err in set rsa private key1!\n"); + return -WD_EINVAL; + } + + pkey1->d.dsize = d->dsize; + memset(pkey1->d.data, 0, pkey1->d.bsize); + memcpy(pkey1->d.data, d->data, d->dsize); + } + if (n) { + if (n->dsize > pkey1->key_size || !n->data) { + WD_ERR("en err in set rsa private key1!\n"); + return -WD_EINVAL; + } + + pkey1->n.dsize = n->dsize; + memset(pkey1->n.data, 0, pkey1->n.bsize); + memcpy(pkey1->n.data, n->data, n->dsize); + } + return WD_SUCCESS; +} + +void wcrypto_get_rsa_prikey_params(struct wcrypto_rsa_prikey *pvk, struct wd_dtb **d, + struct wd_dtb **n) +{ + struct wcrypto_rsa_prikey1 *pkey1; + + if (!pvk) { + WD_ERR("pvk is NULL!\n"); + return; + } + + pkey1 = &pvk->pkey1; + + if (d) + *d = &pkey1->d; + if (n) + *n = &pkey1->n; +} + +static int rsa_set_param(struct wd_dtb *src, struct wd_dtb *dst) +{ + if (!src || !dst || dst->dsize > src->bsize) + return -WD_EINVAL; + + src->dsize = dst->dsize; + memset(src->data, 0, src->bsize); + memcpy(src->data, dst->data, dst->dsize); + + return WD_SUCCESS; +} + +static int rsa_prikey2_param_set(struct wcrypto_rsa_prikey2 *pkey2, + struct wd_dtb *param, + enum wcrypto_rsa_crt_prikey_para type) +{ + int ret; + + if (param->dsize > pkey2->key_size || !param->data) + return -WD_EINVAL; + + switch (type) { + case WD_CRT_PRIKEY_DQ: + ret = rsa_set_param(&pkey2->dq, param); + break; + + case WD_CRT_PRIKEY_DP: + ret = rsa_set_param(&pkey2->dp, param); + break; + + case WD_CRT_PRIKEY_QINV: + ret = rsa_set_param(&pkey2->qinv, param); + break; + + case WD_CRT_PRIKEY_P: + ret = rsa_set_param(&pkey2->p, param); + break; + + case WD_CRT_PRIKEY_Q: + ret = rsa_set_param(&pkey2->q, param); + break; + } + + return ret; +} + +int wcrypto_set_rsa_crt_prikey_params(void *ctx, struct wd_dtb *dq, + struct wd_dtb *dp, struct wd_dtb *qinv, + struct wd_dtb *q, struct wd_dtb *p) +{ + struct wcrypto_rsa_prikey2 *pkey2; + struct wcrypto_rsa_ctx *c = ctx; + int ret = -WD_EINVAL; + + if (!ctx || !wcrypto_rsa_is_crt(ctx)) { + WD_ERR("ctx err in set rsa crt private key2!\n"); + return ret; + } + + if (!dq || !dp || !qinv || !q || !p) { + WD_ERR("para err in set rsa crt private key2!\n"); + return ret; + } + + pkey2 = &c->prikey->pkey2; + ret = rsa_prikey2_param_set(pkey2, dq, WD_CRT_PRIKEY_DQ); + if (ret) { + WD_ERR("dq err in set rsa private key2!\n"); + return ret; + } + + ret = rsa_prikey2_param_set(pkey2, dp, WD_CRT_PRIKEY_DP); + if (ret) { + WD_ERR("dp err in set rsa private key2!\n"); + return ret; + } + + ret = rsa_prikey2_param_set(pkey2, qinv, WD_CRT_PRIKEY_QINV); + if (ret) { + WD_ERR("qinv err in set rsa private key2!\n"); + return ret; + } + + ret = rsa_prikey2_param_set(pkey2, q, WD_CRT_PRIKEY_Q); + if (ret) { + WD_ERR("q err in set rsa private key2!\n"); + return ret; + } + + ret = rsa_prikey2_param_set(pkey2, p, WD_CRT_PRIKEY_P); + if (ret) { + WD_ERR("p err in set rsa private key2!\n"); + return ret; + } + + return WD_SUCCESS; +} + +void wcrypto_get_rsa_crt_prikey_params(struct wcrypto_rsa_prikey *pvk, + struct wd_dtb **dq, + struct wd_dtb **dp, struct wd_dtb **qinv, + struct wd_dtb **q, struct wd_dtb **p) +{ + struct wcrypto_rsa_prikey2 *pkey2; + + if (!pvk) { + WD_ERR("pvk is NULL!\n"); + return; + } + + pkey2 = &pvk->pkey2; + + if (dq) + *dq = &pkey2->dq; + if (dp) + *dp = &pkey2->dp; + if (qinv) + *qinv = &pkey2->qinv; + if (q) + *q = &pkey2->q; + if (p) + *p = &pkey2->p; +} + +void wcrypto_get_rsa_pubkey(void *ctx, struct wcrypto_rsa_pubkey **pubkey) +{ + if (!ctx || !pubkey) { + WD_ERR("parameter is NULL!\n"); + return; + } + + *pubkey = ((struct wcrypto_rsa_ctx *)ctx)->pubkey; +} + +void wcrypto_get_rsa_prikey(void *ctx, struct wcrypto_rsa_prikey **prikey) +{ + if (!ctx || !prikey) { + WD_ERR("parameter is NULL!\n"); + return; + } + + *prikey = ((struct wcrypto_rsa_ctx *)ctx)->prikey; +} + +static int rsa_request_init(struct wcrypto_rsa_msg *req, struct wcrypto_rsa_op_data *op, + struct wcrypto_rsa_ctx *c) +{ + __u8 *key = NULL; + + req->in = op->in; + req->in_bytes = (__u16)op->in_bytes; + req->out = op->out; + req->out_bytes = (__u16)op->out_bytes; + req->op_type = op->op_type; + req->result = WD_EINVAL; + + switch (req->op_type) { + case WCRYPTO_RSA_SIGN: + key = (__u8 *)c->prikey; + break; + case WCRYPTO_RSA_VERIFY: + key = (__u8 *)c->pubkey; + break; + case WCRYPTO_RSA_GENKEY: + key = (__u8 *)op->in; + break; + default: + WD_ERR("rsa request op type err!\n"); + return -WD_EINVAL; + } + + if (unlikely(!key)) { + WD_ERR("rsa request key null!\n"); + return -WD_EINVAL; + } + + if (req->op_type == WCRYPTO_RSA_SIGN || + req->op_type == WCRYPTO_RSA_VERIFY) { + if (unlikely(req->in_bytes != c->key_size)) { + WD_ERR("sign or verf in_bytes != key_size!\n"); + return -WD_EINVAL; + } + } + + req->key = key; + + return WD_SUCCESS; +} + +static int do_rsa_prepare(struct wcrypto_rsa_ctx *ctxt, + struct wcrypto_rsa_op_data *opdata, + struct wcrypto_rsa_cookie **cookie_addr, + struct wcrypto_rsa_msg **req_addr, + void *tag) +{ + struct wcrypto_rsa_cookie *cookie; + struct wcrypto_rsa_msg *req; + int ret; + + if (unlikely(!ctxt || !opdata)) { + WD_ERR("input parameter err!\n"); + return -WD_EINVAL; + } + + if (unlikely(tag && !ctxt->setup.cb)) { + WD_ERR("ctx call back is null!\n"); + return -WD_EINVAL; + } + + ret = wd_get_cookies(&ctxt->pool, (void **)&cookie, 1); + if (ret) + return ret; + + if (tag) + cookie->tag.tag = tag; + + req = &cookie->msg; + ret = rsa_request_init(req, opdata, ctxt); + if (unlikely(ret)) { + wd_put_cookies(&ctxt->pool, (void **)&cookie, 1); + return ret; + } + + *cookie_addr = cookie; + *req_addr = req; + + return 0; +} + +static int rsa_send(struct wcrypto_rsa_ctx *ctx, struct wcrypto_rsa_msg *req) +{ + uint32_t tx_cnt = 0; + int ret; + + do { + ret = wd_send(ctx->q, req); + if (!ret) { + break; + } else if (ret == -WD_EBUSY) { + if (tx_cnt++ > RSA_RESEND_CNT) { + WD_ERR("do rsa send cnt %u, exit!\n", tx_cnt); + break; + } + + usleep(1); + } else { + WD_ERR("do rsa wd_send err!\n"); + break; + } + } while (true); + + return ret; +} + +int wcrypto_do_rsa(void *ctx, struct wcrypto_rsa_op_data *opdata, void *tag) +{ + struct wcrypto_rsa_msg *resp = NULL; + struct wcrypto_rsa_ctx *ctxt = ctx; + struct wcrypto_rsa_cookie *cookie; + struct wcrypto_rsa_msg *req; + uint32_t rx_cnt = 0; + int ret; + + ret = do_rsa_prepare(ctxt, opdata, &cookie, &req, tag); + if (unlikely(ret)) + return ret; + + ret = rsa_send(ctxt, req); + if (unlikely(ret)) + goto fail_with_cookie; + + if (tag) + return ret; + + resp = (void *)(uintptr_t)ctxt->ctx_id; + do { + ret = wd_recv(ctxt->q, (void **)&resp); + if (ret > 0) { + break; + } else if (!ret) { + if (unlikely(rx_cnt++ >= RSA_RECV_MAX_CNT)) { + WD_ERR("failed to recv: timeout!\n"); + ret = -WD_ETIMEDOUT; + goto fail_with_cookie; + } + + if (balance > RSA_BALANCE_THRHD) + usleep(1); + } else { + WD_ERR("do rsa wd_recv err!\n"); + goto fail_with_cookie; + } + } while (true); + + balance = rx_cnt; + opdata->out = (void *)resp->out; + opdata->out_bytes = resp->out_bytes; + opdata->status = resp->result; + ret = GET_NEGATIVE(opdata->status); + +fail_with_cookie: + wd_put_cookies(&ctxt->pool, (void **)&cookie, 1); + return ret; +} + +int wcrypto_rsa_poll(struct wd_queue *q, unsigned int num) +{ + struct wcrypto_rsa_msg *resp = NULL; + struct wcrypto_rsa_ctx *ctx; + struct wcrypto_cb_tag *tag; + unsigned int tmp = num; + int count = 0; + int ret; + + if (unlikely(!q)) { + WD_ERR("q is NULL!\n"); + return -WD_EINVAL; + } + + do { + ret = wd_recv(q, (void **)&resp); + if (ret == 0) + break; + else if (unlikely(ret < 0)) { + WD_ERR("recv err at rsa poll!\n"); + return ret; + } + count++; + tag = (void *)(uintptr_t)resp->usr_data; + ctx = tag->ctx; + ctx->setup.cb(resp, tag->tag); + wd_put_cookies(&ctx->pool, (void **)&tag, 1); + resp = NULL; + } while (--tmp); + + return count; +} + +void wcrypto_del_rsa_ctx(void *ctx) +{ + struct wcrypto_rsa_ctx_setup *st; + struct wcrypto_rsa_ctx *cx; + struct q_info *qinfo; + + if (!ctx) { + WD_ERR("delete rsa parameter err!\n"); + return; + } + + cx = ctx; + st = &cx->setup; + qinfo = cx->q->qinfo; + + wd_uninit_cookie_pool(&cx->pool); + wd_spinlock(&qinfo->qlock); + if (qinfo->ctx_num <= 0) { + wd_unspinlock(&qinfo->qlock); + WD_ERR("error: repeat del rsa ctx!\n"); + return; + } + + wd_free_id(qinfo->ctx_id, WD_MAX_CTX_NUM, cx->ctx_id - 1, + WD_MAX_CTX_NUM); + if (!(--qinfo->ctx_num)) + memset(&qinfo->br, 0, sizeof(qinfo->br)); + + wd_unspinlock(&qinfo->qlock); + del_ctx_key(st, cx); + del_ctx(cx); +} diff --git a/uadk/v1/wd_rsa.h b/uadk/v1/wd_rsa.h new file mode 100644 index 0000000..480c088 --- /dev/null +++ b/uadk/v1/wd_rsa.h @@ -0,0 +1,148 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#ifndef __WD_RSA_H +#define __WD_RSA_H + +#include +#include +#include +#include "wd.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct wcrypto_rsa_kg_in; /* rsa key generation input parameters */ +struct wcrypto_rsa_kg_out; /* rsa key generation output parameters */ +struct wcrypto_rsa_pubkey; /* rsa public key */ +struct wcrypto_rsa_prikey; /* rsa private key */ + +/* RSA operational types */ +enum wcrypto_rsa_op_type { + WCRYPTO_RSA_INVALID, /* invalid rsa operation */ + WCRYPTO_RSA_SIGN, /* RSA sign */ + WCRYPTO_RSA_VERIFY, /* RSA verify */ + WCRYPTO_RSA_GENKEY, /* RSA key generation */ +}; + +/* RSA key types */ +enum wcrypto_rsa_key_type { + WCRYPTO_RSA_INVALID_KEY, /* invalid rsa key type */ + WCRYPTO_RSA_PUBKEY, /* rsa public key type */ + WCRYPTO_RSA_PRIKEY1, /* invalid rsa private common key type */ + WCRYPTO_RSA_PRIKEY2, /* invalid rsa private CRT key type */ +}; + +/* RSA context setting up input parameters from user */ +struct wcrypto_rsa_ctx_setup { + wcrypto_cb cb; /* call back function from user */ + __u16 data_fmt; /* data format denoted by enum wd_buff_type */ + __u16 key_bits; /* RSA key bits */ + bool is_crt; /* CRT mode or not */ + struct wd_mm_br br; /* memory operations from user */ +}; + +struct wcrypto_rsa_op_data { + enum wcrypto_rsa_op_type op_type; /* rsa operation type */ + int status; /* rsa operation status */ + void *in; /* rsa operation input address, should be DMA-able */ + void *out; /* rsa operation output address, should be DMA-able */ + __u32 in_bytes; /* rsa operation input bytes */ + __u32 out_bytes; /* rsa operation output bytes */ +}; + +/* RSA message format of Warpdrive */ +struct wcrypto_rsa_msg { + __u8 alg_type:3; /* Denoted by enum wcrypto_type */ + __u8 op_type:2; /* Denoted by enum wcrypto_rsa_op_type */ + __u8 key_type:2; /* Denoted by enum wcrypto_rsa_key_type */ + __u8 data_fmt:1; /* Data format, denoted by enum wd_buff_type */ + __u8 result; /* Data format, denoted by WD error code */ + __u16 in_bytes; /* Input data bytes */ + __u16 out_bytes; /* Output data bytes */ + __u16 key_bytes; /* Input key bytes */ + __u8 *in; /* Input data VA, buf should be DMA buffer. */ + __u8 *out; /* Output data VA pointer, should be DMA buffer */ + __u8 *key; /* Input key VA pointer, should be DMA buffer */ + + /* + * Input user tag, used for identify data stream/user: + * struct wcrypto_cb_tag + */ + __u64 usr_data; +}; + +bool wcrypto_rsa_is_crt(const void *ctx); +int wcrypto_rsa_key_bits(const void *ctx); +void *wcrypto_create_rsa_ctx(struct wd_queue *q, struct wcrypto_rsa_ctx_setup *setup); +void wcrypto_get_rsa_pubkey(void *ctx, struct wcrypto_rsa_pubkey **pubkey); +void wcrypto_get_rsa_prikey(void *ctx, struct wcrypto_rsa_prikey **prikey); +int wcrypto_set_rsa_pubkey_params(void *ctx, struct wd_dtb *e, struct wd_dtb *n); +void wcrypto_get_rsa_pubkey_params(struct wcrypto_rsa_pubkey *pbk, + struct wd_dtb **e, struct wd_dtb **n); +int wcrypto_set_rsa_prikey_params(void *ctx, struct wd_dtb *d, struct wd_dtb *n); +void wcrypto_get_rsa_prikey_params(struct wcrypto_rsa_prikey *pvk, struct wd_dtb **d, + struct wd_dtb **n); +int wcrypto_set_rsa_crt_prikey_params(void *ctx, struct wd_dtb *dq, + struct wd_dtb *dp, + struct wd_dtb *qinv, + struct wd_dtb *q, + struct wd_dtb *p); +void wcrypto_get_rsa_crt_prikey_params(struct wcrypto_rsa_prikey *pvk, + struct wd_dtb **dq, struct wd_dtb **dp, + struct wd_dtb **qinv, struct wd_dtb **q, + struct wd_dtb **p); + +/* APIs For RSA key generate */ +struct wcrypto_rsa_kg_in *wcrypto_new_kg_in(void *ctx, struct wd_dtb *e, + struct wd_dtb *p, struct wd_dtb *q); +void wcrypto_del_kg_in(void *ctx, struct wcrypto_rsa_kg_in *ki); +void wcrypto_get_rsa_kg_in_params(struct wcrypto_rsa_kg_in *kin, struct wd_dtb *e, + struct wd_dtb *q, struct wd_dtb *p); + +struct wcrypto_rsa_kg_out *wcrypto_new_kg_out(void *ctx); +void wcrypto_del_kg_out(void *ctx, struct wcrypto_rsa_kg_out *kout); +void wcrypto_get_rsa_kg_out_params(struct wcrypto_rsa_kg_out *kout, + struct wd_dtb *d, + struct wd_dtb *n); +void wcrypto_get_rsa_kg_out_crt_params(struct wcrypto_rsa_kg_out *kout, + struct wd_dtb *qinv, + struct wd_dtb *dq, struct wd_dtb *dp); + +int wcrypto_rsa_kg_in_data(struct wcrypto_rsa_kg_in *ki, char **data); +int wcrypto_rsa_kg_out_data(struct wcrypto_rsa_kg_out *ko, char **data); +void wcrypto_set_rsa_kg_out_crt_psz(struct wcrypto_rsa_kg_out *kout, + size_t qinv_sz, + size_t dq_sz, + size_t dp_sz); +void wcrypto_set_rsa_kg_out_psz(struct wcrypto_rsa_kg_out *kout, + size_t d_sz, + size_t n_sz); + +/** + * This is a pair of asynchronous mode RSA API as tag is not NULL, + * or it is synchronous mode + */ +int wcrypto_do_rsa(void *ctx, struct wcrypto_rsa_op_data *opdata, void *tag); +int wcrypto_rsa_poll(struct wd_queue *q, unsigned int num); +void wcrypto_del_rsa_ctx(void *ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/uadk/v1/wd_sgl.c b/uadk/v1/wd_sgl.c new file mode 100644 index 0000000..dffbf12 --- /dev/null +++ b/uadk/v1/wd_sgl.c @@ -0,0 +1,978 @@ +/* + * Copyright 2020 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +/* SGL Memory Management (lib): A SGL memory algorithm */ +#include +#include +#include +#include + +#include "wd.h" +#include "wd_adapter.h" +#include "wd_bmm.h" +#include "wd_util.h" +#include "wd_sgl.h" + +#define __ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask)) +#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1) +#define ILLEGAL_ALIGN_SZ(x) ((((x)-1) & (x))) + +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) + +#define FLAG_SGE_CHAIN 0x01UL +#define FLAG_SGE_END 0x02UL +#define FLAG_MERGED_SGL (uintptr_t)1 + +#define SGL_NUM_MAX 2048 +#define SGE_NUM_MAX 60 +#define SGL_NUM 2 +#define BUF_SIZE_MAX 2048 +#define ALIGN_SIZE_MIN 0x8 +#define ALIGN_SIZE_MAX 0x800 +#define ALIGN_SIZE 64 + +struct wd_sge { + /* 'priv' is used by driver, which may be a hardware sgl address */ + void *priv; + void *buf; + __u32 data_len; + __u32 flag; + void *sgl; +}; + +struct wd_sgl { + /* 'priv' is hardware sgl address */ + void *priv; + __u8 sge_num; + __u8 buf_num; + __u16 buf_sum; + __u32 sum_data_bytes; + + struct wd_sglpool *pool; + struct wd_sgl *next; + + /* user configuration, 60 sges max */ + struct wd_sge sge[]; +}; + +struct wd_sglpool { + struct wd_queue *q; + struct wd_lock sgl_lock; + + /* get 'act_align_sz' from hardware's 'align_sz' and user's 'align_sz' */ + __u32 act_align_sz; + __u32 act_buf_sz; + __u32 act_buf_num; + size_t sgl_mem_sz; + + /* Unused sgl/buffer number in the pool */ + __u32 free_sgl_num; + __u32 alloc_failures; + __u32 free_buf_num; + + struct wd_blkpool *buf_pool; + struct wd_blkpool *sgl_pool; + struct wd_sgl **sgl_blk; + /* used for driver to 'alloc' and 'dma_map' in 'buf_pool' */ + struct wd_mm_br buf_br; + + struct wd_sglpool_setup setup; +}; + +static void sgl_init(struct wd_sgl *sgl, struct wd_sglpool *pool) +{ + struct wd_sglpool_setup *sp = &pool->setup; + + sgl->sge_num = sp->sge_num_in_sgl; + sgl->buf_num = sp->buf_num_in_sgl; + sgl->buf_sum = sp->buf_num_in_sgl; + sgl->sum_data_bytes = 0; + sgl->next = NULL; + sgl->priv = NULL; + sgl->pool = pool; +} + +static void sgl_sge_init(struct wd_sgl *sgl, __u8 num, void *buf) +{ + sgl->sge[num].buf = buf; + sgl->sge[num].data_len = 0; + sgl->sge[num].sgl = sgl; + + if (num != sgl->pool->setup.buf_num_in_sgl - 1) + sgl->sge[num].flag &= ~FLAG_SGE_END; + else + sgl->sge[num].flag |= FLAG_SGE_END; + + sgl->sge[num].flag &= ~FLAG_SGE_CHAIN; +} + +static int sgl_chain_build(struct wd_queue *q, struct wd_sglpool *pool) +{ + struct wd_sglpool_setup *sp = &pool->setup; + struct wd_mm_br br = pool->buf_br; + struct wd_sgl **sgl_blk; + int ret = -WD_ENOMEM; + int i, j, m, n; + void *buf; + + sgl_blk = calloc(sp->sgl_num, sizeof(struct wd_sgl *)); + if (!sgl_blk) + return ret; + + for (i = 0; i < sp->sgl_num; i++) { + sgl_blk[i] = wd_alloc_blk(pool->sgl_pool); + if (!sgl_blk[i]) { + WD_ERR("alloc for sgl failed !\n"); + goto alloc_sgl_err; + } + + sgl_init(sgl_blk[i], pool); + + for (j = 0; j < sgl_blk[i]->buf_num; j++) { + buf = br.alloc(br.usr, sp->buf_size); + if (!buf) { + WD_ERR("alloc for sgl_buf failed, j = %d!\n", j); + goto alloc_buf_err; + } + sgl_sge_init(sgl_blk[i], j, buf); + } + + ret = drv_init_sgl(q, pool, sgl_blk[i]); + if (ret) { + i++; + WD_ERR("initialize hardware sgl failed, ret = %d\n", ret); + goto alloc_sgl_err; + } + } + + for (m = i - 1; m >= 0; m--) + wd_free_blk(pool->sgl_pool, sgl_blk[m]); + + pool->sgl_blk = sgl_blk; + return WD_SUCCESS; + +alloc_buf_err: + for (n = j - 1; n >= 0; n--) + br.free(br.usr, sgl_blk[i]->sge[n].buf); + wd_free_blk(pool->sgl_pool, sgl_blk[i]); +alloc_sgl_err: + for (m = i - 1; m >= 0; m--) { + for (n = sgl_blk[m]->buf_num - 1; n >= 0; n--) + br.free(br.usr, sgl_blk[m]->sge[n].buf); + if (sgl_blk[m]->priv) + drv_uninit_sgl(q, pool, sgl_blk[m]); + wd_free_blk(pool->sgl_pool, sgl_blk[m]); + } + + free(sgl_blk); + return ret; +} + +static void *sgl_buf_pool_init(struct wd_queue *q, struct wd_sglpool *pool) +{ + struct wd_sglpool_setup *sp = &pool->setup; + struct wd_blkpool_setup blk_setup; + void *p; + + blk_setup.block_size = pool->act_buf_sz; + blk_setup.block_num = pool->act_buf_num + sp->sgl_num; + blk_setup.align_size = pool->act_align_sz; + memcpy(&blk_setup.br, &sp->br, sizeof(struct wd_mm_br)); + + p = wd_blkpool_create(q, &blk_setup); + if (!p) { + WD_ERR("wd failed to create block pool for buffers!\n"); + return NULL; + } + + pool->buf_br.alloc = (void *)wd_alloc_blk; + pool->buf_br.free = (void *)wd_free_blk; + pool->buf_br.iova_map = (void *)wd_blk_iova_map; + pool->buf_br.iova_unmap = (void *)wd_blk_iova_unmap; + pool->buf_br.get_bufsize = (void *)wd_blksize; + pool->buf_br.usr = p; + + return p; +} + +static void *sgl_mem_alloc(void *usr, size_t size) +{ + return calloc(1, size); +} + +static void sgl_mem_free(void *usr, void *va) +{ + free(va); +} + +static void *sgl_mem_iova_map(void *usr, void *va, size_t sz) +{ + /* DMA address is not needed, 'return' is only for format. */ + return va; +} + +static void sgl_mem_iova_unmap(void *usr, void *va, void *dma, size_t sz) +{ + /* do nothing */ +} + +static void *sgl_blk_pool_init(struct wd_queue *q, struct wd_sglpool *pool) +{ + struct wd_sglpool_setup *sgl_sp = &pool->setup; + struct wd_blkpool_setup sp; + __u32 asz; + + asz = sgl_sp->align_size; + + sp.br.alloc = sgl_mem_alloc; + sp.br.free = sgl_mem_free; + sp.br.iova_map = sgl_mem_iova_map; + sp.br.iova_unmap = sgl_mem_iova_unmap; + sp.align_size = ALIGN_SIZE; + sp.block_num = sgl_sp->sgl_num; + sp.block_size = ALIGN(sizeof(struct wd_sgl), asz) + + sgl_sp->sge_num_in_sgl * ALIGN(sizeof(struct wd_sge), asz); + + return wd_blkpool_create(q, &sp); +} + +static void sgl_blk_pool_uninit(void *sgl_pool) +{ + wd_blkpool_destroy(sgl_pool); +} + +static void sgl_buf_pool_uninit(void *buf_pool) +{ + wd_blkpool_destroy(buf_pool); +} + +static int sgl_pool_init(struct wd_queue *q, struct wd_sglpool *pool) +{ + struct wd_sglpool_setup sp = pool->setup; + void *sgl_pool, *buf_pool; + int ret = -WD_ENOMEM; + + sgl_pool = sgl_blk_pool_init(q, pool); + if (!sgl_pool) { + WD_ERR("failed to create wd sgl pool.\n"); + return ret; + } + pool->sgl_pool = sgl_pool; + + buf_pool = sgl_buf_pool_init(q, pool); + if (!buf_pool) { + WD_ERR("failed to create hardware buf pool.\n"); + goto err; + } + pool->buf_pool = buf_pool; + + ret = sgl_chain_build(q, pool); + if (ret) { + WD_ERR("failed to build sgl chain, ret = %d.\n", ret); + sgl_buf_pool_uninit(buf_pool); + goto err; + } + + pool->q = q; + wd_get_free_blk_num(buf_pool, &pool->free_buf_num); + pool->free_buf_num = MIN(pool->free_buf_num, + sp.buf_num - sp.sgl_num * sp.buf_num_in_sgl); + + ret = wd_blk_alloc_failures(sgl_pool, &pool->alloc_failures); + if (ret != WD_SUCCESS) { + WD_ERR("wd blk alloc failures failed, ret = %d.\n", ret); + goto err; + } + + pool->free_sgl_num = pool->setup.sgl_num; + pool->sgl_mem_sz = sp.buf_num_in_sgl * sp.buf_size; + + return WD_SUCCESS; +err: + sgl_blk_pool_uninit(sgl_pool); + return ret; +} + +static int sgl_params_check(struct wd_sglpool_setup *setup) +{ + struct wd_sglpool_setup *sp = setup; + __u32 buf_num_need; + + if (!sp->buf_num || !sp->sgl_num || !sp->sge_num_in_sgl || + !sp->buf_num_in_sgl || sp->buf_size < BUF_SIZE_MAX || + sp->buf_num_in_sgl > sp->sge_num_in_sgl || + sp->sgl_num > SGL_NUM_MAX || sp->sge_num_in_sgl > SGE_NUM_MAX) { + WD_ERR("invalid size or num in sgl!\n"); + return -WD_EINVAL; + } + + if (sp->align_size < ALIGN_SIZE_MIN || sp->align_size > ALIGN_SIZE_MAX || + ILLEGAL_ALIGN_SZ(sp->align_size)) { + WD_ERR("invalid align_size, %u!\n", sp->align_size); + return -WD_EINVAL; + } + + buf_num_need = sp->sgl_num * sp->buf_num_in_sgl; + if (sp->buf_num < buf_num_need) { + WD_ERR("'buf_num' u need at least is <%u>!\n", buf_num_need); + return -WD_EINVAL; + } + + return WD_SUCCESS; +} + +static int sgl_hw_params_check(struct hw_sgl_info *hw_sgl_info) +{ + struct hw_sgl_info *info = hw_sgl_info; + + if (info->sge_align_sz < ALIGN_SIZE_MIN || + info->sge_align_sz > ALIGN_SIZE_MAX || + ILLEGAL_ALIGN_SZ(info->sge_align_sz)) { + WD_ERR("invalid sge align size: %u!\n", info->sge_align_sz); + return -WD_EINVAL; + } + + if (info->sgl_align_sz < ALIGN_SIZE_MIN || + info->sgl_align_sz > ALIGN_SIZE_MAX || + ILLEGAL_ALIGN_SZ(info->sgl_align_sz)) { + WD_ERR("invalid sgl align size: %u!\n", info->sgl_align_sz); + return -WD_EINVAL; + } + + return WD_SUCCESS; +} + +static int sgl_pool_pre_layout(struct wd_sglpool *p, struct wd_sglpool_setup *sp, + struct hw_sgl_info *hw_sgl_info) +{ + __u32 hw_sgl_size; + int ret; + + ret = sgl_params_check(sp); + if (ret) + return ret; + + ret = sgl_hw_params_check(hw_sgl_info); + if (ret) + return ret; + + p->act_align_sz = MAX(sp->align_size, hw_sgl_info->sge_align_sz); + p->act_align_sz = MAX(p->act_align_sz, hw_sgl_info->sgl_align_sz); + + p->act_buf_sz = ALIGN(sp->buf_size, p->act_align_sz); + + hw_sgl_size = hw_sgl_info->sgl_sz + + sp->sge_num_in_sgl * hw_sgl_info->sge_sz; + hw_sgl_size = ALIGN(hw_sgl_size, p->act_align_sz); + if (sp->buf_size < hw_sgl_size) { + WD_ERR("'buf_size' should be lager than (%u)!\n", hw_sgl_size); + return -WD_EINVAL; + } + +/* 'buf_num = 1.15 * buf_num' is needed in 'wd_blkpool_create' to create pool */ +#define NUM_TIMES(x) (100 * (x) / 87) + p->act_buf_num = NUM_TIMES(sp->buf_num); + + return WD_SUCCESS; +} + +void *wd_sglpool_create(struct wd_queue *q, struct wd_sglpool_setup *setup) +{ + struct hw_sgl_info hw_sgl_info; + struct wd_sglpool *pool; + int ret; + + if (!q || !setup) { + WD_ERR("q or setup is NULL.\n"); + return NULL; + } + + ret = drv_get_sgl_info(q, &hw_sgl_info); + if (ret) { + WD_ERR("get hardware sgl size err, ret = %d.\n", ret); + return NULL; + } + + pool = calloc(1, sizeof(*pool)); + if (!pool) { + WD_ERR("failed to malloc pool!\n"); + return NULL; + } + + ret = sgl_pool_pre_layout(pool, setup, &hw_sgl_info); + if (ret) + goto err_pool_alloc; + + memcpy(&pool->setup, setup, sizeof(*setup)); + + if (sgl_pool_init(q, pool)) + goto err_pool_alloc; + + return pool; + +err_pool_alloc: + free(pool); + return NULL; +} + +void wd_sglpool_destroy(void *pool) +{ + struct wd_sglpool *p = pool; + struct wd_sglpool_setup sp; + struct wd_sgl *sgl; + int i, j; + + if (!p || !p->sgl_blk || !p->buf_pool || !p->sgl_pool) { + WD_ERR("pool parameter is err!\n"); + return; + } + + sp = p->setup; + if (p->free_sgl_num != sp.sgl_num) { + WD_ERR("sgl is still in use!\n"); + return; + } + + for (i = 0; i < sp.sgl_num; i++) { + sgl = p->sgl_blk[i]; + drv_uninit_sgl(p->q, pool, sgl); + + for (j = 0; j < sp.buf_num_in_sgl; j++) + wd_free_blk(p->buf_pool, sgl->sge[j].buf); + } + + wd_blkpool_destroy(p->sgl_pool); + p->sgl_pool = NULL; + wd_blkpool_destroy(p->buf_pool); + p->buf_pool = NULL; + free(p->sgl_blk); + p->sgl_blk = NULL; + + free(p); +} + +struct wd_sgl *wd_alloc_sgl(void *pool, __u32 size) +{ + struct wd_sglpool *p = pool; + struct wd_sgl *sg1, *sg2; + int ret; + + if (unlikely(!p || !size)) { + WD_ERR("pool is null!\n"); + return NULL; + } + + if (size > p->sgl_mem_sz * SGL_NUM) { + WD_ERR("Size you need is bigger than a 2 * SGL!\n"); + return NULL; + } + + sg1 = wd_alloc_blk(p->sgl_pool); + if (!sg1) { + WD_ERR("alloc for sg1 failed!\n"); + __atomic_add_fetch(&p->alloc_failures, 1, __ATOMIC_RELAXED); + return NULL; + } + + __atomic_sub_fetch(&p->free_sgl_num, 1, __ATOMIC_RELAXED); + + if (size > p->sgl_mem_sz) { + sg2 = wd_alloc_blk(p->sgl_pool); + if (!sg2) { + WD_ERR("alloc for sg2 failed!\n"); + __atomic_add_fetch(&p->alloc_failures, 1, + __ATOMIC_RELAXED); + return NULL; + } + __atomic_sub_fetch(&p->free_sgl_num, 1, __ATOMIC_RELAXED); + + ret = wd_sgl_merge(sg1, sg2); + if (ret) { + WD_ERR("merge two sgls failed for u!, ret = %d.\n", ret); + return NULL; + } + } + + return sg1; +} + +void wd_free_sgl(void *pool, struct wd_sgl *sgl) +{ + struct wd_sglpool *p = pool; + struct wd_sgl *tmp = sgl; + struct wd_sgl *next; + int i; + + if (unlikely(!p || !tmp || !p->sgl_pool)) { + WD_ERR("pool or sgl or p->sgl_pool is null!\n"); + return; + } + + if (unlikely((uintptr_t)tmp->next & FLAG_MERGED_SGL)) { + WD_ERR("This is a merged sgl, u cannot free it!\n"); + return; + } + + do { + next = tmp->next; + tmp->buf_sum = tmp->buf_num; + tmp->next = NULL; + tmp->sum_data_bytes = 0; + for (i = 0; i < tmp->buf_num; i++) + tmp->sge[i].data_len = 0; + + /* have to update current 'wd_sgl' before free it */ + wd_free_blk(p->sgl_pool, tmp); + wd_get_free_blk_num(p->sgl_pool, &p->free_sgl_num); + next = (struct wd_sgl *)((uintptr_t)next & (~FLAG_MERGED_SGL)); + tmp = next; + } while (next); +} + +/* Merge two SGLs (dst_sgl, src_sgl) into 'dst_sgl' */ +int wd_sgl_merge(struct wd_sgl *dst_sgl, struct wd_sgl *src_sgl) +{ + struct wd_sglpool *dst_pool, *src_pool; + int ret; + + if (unlikely(!dst_sgl || !src_sgl || dst_sgl == src_sgl)) { + WD_ERR("dst_sgl or src_sgl is null, or they are the same!\n"); + return -WD_EINVAL; + } + + if (unlikely(dst_sgl->next || src_sgl->next)) { + WD_ERR("dst_sgl or src_sgl has two sgls!\n"); + return -WD_EINVAL; + } + + dst_pool = dst_sgl->pool; + src_pool = src_sgl->pool; + if (unlikely(!dst_pool || !src_pool || dst_pool != src_pool || + dst_sgl->sge_num != src_sgl->sge_num)) { + WD_ERR("dst_sgl or src_sgl is error!\n"); + return -WD_EINVAL; + } + + dst_sgl->sge[dst_sgl->buf_num].flag |= FLAG_SGE_CHAIN; + dst_sgl->buf_sum += src_sgl->buf_sum; + src_sgl->next = (struct wd_sgl *)((uintptr_t)src_sgl->next | FLAG_MERGED_SGL); + + ret = drv_sgl_merge(dst_pool->q, dst_pool, dst_sgl, src_sgl); + if (ret) + return ret; + + dst_sgl->next = src_sgl; + return WD_SUCCESS; +} + +static void sgl_cp_to_pbuf(struct wd_sgl *src_sgl, int start_sg, int strtad, + void *buf, size_t sgl_sz) +{ + __u32 sz = src_sgl->pool->setup.buf_size; + __u32 act_sz = MIN(sgl_sz, sz - strtad); + struct wd_sgl *sgl = src_sgl; + int strtsg = start_sg; + size_t size = sgl_sz; + struct wd_sgl *next; + void *pbuf = buf; + int i; + + next = (struct wd_sgl *)((uintptr_t)sgl->next & (~FLAG_MERGED_SGL)); + if (strtsg >= sgl->buf_num) { + strtsg = strtsg - sgl->buf_num; + sgl = next; + } + + memcpy(pbuf, sgl->sge[strtsg].buf + strtad, act_sz); + if (act_sz == size) + return; + + size -= sz - strtad; + pbuf += sz - strtad; + for (i = strtsg + 1; i <= sgl->buf_num - 1 && size > sz; i++) { + memcpy(pbuf + (i - strtsg - 1) * sz, sgl->sge[i].buf, sz); + size -= sz; + } + + if (i <= sgl->buf_num - 1) { + memcpy(pbuf + (i - strtsg - 1) * sz, sgl->sge[i].buf, size); + } else { + sgl = next; + for (i = 0; i < sgl->buf_num - 1 && size > sz; i++) { + memcpy(pbuf + (i + sgl->buf_num - strtsg - 1) * sz, + sgl->sge[i].buf, sz); + size -= sz; + } + memcpy(pbuf + (i + sgl->buf_num - strtsg - 1) * sz, + sgl->sge[i].buf, size); + } +} + +/* + * Copy the 'size' bytes in 'pbuf' from the SGL at the start address of 'offset' + * Return: + * = 0:copy size bytes from SGL to pbuf successfully; + * > 0:copy the return value bytes from SGL to pbuf successfully; + * < 0: failing, and copy nothing; + */ +int wd_sgl_cp_to_pbuf(struct wd_sgl *sgl, size_t offset, void *pbuf, size_t size) +{ + size_t strtsg, strtad, sz; + __u32 buf_sz; + + if (unlikely(!sgl || !pbuf || !sgl->pool || !size || !sgl->buf_num || + !sgl->pool->setup.buf_size)) { + WD_ERR("sgl or size is null, or sgl is not a legal sgl!\n"); + return -WD_EINVAL; + } + + sz = sgl->pool->sgl_mem_sz; + ((uintptr_t)sgl->next & (~FLAG_MERGED_SGL)) ? sz <<= 1 : sz; + if (unlikely(offset >= sz)) { + WD_ERR("'offset' is out of memory!\n"); + return -WD_EINVAL; + } + + buf_sz = sgl->pool->setup.buf_size; + strtsg = offset / buf_sz; + strtad = offset % buf_sz; + + if (sz - offset < size) { + sgl_cp_to_pbuf(sgl, strtsg, strtad, pbuf, sz - offset); + return sz - offset; + } + + sgl_cp_to_pbuf(sgl, strtsg, strtad, pbuf, size); + return 0; +} + +static void sgl_cp_from_pbuf(struct wd_sgl *dst_sgl, int start_sg, int strtad, + void *buf, size_t mem_sz) +{ + __u32 sz = dst_sgl->pool->setup.buf_size; + __u32 act_sz = MIN(mem_sz, sz - strtad); + struct wd_sgl *sgl = dst_sgl; + int strtsg = start_sg; + size_t size = mem_sz; + struct wd_sgl *next; + void *pbuf = buf; + int i; + + next = (struct wd_sgl *)((uintptr_t)sgl->next & (~FLAG_MERGED_SGL)); + if (strtsg >= sgl->buf_num) { + for (i = 0; i < sgl->buf_num; i++) + sgl->sge[i].data_len = sz; + strtsg = strtsg - sgl->buf_num; + sgl = next; + } + for (i = 0; i < strtsg; i++) + sgl->sge[i].data_len = sz; + + memcpy(sgl->sge[strtsg].buf + strtad, pbuf, act_sz); + sgl->sge[strtsg].data_len = strtad + act_sz; + if (act_sz == size) + return; + + size -= sz - strtad; + pbuf += sz - strtad; + for (i = strtsg + 1; i <= sgl->buf_num - 1 && size > sz; i++) { + memcpy(sgl->sge[i].buf, pbuf + (i - strtsg - 1) * sz, sz); + sgl->sge[i].data_len = sz; + size -= sz; + } + + if (i <= sgl->buf_num - 1) { + memcpy(sgl->sge[i].buf, pbuf + (i - strtsg - 1) * sz, size); + } else { + sgl = next; + for (i = 0; i < sgl->buf_num - 1 && size > sz; i++) { + memcpy(sgl->sge[i].buf, + pbuf + (i + sgl->buf_num - strtsg - 1) * sz, sz); + sgl->sge[i].data_len = sz; + size -= sz; + } + memcpy(sgl->sge[i].buf, + pbuf + (i + sgl->buf_num - strtsg - 1) * sz, size); + } + sgl->sge[i].data_len = size; +} + +int wd_sgl_cp_from_pbuf(struct wd_sgl *sgl, size_t offset, void *pbuf, size_t size) +{ + size_t strtsg, strtad, sz; + uintptr_t next; + __u32 buf_sz; + int i; + + if (unlikely(!sgl || !pbuf || !sgl->pool || !size || !sgl->buf_num || + !sgl->pool->setup.buf_size)) { + WD_ERR("sgl or size is null, or sgl is not a legal sgl!\n"); + return -WD_EINVAL; + } + + sz = sgl->pool->sgl_mem_sz; + next = (uintptr_t)sgl->next & (~FLAG_MERGED_SGL); + next ? sz <<= 1 : sz; + + if (unlikely(offset >= sz)) { + WD_ERR("'offset' is out of memory!\n"); + return -WD_EINVAL; + } + + buf_sz = sgl->pool->setup.buf_size; + strtsg = offset / buf_sz; + strtad = offset % buf_sz; + + for (i = 0; i < sgl->buf_num; i++) + sgl->sge[i].data_len = 0; + + if (next) { + for (i = 0; i < sgl->buf_num; i++) + ((struct wd_sgl *)next)->sge[i].data_len = 0; + ((struct wd_sgl *)next)->sum_data_bytes = 0; + } + + if (sz - offset < size) { + sgl_cp_from_pbuf(sgl, strtsg, strtad, pbuf, sz - offset); + sgl->sum_data_bytes = sz; + return sz - offset; + } + + sgl_cp_from_pbuf(sgl, strtsg, strtad, pbuf, size); + sgl->sum_data_bytes = offset + size; + return 0; +} + +void *wd_sgl_iova_map(void *pool, struct wd_sgl *sgl, size_t sz) +{ + struct wd_sglpool *p = pool; + + if (unlikely(!p || !sgl)) { + WD_ERR("pool or sgl is null!\n"); + return NULL; + } + + return (void *)((uintptr_t)wd_blk_iova_map(p->buf_pool, sgl->priv)); +} + +void wd_sgl_iova_unmap(void *pool, void *sgl_iova, struct wd_sgl *sgl) +{ + /* do nothing */ +} + +void *wd_get_last_sge_buf(struct wd_sgl *sgl) +{ + struct wd_sgl *tmp = sgl; + uintptr_t next; + + if (unlikely(!tmp || !tmp->buf_num)) { + WD_ERR("sgl or buf_num in sgl is null!\n"); + return NULL; + } + + next = (uintptr_t)tmp->next & (~FLAG_MERGED_SGL); + if (next) + tmp = (struct wd_sgl *)next; + + return tmp->sge[tmp->buf_num - 1].buf; +} + +void *wd_get_first_sge_buf(struct wd_sgl *sgl) +{ + if (unlikely(!sgl)) { + WD_ERR("sgl is null!\n"); + return NULL; + } + + return sgl->sge[0].buf; +} + +int wd_get_sgl_sge_num(struct wd_sgl *sgl) +{ + if (unlikely(!sgl)) { + WD_ERR("sgl is null!\n"); + return -WD_EINVAL; + } + + return sgl->sge_num; +} + +int wd_get_sgl_buf_num(struct wd_sgl *sgl) +{ + if (unlikely(!sgl)) { + WD_ERR("sgl is null!\n"); + return -WD_EINVAL; + } + + return sgl->buf_num; +} + +/* 'num' starts from 1 */ +void *wd_get_sge_buf(struct wd_sgl *sgl, __u32 num) +{ + if (unlikely(!sgl || !num || num > sgl->sge_num)) { + WD_ERR("sgl is null, or num is valid, num = %u!\n", num); + return NULL; + } + + return sgl->sge[num - 1].buf; +} + +int wd_get_sgl_buf_sum(struct wd_sgl *sgl) +{ + if (unlikely(!sgl)) { + WD_ERR("sgl is null!\n"); + return -WD_EINVAL; + } + + return sgl->buf_sum; +} + +int wd_get_sgl_mem_size(struct wd_sgl *sgl, size_t *size) +{ + if (unlikely(!sgl || !sgl->pool || !size)) { + WD_ERR("sgl parameter err!\n"); + return -WD_EINVAL; + } + + *size = sgl->pool->sgl_mem_sz; + + return WD_SUCCESS; +} + +int wd_get_free_sgl_num(void *pool, __u32 *free_sgl_num) +{ + struct wd_sglpool *p = pool; + + if (unlikely(!p || !free_sgl_num)) { + WD_ERR("pool or free_sgl_num is null!\n"); + return -WD_EINVAL; + } + + *free_sgl_num = __atomic_load_n(&p->free_sgl_num, __ATOMIC_RELAXED); + + return WD_SUCCESS; +} + +int wd_get_free_sgl_sge_num(struct wd_sgl *sgl, __u32 *free_sgl_sge_num) +{ + if (unlikely(!sgl || !free_sgl_sge_num)) { + WD_ERR("sgl or free_sgl_sge_num is null!\n"); + return -WD_EINVAL; + } + + *free_sgl_sge_num = sgl->sge_num - sgl->buf_num; + + return WD_SUCCESS; +} + +int wd_get_free_buf_num(void *pool, __u32 *free_buf_num) +{ + struct wd_sglpool *p = pool; + + if (unlikely(!p || !free_buf_num)) { + WD_ERR("pool or free_buf_num is null!\n"); + return -WD_EINVAL; + } + + *free_buf_num = __atomic_load_n(&p->free_buf_num, __ATOMIC_RELAXED); + + return WD_SUCCESS; +} + +/* if sgl is a chain(has two sgl), the sgl_datalen is the data_len in chain */ +int wd_get_sgl_datalen(struct wd_sgl *sgl, __u32 *dtsize) +{ + uintptr_t next; + + if (unlikely(!sgl || !dtsize)) { + WD_ERR("sgl or dtsize is null!\n"); + return -WD_EINVAL; + } + + *dtsize = sgl->sum_data_bytes; + + next = (uintptr_t)sgl->next & (~FLAG_MERGED_SGL); + if (next) + *dtsize += ((struct wd_sgl *)next)->sum_data_bytes; + + return WD_SUCCESS; +} + +/* get 'num'th' sge datalen in sgl, 'num' from 1 */ +int wd_get_sge_datalen(struct wd_sgl *sgl, __u32 num, __u32 *dtsize) +{ + if (unlikely(!sgl || !num || num > sgl->sge_num || !dtsize)) { + WD_ERR("sgl or num or dtsize is invalid!\n"); + return -WD_EINVAL; + } + + *dtsize = sgl->sge[num - 1].data_len; + return WD_SUCCESS; +} + +int wd_get_sgl_bufsize(struct wd_sgl *sgl, __u32 *bufsz) +{ + if (unlikely(!sgl || !sgl->pool || !bufsz)) { + WD_ERR("sgl parameter err or bufsz is null!\n"); + return -WD_EINVAL; + } + + *bufsz = sgl->pool->setup.buf_size; + return WD_SUCCESS; +} + +/* internal interface */ +/* set sgl.sge[num].priv as 'addr'm num starts '0' */ +void drv_set_sgl_sge_pri(struct wd_sgl *sgl, int num, void *priv) +{ + sgl->sge[num].priv = priv; +} + +void *drv_get_sgl_sge_pri(struct wd_sgl *sgl, int num) +{ + return sgl->sge[num].priv; +} + +void drv_set_sgl_pri(struct wd_sgl *sgl, void *priv) +{ + sgl->priv = priv; +} + +void *drv_get_sgl_pri(struct wd_sgl *sgl) +{ + return sgl->priv; +} + +struct wd_mm_br *drv_get_br(void *pool) +{ + struct wd_sglpool *p = pool; + + return &p->buf_br; +} + +void wd_sgl_memset(struct wd_sgl *sgl, int ch) +{ + int i; + + if (!sgl || !sgl->buf_num || !sgl->pool || !sgl->pool->setup.buf_size) { + WD_ERR("Sgl error!\n"); + return; + } + + for (i = 0; i < sgl->buf_num; i++) + memset(sgl->sge[i].buf, ch, sgl->pool->setup.buf_size); +} diff --git a/uadk/v1/wd_sgl.h b/uadk/v1/wd_sgl.h new file mode 100644 index 0000000..e2e82f2 --- /dev/null +++ b/uadk/v1/wd_sgl.h @@ -0,0 +1,74 @@ +/* + * Copyright 2020 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#ifndef _WD_SGL_H +#define _WD_SGL_H + +#include +#include +#include "wd.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct wd_sgl; +struct wd_sglpool_setup { + /* Total number of SGEs with buffer slices */ + __u32 buf_num; + /* memory size of entry buffer */ + __u32 buf_size; + /* Fixed SGE number in the SGL of the pool */ + __u8 sge_num_in_sgl; + /* Initiated buf number in the SGL of the pool, changeable */ + __u8 buf_num_in_sgl; + /* Total number of sgl for entries and buffers */ + __u16 sgl_num; + /* SGE data buffer starting address align size */ + __u32 align_size; + /* memory from user if don't use WD memory */ + struct wd_mm_br br; +}; + +void *wd_sglpool_create(struct wd_queue *q, struct wd_sglpool_setup *setup); +void wd_sglpool_destroy(void *pool); +struct wd_sgl *wd_alloc_sgl(void *pool, __u32 size); +void wd_free_sgl(void *pool, struct wd_sgl *sgl); +int wd_sgl_merge(struct wd_sgl *dst_sgl, struct wd_sgl *src_sgl); +int wd_sgl_cp_to_pbuf(struct wd_sgl *sgl, size_t offset, void *pbuf, size_t size); +int wd_sgl_cp_from_pbuf(struct wd_sgl *sgl, size_t offset, void *pbuf, size_t size); +void *wd_sgl_iova_map(void *pool, struct wd_sgl *sgl, size_t sz); +void wd_sgl_iova_unmap(void *pool, void *sgl_iova, struct wd_sgl *sgl); + +void *wd_get_last_sge_buf(struct wd_sgl *sgl); +void *wd_get_first_sge_buf(struct wd_sgl *sgl); +int wd_get_sgl_sge_num(struct wd_sgl *sgl); +int wd_get_sgl_buf_num(struct wd_sgl *sgl); +void *wd_get_sge_buf(struct wd_sgl *sgl, __u32 num); +int wd_get_sgl_buf_sum(struct wd_sgl *sgl); +int wd_get_sgl_mem_size(struct wd_sgl *sgl, size_t *size); +int wd_get_free_sgl_num(void *pool, __u32 *free_sgl_num); +int wd_get_free_sgl_sge_num(struct wd_sgl *sgl, __u32 *free_sgl_sge_num); +int wd_get_free_buf_num(void *pool, __u32 *free_buf_num); +int wd_get_sgl_datalen(struct wd_sgl *sgl, __u32 *dtsize); +int wd_get_sge_datalen(struct wd_sgl *sgl, __u32 num, __u32 *dtsize); +int wd_get_sgl_bufsize(struct wd_sgl *sgl, __u32 *bufsz); + +#ifdef __cplusplus +} +#endif + +#endif /* _WD_SGL_H */ diff --git a/uadk/v1/wd_util.c b/uadk/v1/wd_util.c new file mode 100644 index 0000000..112cc16 --- /dev/null +++ b/uadk/v1/wd_util.c @@ -0,0 +1,168 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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. + */ + +#include +#include +#include + +#include "v1/wd_util.h" + +#define BYTE_TO_BIT 8 + +void wd_spinlock(struct wd_lock *lock) +{ + while (__atomic_test_and_set(&lock->lock, __ATOMIC_ACQUIRE)) + while (__atomic_load_n(&lock->lock, __ATOMIC_RELAXED)) + ; +} + +void wd_unspinlock(struct wd_lock *lock) +{ + __atomic_clear(&lock->lock, __ATOMIC_RELEASE); +} + +void *drv_iova_map(struct wd_queue *q, void *va, size_t sz) +{ + struct q_info *qinfo = q->qinfo; + + if (qinfo->br.iova_map) + return (void *)qinfo->br.iova_map(qinfo->br.usr, va, sz); + else + return wd_iova_map(q, va, sz); +} + +void drv_iova_unmap(struct wd_queue *q, void *va, void *dma, size_t sz) +{ + struct q_info *qinfo = q->qinfo; + + if (qinfo->br.iova_unmap) + qinfo->br.iova_unmap(qinfo->br.usr, va, dma, sz); + else + wd_iova_unmap(q, va, dma, sz); +} + +int wd_alloc_id(__u8 *buf, __u32 size, __u32 *id, __u32 last_id, __u32 id_max) +{ + __u32 idx = last_id; + int cnt = 0; + + while (__atomic_test_and_set(&buf[idx], __ATOMIC_ACQUIRE)) { + idx++; + cnt++; + if (idx == id_max) + idx = 0; + if (cnt == id_max) + return -WD_EBUSY; + } + + *id = idx; + return 0; +} + +void wd_free_id(__u8 *buf, __u32 size, __u32 id, __u32 id_max) +{ + if (unlikely(id >= id_max)) { + WD_ERR("id error, id = %u!\n", id); + return; + } + + __atomic_clear(&buf[id], __ATOMIC_RELEASE); +} + +int wd_init_cookie_pool(struct wd_cookie_pool *pool, + __u32 cookies_size, __u32 cookies_num) +{ + __u64 total_size = cookies_size * cookies_num; + + pool->cookies = malloc(total_size + cookies_num); + if (!pool->cookies) + return -WD_ENOMEM; + + pool->cstatus = (void *)((uintptr_t)pool->cookies + total_size); + memset(pool->cstatus, 0, cookies_num); + + pool->cookies_num = cookies_num; + pool->cookies_size = cookies_size; + pool->cid = 0; + + return 0; +} + +void wd_uninit_cookie_pool(struct wd_cookie_pool *pool) +{ + if (pool->cookies) { + free(pool->cookies); + pool->cookies = NULL; + } +} + +static void put_cookie(struct wd_cookie_pool *pool, const void *cookie) +{ + __u32 idx = ((uintptr_t)cookie - (uintptr_t)pool->cookies) / + pool->cookies_size; + + wd_free_id(pool->cstatus, pool->cookies_num, idx, pool->cookies_num); +} + +static void *get_cookie(struct wd_cookie_pool *pool) +{ + __u32 last = pool->cid % pool->cookies_num; + __u32 id = 0; + int ret; + + ret = wd_alloc_id(pool->cstatus, pool->cookies_num, &id, last, + pool->cookies_num); + if (ret) + return NULL; + + pool->cid = id; + return (void *)((uintptr_t)pool->cookies + id * pool->cookies_size); +} + +void wd_put_cookies(struct wd_cookie_pool *pool, void **cookies, __u32 num) +{ + int i; + + for (i = 0; i < num; i++) + put_cookie(pool, cookies[i]); +} + +int wd_get_cookies(struct wd_cookie_pool *pool, void **cookies, __u32 num) +{ + int i ; + + for (i = 0; i < num; i++) { + cookies[i] = get_cookie(pool); + if (!cookies[i]) + goto put_cookies; + } + + return 0; + +put_cookies: + wd_put_cookies(pool, cookies, i); + return -WD_EBUSY; +} + +int wd_burst_send(struct wd_queue *q, void **req, __u32 num) +{ + return drv_send(q, req, num); +} + +int wd_burst_recv(struct wd_queue *q, void **resp, __u32 num) +{ + return drv_recv(q, resp, num); +} diff --git a/uadk/v1/wd_util.h b/uadk/v1/wd_util.h new file mode 100644 index 0000000..228493c --- /dev/null +++ b/uadk/v1/wd_util.h @@ -0,0 +1,393 @@ +/* + * Copyright 2019 Huawei Technologies Co.,Ltd.All rights reserved. + * + * 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 common driver header define the unified interface for wd */ +#ifndef __WD_UTIL_H__ +#define __WD_UTIL_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "v1/wd.h" +#include "v1/wd_ecc.h" +#include "v1/wd_adapter.h" + +#define WD_CTX_MSG_NUM 64 +#define WD_HPRE_CTX_MSG_NUM 64 +#define WD_RNG_CTX_MSG_NUM 256 +#define WD_MAX_CTX_NUM 256 +#define BYTE_BITS 8 +#define BYTE_BITS_SHIFT 3 +#define CRT_PARAMS_SZ(key_size) ((5 * (key_size)) >> 1) +#define CRT_GEN_PARAMS_SZ(key_size) ((7 * (key_size)) >> 1) +#define GEN_PARAMS_SZ(key_size) ((key_size) << 1) +#define CRT_PARAM_SZ(key_size) ((key_size) >> 1) +#define GET_NEGATIVE(val) (0 - (val)) +#define XTS_MODE_KEY_SHIFT 1 +#define AES_KEYSIZE_128 16 +#define AES_KEYSIZE_192 24 +#define AES_KEYSIZE_256 32 +#define CTX_ID_MAX_NUM 64 +#define CTX_ID_MAX_NUM_BYTES 512 + +/* ECC */ +#define ECDH_IN_PARAM_NUM 2 +#define ECDH_OUT_PARAM_NUM 2 +#define ECC_SIGN_IN_PARAM_NUM 2 +#define ECC_SIGN_OUT_PARAM_NUM 2 +#define ECC_VERF_IN_PARAM_NUM 3 +#define ECC_PRIKEY_PARAM_NUM 7 +#define ECDH_HW_KEY_PARAM_NUM 5 +#define ECC_PUBKEY_PARAM_NUM 8 +#define SM2_KG_OUT_PARAM_NUM 3 +#define ECC_POINT_PARAM_NUM 2 + +#define ECDH_HW_KEY_SZ(hsz) ((hsz) * ECDH_HW_KEY_PARAM_NUM) +#define ECC_PRIKEY_SZ(hsz) ((hsz) * ECC_PRIKEY_PARAM_NUM) +#define ECC_PUBKEY_SZ(hsz) ((hsz) * ECC_PUBKEY_PARAM_NUM) +#define ECDH_OUT_PARAMS_SZ(hsz) ((hsz) * ECDH_OUT_PARAM_NUM) + +/* x25519/x448 */ +#define X_DH_OUT_PARAM_NUM 1 +#define X_DH_HW_KEY_PARAM_NUM 3 + +#define X_DH_OUT_PARAMS_SZ(hsz) ((hsz) * X_DH_OUT_PARAM_NUM) +#define X_DH_HW_KEY_SZ(hsz) ((hsz) * X_DH_HW_KEY_PARAM_NUM) +#define SM2_KG_OUT_PARAMS_SZ(hsz) ((hsz) * SM2_KG_OUT_PARAM_NUM) +#define BITS_TO_BYTES(bits) (((bits) + 7) >> 3) +#define ECC_SIGN_IN_PARAMS_SZ(hsz) ((hsz) * ECC_SIGN_IN_PARAM_NUM) +#define ECC_SIGN_OUT_PARAMS_SZ(hsz) ((hsz) * ECC_SIGN_OUT_PARAM_NUM) +#define ECC_VERF_IN_PARAMS_SZ(hsz) ((hsz) * ECC_VERF_IN_PARAM_NUM) +#define ECC_VERF_OUT_PARAMS_SZ 1 + +/* Required compiler attributes */ +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) + +struct wd_lock { + __u8 lock; +}; + +struct wd_ss_region { + void *va; + unsigned long long pa; + size_t size; + + TAILQ_ENTRY(wd_ss_region) next; +}; + +TAILQ_HEAD(wd_ss_region_list, wd_ss_region); + +struct q_info { + const char *hw_type; + int hw_type_id; + int ref; + void *priv; /* private data used by the drive layer */ + const void *dev_info; + void *ss_va; + int fd; + int iommu_type; + struct wd_ss_region_list ss_list; + struct wd_ss_region_list *head; + unsigned int dev_flags; + unsigned long ss_size; + enum wcrypto_type atype; + int ctx_num; + struct wd_mm_br br; + struct wcrypto_hash_mt hash; + unsigned long qfrs_offset[WD_UACCE_QFRT_MAX]; + struct wd_lock qlock; + __u8 ctx_id[WD_MAX_CTX_NUM]; +}; + +struct wd_cookie_pool { + void *cookies; + __u8 *cstatus; + __u32 cookies_num; + __u32 cookies_size; + __u32 cid; +}; + +struct wd_dif_gen { + __u32 page_layout_gen_type:4; + __u32 grd_gen_type:4; + __u32 ver_gen_type:4; + __u32 app_gen_type:4; + __u32 ref_gen_type:4; + __u32 page_layout_pad_type:2; + __u32 reserved:10; +}; + +struct wd_dif_verify { + __u16 page_layout_pad_type:2; + __u16 grd_verify_type:4; + __u16 ref_verify_type:4; + __u16 reserved:6; +}; + +struct wd_dif_ctrl { + struct wd_dif_gen gen; + struct wd_dif_verify verify; + __u8 dif_comp_ctrl; +}; + +struct wd_dif { + __u64 lba; + __u32 priv_info; + __u8 ver; + __u8 app; + struct wd_dif_ctrl ctrl; +}; + +struct wd_sec_udata { + __u32 src_offset; + __u32 dst_offset; + struct wd_dif dif; + __u16 block_size; + __u16 gran_num; + __u16 key_bytes; + __u8 *key; +}; + +/* Digest tag format of Warpdrive */ +struct wcrypto_digest_tag { + struct wcrypto_cb_tag wcrypto_tag; + __u64 long_data_len; + void *priv; +}; + +/* Cipher tag format of Warpdrive */ +struct wcrypto_cipher_tag { + struct wcrypto_cb_tag wcrypto_tag; + void *priv; +}; + +/* AEAD tag format of Warpdrive */ +struct wcrypto_aead_tag { + struct wcrypto_cb_tag wcrypto_tag; + void *priv; +}; + +/* EC tag format of Warpdrive */ +struct wcrypto_ec_tag { + struct wcrypto_cb_tag wcrypto_tag; + __u64 tbl_addr; + void *priv; +}; + +/* COMP tag format of Warpdrive */ +struct wcrypto_comp_tag { + struct wcrypto_cb_tag wcrypto_tag; + void *priv; +}; + +/* ecc */ +struct wcrypto_ecc_pubkey { + struct wd_dtb p; + struct wd_dtb a; + struct wd_dtb b; + struct wd_dtb n; + struct wcrypto_ecc_point g; + struct wcrypto_ecc_point pub; + __u32 size; + void *data; +}; + +struct wcrypto_ecc_prikey { + struct wd_dtb p; + struct wd_dtb a; + struct wd_dtb d; + struct wd_dtb b; + struct wd_dtb n; + struct wcrypto_ecc_point g; + __u32 size; + void *data; +}; + +struct wcrypto_ecc_key { + struct wcrypto_ecc_pubkey *pubkey; + struct wcrypto_ecc_prikey *prikey; + struct wcrypto_ecc_curve *cv; + struct wcrypto_ecc_point *pub; + struct wd_dtb *d; +}; + +struct wcrypto_ecc_dh_in { + struct wcrypto_ecc_point pbk; +}; + +struct wcrypto_ecc_sign_in { + struct wd_dtb dgst; /* hash message */ + struct wd_dtb k; /* random */ + struct wd_dtb plaintext; /* original text before hash */ + __u8 k_set; /* 1 - k parameter set 0 - not set */ + __u8 dgst_set; /* 1 - dgst parameter set 0 - not set */ +}; + +struct wcrypto_ecc_verf_in { + struct wd_dtb dgst; /* hash message */ + struct wd_dtb s; /* signature s parameter */ + struct wd_dtb r; /* signature r parameter */ + struct wd_dtb plaintext; /* original text before hash */ + __u8 dgst_set; /* 1 - dgst parameter set 0 - not set */ +}; + +struct wcrypto_ecc_dh_out { + struct wcrypto_ecc_point out; +}; + +struct wcrypto_ecc_sign_out { + struct wd_dtb r; /* signature r parameter */ + struct wd_dtb s; /* signature s parameter */ +}; + +struct wcrypto_sm2_enc_in { + struct wd_dtb k; /* random */ + struct wd_dtb plaintext; /* original text */ + __u8 k_set; /* 0 - not set 1 - set */ +}; + +struct wcrypto_sm2_enc_out { + struct wcrypto_ecc_point c1; + struct wd_dtb c2; + struct wd_dtb c3; +}; + +struct wcrypto_sm2_dec_in { + struct wcrypto_ecc_point c1; + struct wd_dtb c2; + struct wd_dtb c3; +}; + +struct wcrypto_sm2_kg_in { + struct wcrypto_ecc_point g; +}; + +struct wcrypto_sm2_dec_out { + struct wd_dtb plaintext; +}; + +struct wcrypto_sm2_kg_out { + struct wcrypto_ecc_point pub; + struct wd_dtb priv; +}; + +typedef union { + struct wcrypto_ecc_dh_in dh_in; + struct wcrypto_ecc_sign_in sin; + struct wcrypto_ecc_verf_in vin; + struct wcrypto_sm2_enc_in ein; + struct wcrypto_sm2_dec_in din; + struct wcrypto_sm2_kg_in kin; +} wcrypto_ecc_in_param; + +typedef union { + struct wcrypto_ecc_dh_out dh_out; + struct wcrypto_ecc_sign_out sout; + struct wcrypto_sm2_enc_out eout; + struct wcrypto_sm2_dec_out dout; + struct wcrypto_sm2_kg_out kout; +} wcrypto_ecc_out_param; + +struct wcrypto_ecc_in { + wcrypto_ecc_in_param param; + __u64 size; + char data[]; +}; + +struct wcrypto_ecc_out { + wcrypto_ecc_out_param param; + __u64 size; + char data[]; +}; + +#ifdef DEBUG_LOG +#define dbg(msg, ...) fprintf(stderr, msg, ##__VA_ARGS__) +#else +#define dbg(msg, ...) +#endif + +#ifdef DEBUG +#define ASSERT(f) assert(f) +#else +#define ASSERT(f) +#endif + +#if defined(__AARCH64_CMODEL_SMALL__) && __AARCH64_CMODEL_SMALL__ +#define dsb(opt) { asm volatile("dsb " #opt : : : "memory"); } +#define rmb() dsb(ld) /* read fence */ +#define wmb() dsb(st) /* write fence */ +#define mb() dsb(sy) /* rw fence */ +#else +#define rmb() __sync_synchronize() /* read fence */ +#define wmb() __sync_synchronize() /* write fence */ +#define mb() __sync_synchronize() /* rw fence */ +#endif + +static inline void wd_reg_write(void *reg_addr, uint32_t value) +{ + *((uint32_t *)reg_addr) = value; + wmb(); /* load fence */ +} + +static inline uint32_t wd_reg_read(void *reg_addr) +{ + uint32_t temp; + + temp = *((uint32_t *)reg_addr); + rmb(); /* load fence */ + + return temp; +} + +void wd_spinlock(struct wd_lock *lock); +void wd_unspinlock(struct wd_lock *lock); +void *wd_drv_mmap_qfr(struct wd_queue *q, enum uacce_qfrt qfrt, size_t size); +void wd_drv_unmmap_qfr(struct wd_queue *q, void *addr, + enum uacce_qfrt qfrt, size_t size); +void *drv_iova_map(struct wd_queue *q, void *va, size_t sz); +void drv_iova_unmap(struct wd_queue *q, void *va, void *dma, size_t sz); +int wd_init_cookie_pool(struct wd_cookie_pool *pool, + __u32 cookies_size, __u32 cookies_num); +void wd_uninit_cookie_pool(struct wd_cookie_pool *pool); +int wd_alloc_id(__u8 *buf, __u32 size, __u32 *id, __u32 last_id, __u32 id_max); +void wd_free_id(__u8 *buf, __u32 size, __u32 id, __u32 id_max); +int wd_get_cookies(struct wd_cookie_pool *pool, void **cookies, __u32 num); +void wd_put_cookies(struct wd_cookie_pool *pool, void **cookies, __u32 num); +const char *wd_get_drv(struct wd_queue *q); +int wd_burst_send(struct wd_queue *q, void **req, __u32 num); +int wd_burst_recv(struct wd_queue *q, void **resp, __u32 num); + +void drv_set_sgl_sge_pri(struct wd_sgl *sgl, int num, void *priv); +void *drv_get_sgl_sge_pri(struct wd_sgl *sgl, int num); +void drv_set_sgl_pri(struct wd_sgl *sgl, void *priv); +void *drv_get_sgl_pri(struct wd_sgl *sgl); +struct wd_mm_br *drv_get_br(void *pool); +void wd_sgl_memset(struct wd_sgl *sgl, int ch); + +#endif diff --git a/uadk/wd.c b/uadk/wd.c new file mode 100644 index 0000000..6ea17f3 --- /dev/null +++ b/uadk/wd.c @@ -0,0 +1,824 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. + * Copyright 2020-2021 Linaro ltd. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "wd_alg_common.h" +#include "wd.h" + +#define SYS_CLASS_DIR "/sys/class/uacce" + +enum UADK_LOG_LEVEL { + LOG_NONE = 0, + WD_LOG_ERROR, + WD_LOG_INFO, + WD_LOG_DEBUG, +}; + +static int uadk_log_level; + +struct wd_ctx_h { + int fd; + char dev_path[MAX_DEV_NAME_LEN]; + char *dev_name; + char *drv_name; + unsigned long qfrs_offs[UACCE_QFRT_MAX]; + void *qfrs_base[UACCE_QFRT_MAX]; + struct uacce_dev *dev; + void *priv; +}; + +static void wd_parse_log_level(void) +{ + const char *syslog_file = "/etc/rsyslog.conf"; + const char *log_dir = "/var/log/uadk.log"; + bool log_debug = false; + bool log_info = false; + struct stat file_info; + char *file_contents; + FILE *in_file; + + in_file = fopen(syslog_file, "r"); + if (!in_file) { + WD_ERR("failed to open the rsyslog.conf file.\n"); + return; + } + + if (stat(syslog_file, &file_info) == -1) { + WD_ERR("failed to get file information.\n"); + goto close_file; + } + + file_contents = malloc(file_info.st_size); + if (!file_contents) { + WD_ERR("failed to get file contents memory.\n"); + goto close_file; + } + + while (fscanf(in_file, "%[^\n ] ", file_contents) != EOF) { + if (!strcmp("local5.debug", file_contents)) + log_debug = true; + else if (!strcmp("local5.info", file_contents)) + log_info = true; + + if (log_debug && !strcmp(log_dir, file_contents)) { + uadk_log_level = WD_LOG_DEBUG; + break; + } else if (log_info && !strcmp(log_dir, file_contents)) { + uadk_log_level = WD_LOG_INFO; + break; + } + } + + free(file_contents); + +close_file: + fclose(in_file); +} + +static int get_raw_attr(const char *dev_root, const char *attr, char *buf, + size_t sz) +{ + char attr_file[PATH_STR_SIZE]; + char attr_path[PATH_MAX]; + char *ptrRet = NULL; + ssize_t size; + int fd; + + size = snprintf(attr_file, PATH_STR_SIZE, "%s/%s", dev_root, attr); + if (size < 0) { + WD_ERR("failed to snprintf, dev_root: %s, attr: %s!\n", + dev_root, attr); + return -WD_EINVAL; + } + + ptrRet = realpath(attr_file, attr_path); + if (ptrRet == NULL) { + WD_ERR("failed to resolve path, attr_file: %s!\n", attr_file); + return -WD_ENODEV; + } + + fd = open(attr_path, O_RDONLY, 0); + if (fd < 0) { + WD_ERR("failed to open %s(%d)!\n", attr_path, -errno); + return -WD_ENODEV; + } + + memset(buf, 0, sz); + size = read(fd, buf, sz); + if (size <= 0) { + WD_ERR("failed to read anything at %s!\n", attr_path); + size = -WD_EIO; + } + + close(fd); + + return size; +} + +static int get_int_attr(struct uacce_dev *dev, const char *attr, int *val) +{ + char buf[MAX_ATTR_STR_SIZE] = {'\0'}; + int ret; + + ret = get_raw_attr(dev->dev_root, attr, buf, MAX_ATTR_STR_SIZE - 1); + if (ret < 0) + return ret; + + *val = strtol(buf, NULL, 10); + if (errno == ERANGE) { + WD_ERR("failed to strtol %s, out of range!\n", buf); + return -errno; + } + + return 0; +} + +static int get_str_attr(struct uacce_dev *dev, const char *attr, char *buf, + size_t buf_sz) +{ + int ret; + + ret = get_raw_attr(dev->dev_root, attr, buf, buf_sz); + if (ret < 0) { + buf[0] = '\0'; + return ret; + } + + if (ret == buf_sz) + ret--; + + buf[ret] = '\0'; + while ((ret > 1) && (buf[ret - 1] == '\n')) { + buf[ret-- - 1] = '\0'; + } + + return ret; +} + +static int access_attr(const char *dev_root, const char *attr, int mode) +{ + char attr_file[PATH_STR_SIZE]; + ssize_t size; + + if (!dev_root || !attr) + return -WD_EINVAL; + + size = snprintf(attr_file, PATH_STR_SIZE, "%s/%s", dev_root, attr); + if (size < 0) + return -WD_EINVAL; + + return access(attr_file, mode); +} + +int wd_is_isolate(struct uacce_dev *dev) +{ + int value = 0; + int ret; + + if (!dev || !dev->dev_root) + return -WD_EINVAL; + + ret = access_attr(dev->dev_root, "isolate", F_OK); + if (!ret) { + ret = get_int_attr(dev, "isolate", &value); + if (ret < 0) + return ret; + } + + return value == 1 ? 1 : 0; +} + +static int get_dev_info(struct uacce_dev *dev) +{ + int value = 0; + int ret; + + /* hardware err isolate flag */ + ret = access_attr(dev->dev_root, "isolate", F_OK); + if (!ret) { + ret = get_int_attr(dev, "isolate", &value); + if (ret < 0) + return ret; + else if (value == 1) { + WD_ERR("skip isolated uacce device!\n"); + return -ENODEV; + } + } + + ret = get_int_attr(dev, "flags", &dev->flags); + if (ret < 0) + return ret; + else if (!((unsigned int)dev->flags & UACCE_DEV_SVA)) { + WD_ERR("skip none sva uacce device!\n"); + return -ENODEV; + } + + ret = get_int_attr(dev, "region_mmio_size", &value); + if (ret < 0) + return ret; + + dev->qfrs_offs[UACCE_QFRT_MMIO] = value; + + ret = get_int_attr(dev, "region_dus_size", &value); + if (ret < 0) + return ret; + + dev->qfrs_offs[UACCE_QFRT_DUS] = value; + + ret = get_int_attr(dev, "device/numa_node", &dev->numa_id); + if (ret < 0) + return ret; + + ret = get_str_attr(dev, "api", dev->api, WD_NAME_SIZE); + if (ret < 0) + return ret; + + return get_str_attr(dev, "algorithms", dev->algs, MAX_ATTR_STR_SIZE); +} + +static struct uacce_dev *read_uacce_sysfs(const char *dev_name) +{ + struct uacce_dev *dev = NULL; + int ret; + + if (!dev_name) + return NULL; + + wd_parse_log_level(); + + dev = calloc(1, sizeof(struct uacce_dev)); + if (!dev) + return NULL; + + ret = snprintf(dev->dev_root, MAX_DEV_NAME_LEN, "%s/%s", + SYS_CLASS_DIR, dev_name); + if (ret < 0) + goto out; + + ret = snprintf(dev->char_dev_path, MAX_DEV_NAME_LEN, + "/dev/%s", dev_name); + if (ret < 0) + goto out; + + ret = get_dev_info(dev); + if (ret < 0) + goto out; + + return dev; + +out: + free(dev); + return NULL; +} + +char *wd_get_accel_name(char *dev_path, int no_apdx) +{ + int i, appendix, dash_len, len; + char *dash = NULL; + char *name; + + if (!dev_path || (no_apdx != 0 && no_apdx != 1)) + return NULL; + + if (!index(dev_path, '-')) + return NULL; + + /* find '/' index in the string and keep the last level */ + name = rindex(dev_path, '/'); + if (name) { + /* absolute path */ + if (strlen(name) == 1) + return NULL; + name++; + } else { + /* relative path */ + name = dev_path; + } + + if (!strlen(name)) + return NULL; + + if (no_apdx) { + /* find '-' index in the name string */ + appendix = 1; + dash = rindex(name, '-'); + if (!dash) + goto out; + + dash_len = strlen(dash); + for (i = 1; i < dash_len; i++) { + if (!isdigit(dash[i])) { + appendix = 0; + break; + } + } + /* treat dash as a part of name if there's no digit */ + if (i == 1) + appendix = 0; + } else { + appendix = 0; + } + +out: + /* remove '-' and digits */ + len = (dash && appendix) ? strlen(name) - strlen(dash) : strlen(name); + + return strndup(name, len); +} + +static struct uacce_dev *clone_uacce_dev(struct uacce_dev *dev) +{ + struct uacce_dev *new; + + new = calloc(1, sizeof(*dev)); + if (!new) + return NULL; + + memcpy(new, dev, sizeof(*dev)); + + return new; +} + +static void wd_ctx_init_qfrs_offs(struct wd_ctx_h *ctx) +{ + memcpy(&ctx->qfrs_offs, &ctx->dev->qfrs_offs, + sizeof(ctx->qfrs_offs)); +} + +handle_t wd_request_ctx(struct uacce_dev *dev) +{ + struct wd_ctx_h *ctx; + char char_dev_path[PATH_MAX]; + char *ptrRet = NULL; + int fd; + + if (!dev || !strlen(dev->dev_root)) + return 0; + + ptrRet = realpath(dev->char_dev_path, char_dev_path); + if (ptrRet == NULL) + return 0; + + fd = open(char_dev_path, O_RDWR | O_CLOEXEC); + if (fd < 0) { + WD_ERR("failed to open %s!(err = %d)\n", char_dev_path, -errno); + return 0; + } + + ctx = calloc(1, sizeof(struct wd_ctx_h)); + if (!ctx) + goto close_fd; + + ctx->dev_name = wd_get_accel_name(dev->char_dev_path, 0); + if (!ctx->dev_name) + goto free_ctx; + + ctx->drv_name = wd_get_accel_name(dev->char_dev_path, 1); + if (!ctx->drv_name) + goto free_dev_name; + + ctx->dev = clone_uacce_dev(dev); + if (!ctx->dev) + goto free_drv_name; + + ctx->fd = fd; + + wd_ctx_init_qfrs_offs(ctx); + + strncpy(ctx->dev_path, dev->char_dev_path, MAX_DEV_NAME_LEN); + ctx->dev_path[MAX_DEV_NAME_LEN - 1] = '\0'; + + return (handle_t)ctx; + +free_drv_name: + free(ctx->drv_name); +free_dev_name: + free(ctx->dev_name); +free_ctx: + free(ctx); +close_fd: + close(fd); + return 0; +} + +void wd_release_ctx(handle_t h_ctx) +{ + struct wd_ctx_h *ctx = (struct wd_ctx_h *)h_ctx; + + if (!ctx) + return; + + close(ctx->fd); + free(ctx->dev); + free(ctx->drv_name); + free(ctx->dev_name); + free(ctx); +} + +int wd_ctx_start(handle_t h_ctx) +{ + struct wd_ctx_h *ctx = (struct wd_ctx_h *)h_ctx; + int ret; + + if (!ctx) + return -WD_EINVAL; + + ret = wd_ctx_set_io_cmd(h_ctx, UACCE_CMD_START, NULL); + if (ret) + WD_ERR("failed to start on %s (%d), ret = %d!\n", + ctx->dev_path, -errno, ret); + + return ret; +} + +int wd_release_ctx_force(handle_t h_ctx) +{ + struct wd_ctx_h *ctx = (struct wd_ctx_h *)h_ctx; + int ret; + + if (!ctx) + return -WD_EINVAL; + + ret = wd_ctx_set_io_cmd(h_ctx, UACCE_CMD_PUT_Q, NULL); + if (ret) + WD_ERR("failed to stop on %s (%d), ret = %d!\n", + ctx->dev_path, -errno, ret); + + return ret; +} + +void *wd_ctx_mmap_qfr(handle_t h_ctx, enum uacce_qfrt qfrt) +{ + struct wd_ctx_h *ctx = (struct wd_ctx_h *)h_ctx; + off_t off = qfrt * getpagesize(); + size_t size; + void *addr; + + if (!ctx || qfrt >= UACCE_QFRT_MAX || !ctx->qfrs_offs[qfrt]) { + WD_ERR("failed to check input ctx or qfrt!\n"); + return NULL; + } + + size = ctx->qfrs_offs[qfrt]; + + addr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, ctx->fd, off); + if (addr == MAP_FAILED) { + WD_ERR("failed to mmap, qfrt = %d, err = %d!\n", qfrt, -errno); + return NULL; + } + + ctx->qfrs_base[qfrt] = addr; + + return addr; +} + +void wd_ctx_unmap_qfr(handle_t h_ctx, enum uacce_qfrt qfrt) +{ + struct wd_ctx_h *ctx = (struct wd_ctx_h *)h_ctx; + + if (!ctx || qfrt >= UACCE_QFRT_MAX) + return; + + if (ctx->qfrs_offs[qfrt] != 0) + munmap(ctx->qfrs_base[qfrt], ctx->qfrs_offs[qfrt]); +} + +unsigned long wd_ctx_get_region_size(handle_t h_ctx, enum uacce_qfrt qfrt) +{ + struct wd_ctx_h *ctx = (struct wd_ctx_h *)h_ctx; + if (!ctx || qfrt >= UACCE_QFRT_MAX) + return 0; + return ctx->qfrs_offs[qfrt]; +} + +void *wd_ctx_get_priv(handle_t h_ctx) +{ + struct wd_ctx_h *ctx = (struct wd_ctx_h *)h_ctx; + + if (!ctx) + return NULL; + + return ctx->priv; +} + +int wd_ctx_set_priv(handle_t h_ctx, void *priv) +{ + struct wd_ctx_h *ctx = (struct wd_ctx_h *)h_ctx; + + if (!ctx) + return -WD_EINVAL; + + ctx->priv = priv; + + return 0; +} + +char *wd_ctx_get_api(handle_t h_ctx) +{ + struct wd_ctx_h *ctx = (struct wd_ctx_h *)h_ctx; + + if (!ctx || !ctx->dev) + return NULL; + + return ctx->dev->api; +} + +int wd_ctx_wait(handle_t h_ctx, __u16 ms) +{ + struct wd_ctx_h *ctx = (struct wd_ctx_h *)h_ctx; + struct pollfd fds[1]; + int ret; + + if (!ctx) + return -WD_EINVAL; + + fds[0].fd = ctx->fd; + fds[0].events = POLLIN; + ret = poll(fds, 1, ms); + if (ret == -1) + return -errno; + + return ret; +} + +int wd_is_sva(handle_t h_ctx) +{ + struct wd_ctx_h *ctx = (struct wd_ctx_h *)h_ctx; + + if (!ctx || !ctx->dev) + return -WD_EINVAL; + + if ((unsigned int)ctx->dev->flags & UACCE_DEV_SVA) + return 1; + + return 0; +} + +int wd_get_numa_id(handle_t h_ctx) +{ + struct wd_ctx_h *ctx = (struct wd_ctx_h *)h_ctx; + + if (!ctx || !ctx->dev) + return -WD_EINVAL; + + return ctx->dev->numa_id; +} + +int wd_get_avail_ctx(struct uacce_dev *dev) +{ + int avail_ctx, ret; + + if (!dev) + return -WD_EINVAL; + + ret = get_int_attr(dev, "available_instances", &avail_ctx); + if (ret < 0) + return ret; + + return avail_ctx; +} + +static int get_dev_alg_name(const char *d_name, char *dev_alg_name, size_t sz) +{ + char dev_path[MAX_DEV_NAME_LEN] = {0}; + int ret; + + ret = snprintf(dev_path, MAX_DEV_NAME_LEN, "%s/%s", + SYS_CLASS_DIR, d_name); + if (ret < 0) + return ret; + else if (ret > MAX_DEV_NAME_LEN) + return -WD_EINVAL; + + ret = get_raw_attr(dev_path, "algorithms", dev_alg_name, sz); + if (ret < 0) { + dev_alg_name[0] = '\0'; + return ret; + } + + if (ret == sz) + dev_alg_name[sz - 1] = '\0'; + + return 0; +} + +static bool dev_has_alg(const char *dev_alg_name, const char *alg_name) +{ + char *str; + + str = strstr(dev_alg_name, alg_name); + if (!str) + return false; + + if (*(str + strlen(alg_name)) == '\n' && + ((str > dev_alg_name && *(str - 1) == '\n') || str == dev_alg_name)) + return true; + + return false; +} + +static void add_uacce_dev_to_list(struct uacce_dev_list *head, + struct uacce_dev_list *node) +{ + struct uacce_dev_list *tmp = head; + + while (tmp->next) + tmp = tmp->next; + + tmp->next = node; +} + +static int check_alg_name(const char *alg_name) +{ + int i = 0; + + if (!alg_name) + return -WD_EINVAL; + + while (alg_name[i] != '\0') { + i++; + if (i >= MAX_ATTR_STR_SIZE) { + WD_ERR("failed to get list, alg name is too long!\n"); + return -WD_EINVAL; + } + } + + return 0; +} + +struct uacce_dev_list *wd_get_accel_list(const char *alg_name) +{ + struct uacce_dev_list *node, *head = NULL; + char dev_alg_name[MAX_ATTR_STR_SIZE]; + struct dirent *dev_dir; + DIR *wd_class; + int ret; + + if (check_alg_name(alg_name)) + return NULL; + + wd_class = opendir(SYS_CLASS_DIR); + if (!wd_class) { + WD_ERR("UADK framework isn't enabled in system!\n"); + return NULL; + } + + while ((dev_dir = readdir(wd_class)) != NULL) { + if (!strncmp(dev_dir->d_name, ".", LINUX_CRTDIR_SIZE) || + !strncmp(dev_dir->d_name, "..", LINUX_PRTDIR_SIZE)) + continue; + + ret = access_attr(SYS_CLASS_DIR, dev_dir->d_name, F_OK); + if (ret < 0) { + WD_ERR("failed to access dev: %s, ret: %d\n", + dev_dir->d_name, ret); + continue; + } + + ret = get_dev_alg_name(dev_dir->d_name, dev_alg_name, + sizeof(dev_alg_name)); + if (ret < 0) { + WD_ERR("failed to get dev: %s alg name!\n", dev_dir->d_name); + continue; + } + + if (!dev_has_alg(dev_alg_name, alg_name)) + continue; + + node = calloc(1, sizeof(*node)); + if (!node) + goto free_list; + + node->dev = read_uacce_sysfs(dev_dir->d_name); + if (!node->dev) { + free(node); + node = NULL; + continue; + } + + if (!head) + head = node; + else + add_uacce_dev_to_list(head, node); + } + + closedir(wd_class); + + return head; + +free_list: + closedir(wd_class); + wd_free_list_accels(head); + return NULL; +} + +void wd_free_list_accels(struct uacce_dev_list *list) +{ + struct uacce_dev_list *curr, *next; + + if (!list) + return; + + curr = list; + while (curr) { + next = curr->next; + if (curr->dev) + free(curr->dev); + free(curr); + curr = next; + } +} + +struct uacce_dev *wd_get_accel_dev(const char *alg_name) +{ + struct uacce_dev_list *list, *head; + struct uacce_dev *dev = NULL, *target = NULL; + int cpu = sched_getcpu(); + int node = numa_node_of_cpu(cpu); + int ctx_num, tmp; + int dis = 1024; + int max = 0; + + head = wd_get_accel_list(alg_name); + if (!head) + return NULL; + + list = head; + while (list) { + tmp = numa_distance(node, list->dev->numa_id); + ctx_num = wd_get_avail_ctx(list->dev); + if ((dis > tmp && ctx_num > 0) || + (dis == tmp && ctx_num > max)) { + dev = list->dev; + dis = tmp; + max = ctx_num; + } + + list = list->next; + } + + if (dev) + target = clone_uacce_dev(dev); + + wd_free_list_accels(head); + + return target; +} + +int wd_ctx_set_io_cmd(handle_t h_ctx, unsigned long cmd, void *arg) +{ + struct wd_ctx_h *ctx = (struct wd_ctx_h *)h_ctx; + + if (!ctx) + return -WD_EINVAL; + + if (!arg) + return ioctl(ctx->fd, cmd); + + return ioctl(ctx->fd, cmd, arg); +} + +void wd_get_version(void) +{ + const char *wd_released_time = UADK_RELEASED_TIME; + const char *wd_version = UADK_VERSION_NUMBER; + + WD_CONSOLE("%s\n", wd_version); + WD_CONSOLE("%s\n", wd_released_time); +} + +bool wd_need_debug(void) +{ + return uadk_log_level >= WD_LOG_DEBUG; +} + +bool wd_need_info(void) +{ + return uadk_log_level >= WD_LOG_INFO; +} + +char *wd_ctx_get_dev_name(handle_t h_ctx) +{ + struct wd_ctx_h *ctx = (struct wd_ctx_h *)h_ctx; + + if (!ctx) + return NULL; + + return ctx->dev_name; +} diff --git a/uadk/wd_aead.c b/uadk/wd_aead.c new file mode 100644 index 0000000..d6c2380 --- /dev/null +++ b/uadk/wd_aead.c @@ -0,0 +1,734 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. + * Copyright 2020-2021 Linaro ltd. + */ + +#include +#include +#include "wd_util.h" +#include "include/drv/wd_aead_drv.h" +#include "wd_aead.h" + +#define XTS_MODE_KEY_DIVISOR 2 +#define SM4_KEY_SIZE 16 +#define DES_KEY_SIZE 8 +#define DES3_2KEY_SIZE (2 * DES_KEY_SIZE) +#define DES3_3KEY_SIZE (3 * DES_KEY_SIZE) +#define AES_KEYSIZE_128 16 +#define AES_KEYSIZE_192 24 +#define AES_KEYSIZE_256 32 + +#define WD_AEAD_CCM_GCM_MIN 4U +#define WD_AEAD_CCM_GCM_MAX 16 +#define WD_POOL_MAX_ENTRIES 1024 + +static int g_aead_mac_len[WD_DIGEST_TYPE_MAX] = { + WD_DIGEST_SM3_LEN, WD_DIGEST_MD5_LEN, WD_DIGEST_SHA1_LEN, + WD_DIGEST_SHA256_LEN, WD_DIGEST_SHA224_LEN, + WD_DIGEST_SHA384_LEN, WD_DIGEST_SHA512_LEN, + WD_DIGEST_SHA512_224_LEN, WD_DIGEST_SHA512_256_LEN +}; + +struct wd_aead_setting { + struct wd_ctx_config_internal config; + struct wd_sched sched; + struct wd_aead_driver *driver; + struct wd_async_msg_pool pool; + void *sched_ctx; + void *priv; + void *dlhandle; +} wd_aead_setting; + +struct wd_aead_sess { + char *alg_name; + enum wd_cipher_alg calg; + enum wd_cipher_mode cmode; + enum wd_digest_type dalg; + enum wd_digest_mode dmode; + unsigned char ckey[MAX_CIPHER_KEY_SIZE]; + unsigned char akey[MAX_HMAC_KEY_SIZE]; + __u16 ckey_bytes; + __u16 akey_bytes; + __u16 auth_bytes; + void *priv; + void *sched_key; +}; + +struct wd_env_config wd_aead_env_config; + +#ifdef WD_STATIC_DRV +static void wd_aead_set_static_drv(void) +{ + wd_aead_setting.driver = wd_aead_get_driver(); + if (!wd_aead_setting.driver) + WD_ERR("failed to get driver!\n"); +} +#else +static void __attribute__((constructor)) wd_aead_open_driver(void) +{ + wd_aead_setting.dlhandle = dlopen("libhisi_sec.so", RTLD_NOW); + if (!wd_aead_setting.dlhandle) + WD_ERR("failed to open libhisi_sec.so!\n"); +} + +static void __attribute__((destructor)) wd_aead_close_driver(void) +{ + if (wd_aead_setting.dlhandle) + dlclose(wd_aead_setting.dlhandle); +} +#endif + +void wd_aead_set_driver(struct wd_aead_driver *drv) +{ + wd_aead_setting.driver = drv; +} + +static int aes_key_len_check(__u32 length) +{ + switch (length) { + case AES_KEYSIZE_128: + case AES_KEYSIZE_192: + case AES_KEYSIZE_256: + return 0; + default: + return -WD_EINVAL; + } +} + +static int cipher_key_len_check(enum wd_cipher_alg alg, __u16 length) +{ + int ret = 0; + + switch (alg) { + case WD_CIPHER_SM4: + if (length != SM4_KEY_SIZE) + ret = -WD_EINVAL; + break; + case WD_CIPHER_AES: + ret = aes_key_len_check(length); + break; + default: + WD_ERR("failed to set the cipher alg, alg = %d\n", alg); + return -WD_EINVAL; + } + + return ret; +} + +static unsigned int get_iv_block_size(int mode) +{ + int ret; + + /* AEAD just used AES and SM4 algorithm */ + switch (mode) { + case WD_CIPHER_CBC: + case WD_CIPHER_CCM: + ret = AES_BLOCK_SIZE; + break; + case WD_CIPHER_GCM: + ret = GCM_BLOCK_SIZE; + break; + default: + ret = AES_BLOCK_SIZE; + } + + return ret; +} + +int wd_aead_set_ckey(handle_t h_sess, const __u8 *key, __u16 key_len) +{ + struct wd_aead_sess *sess = (struct wd_aead_sess *)h_sess; + int ret; + + if (unlikely(!key || !sess)) { + WD_ERR("failed to check cipher key input param!\n"); + return -WD_EINVAL; + } + + ret = cipher_key_len_check(sess->calg, key_len); + if (ret) { + WD_ERR("failed to check cipher key length!\n"); + return -WD_EINVAL; + } + + sess->ckey_bytes = key_len; + memcpy(sess->ckey, key, key_len); + + return 0; +} + +int wd_aead_set_akey(handle_t h_sess, const __u8 *key, __u16 key_len) +{ + struct wd_aead_sess *sess = (struct wd_aead_sess *)h_sess; + + if (unlikely(!key || !sess)) { + WD_ERR("failed to check authenticate key param!\n"); + return -WD_EINVAL; + } + + if (key_len == 0) + goto err_key_len; + + /* + * Here dalg only supports sha1, sha256, sha512, + * and should check key length with different max length. + */ + if (sess->dalg > WD_DIGEST_SHA256) { + if (key_len > MAX_HMAC_KEY_SIZE) + goto err_key_len; + } else { + if (key_len > MAX_HMAC_KEY_SIZE >> 1) + goto err_key_len; + } + + sess->akey_bytes = key_len; + memcpy(sess->akey, key, key_len); + + return 0; + +err_key_len: + WD_ERR("failed to check authenticate key length, size = %u\n", key_len); + return -WD_EINVAL; +} + +int wd_aead_set_authsize(handle_t h_sess, __u16 authsize) +{ + struct wd_aead_sess *sess = (struct wd_aead_sess *)h_sess; + + if (!sess) { + WD_ERR("failed to check session parameter!\n"); + return -WD_EINVAL; + } + + if (sess->cmode == WD_CIPHER_CCM) { + if (authsize < WD_AEAD_CCM_GCM_MIN || + authsize > WD_AEAD_CCM_GCM_MAX || + authsize % (WD_AEAD_CCM_GCM_MIN >> 1)) { + WD_ERR("failed to check aead CCM authsize, size = %u\n", + authsize); + return -WD_EINVAL; + } + } else if (sess->cmode == WD_CIPHER_GCM) { + if (authsize < WD_AEAD_CCM_GCM_MIN << 1 || + authsize > WD_AEAD_CCM_GCM_MAX) { + WD_ERR("failed to check aead GCM authsize, size = %u\n", + authsize); + return -WD_EINVAL; + } + } else { + if (sess->dalg >= WD_DIGEST_TYPE_MAX || + authsize & (WD_AEAD_CCM_GCM_MAX - 1) || + authsize > g_aead_mac_len[sess->dalg]) { + WD_ERR("failed to check aead mac authsize, size = %u\n", + authsize); + return -WD_EINVAL; + } + } + + sess->auth_bytes = authsize; + + return 0; +} + +int wd_aead_get_authsize(handle_t h_sess) +{ + struct wd_aead_sess *sess = (struct wd_aead_sess *)h_sess; + + if (!sess) { + WD_ERR("failed to check session parameter!\n"); + return -WD_EINVAL; + } + + return sess->auth_bytes; +} + +int wd_aead_get_maxauthsize(handle_t h_sess) +{ + struct wd_aead_sess *sess = (struct wd_aead_sess *)h_sess; + + if (!sess || sess->dalg >= WD_DIGEST_TYPE_MAX) { + WD_ERR("failed to check session parameter!\n"); + return -WD_EINVAL; + } + + if (sess->cmode == WD_CIPHER_CCM || sess->cmode == WD_CIPHER_GCM) + return WD_AEAD_CCM_GCM_MAX; + + return g_aead_mac_len[sess->dalg]; +} + +handle_t wd_aead_alloc_sess(struct wd_aead_sess_setup *setup) +{ + struct wd_aead_sess *sess = NULL; + + if (unlikely(!setup)) { + WD_ERR("failed to check session input parameter!\n"); + return (handle_t)0; + } + + sess = malloc(sizeof(struct wd_aead_sess)); + if (!sess) { + WD_ERR("failed to alloc session memory!\n"); + return (handle_t)0; + } + memset(sess, 0, sizeof(struct wd_aead_sess)); + + sess->calg = setup->calg; + sess->cmode = setup->cmode; + sess->dalg = setup->dalg; + sess->dmode = setup->dmode; + /* Some simple scheduler don't need scheduling parameters */ + sess->sched_key = (void *)wd_aead_setting.sched.sched_init( + wd_aead_setting.sched.h_sched_ctx, setup->sched_param); + if (WD_IS_ERR(sess->sched_key)) { + WD_ERR("failed to init session schedule key!\n"); + free(sess); + return (handle_t)0; + } + + return (handle_t)sess; +} + +void wd_aead_free_sess(handle_t h_sess) +{ + struct wd_aead_sess *sess = (struct wd_aead_sess *)h_sess; + + if (unlikely(!sess)) { + WD_ERR("failed to check session parameter!\n"); + return; + } + + wd_memset_zero(sess->ckey, MAX_CIPHER_KEY_SIZE); + wd_memset_zero(sess->akey, MAX_HMAC_KEY_SIZE); + + if (sess->sched_key) + free(sess->sched_key); + free(sess); +} + +static int aead_mac_param_check(struct wd_aead_sess *sess, + struct wd_aead_req *req) +{ + int ret = 0; + + switch (sess->cmode) { + case WD_CIPHER_CBC: + if (req->mac_bytes < g_aead_mac_len[sess->dalg]) { + WD_ERR("failed to check cbc-hmac mac buffer length, size = %u\n", + req->mac_bytes); + ret = -WD_EINVAL; + } + break; + case WD_CIPHER_CCM: + case WD_CIPHER_GCM: + if (req->mac_bytes < WD_AEAD_CCM_GCM_MAX) { + WD_ERR("failed to check CCM or GCM mac buffer length, size = %u\n", + req->mac_bytes); + ret = -WD_EINVAL; + } + break; + default: + ret = -WD_EINVAL; + WD_ERR("set the aead cmode is error, cmode = %d\n", sess->cmode); + } + + return ret; +} + +static int wd_aead_param_check(struct wd_aead_sess *sess, + struct wd_aead_req *req) +{ + __u32 len; + int ret; + + if (unlikely(!sess || !req)) { + WD_ERR("invalid: aead input sess or req is NULL!\n"); + return -WD_EINVAL; + } + + if (unlikely(sess->cmode == WD_CIPHER_CBC && req->in_bytes == 0)) { + WD_ERR("aead input data length is zero!\n"); + return -WD_EINVAL; + } + + if (unlikely(sess->cmode == WD_CIPHER_CBC && + (req->in_bytes & (AES_BLOCK_SIZE - 1)))) { + WD_ERR("failed to check aead input data length, size = %u\n", + req->in_bytes); + return -WD_EINVAL; + } + + if (unlikely(req->iv_bytes != get_iv_block_size(sess->cmode))) { + WD_ERR("failed to check aead IV length, size = %u\n", + req->iv_bytes); + return -WD_EINVAL; + } + + ret = aead_mac_param_check(sess, req); + if (unlikely(ret)) + return -WD_EINVAL; + + if (req->data_fmt == WD_SGL_BUF) { + len = req->in_bytes + req->assoc_bytes; + ret = wd_check_datalist(req->list_src, len); + if (unlikely(ret)) { + WD_ERR("failed to check the src datalist, size = %u\n", + len); + return -WD_EINVAL; + } + + ret = wd_check_datalist(req->list_dst, req->out_bytes); + if (unlikely(ret)) { + WD_ERR("failed to check the dst datalist, size = %u\n", + req->out_bytes); + return -WD_EINVAL; + } + } + + return 0; +} + +int wd_aead_init(struct wd_ctx_config *config, struct wd_sched *sched) +{ + void *priv; + int ret; + + ret = wd_init_param_check(config, sched); + if (ret) + return ret; + + ret = wd_set_epoll_en("WD_AEAD_EPOLL_EN", + &wd_aead_setting.config.epoll_en); + if (ret < 0) + return ret; + + ret = wd_init_ctx_config(&wd_aead_setting.config, config); + if (ret) + return ret; + + ret = wd_init_sched(&wd_aead_setting.sched, sched); + if (ret < 0) + goto out; + + /* set driver */ +#ifdef WD_STATIC_DRV + wd_aead_set_static_drv(); +#endif + + /* init async request pool */ + ret = wd_init_async_request_pool(&wd_aead_setting.pool, + config->ctx_num, WD_POOL_MAX_ENTRIES, + sizeof(struct wd_aead_msg)); + if (ret < 0) + goto out_sched; + + /* init ctx related resources in specific driver */ + priv = calloc(1, wd_aead_setting.driver->drv_ctx_size); + if (!priv) { + ret = -WD_ENOMEM; + goto out_priv; + } + wd_aead_setting.priv = priv; + + ret = wd_aead_setting.driver->init(&wd_aead_setting.config, priv); + if (ret < 0) { + WD_ERR("failed to init aead dirver!\n"); + goto out_init; + } + + return 0; + +out_init: + free(priv); + wd_aead_setting.priv = NULL; +out_priv: + wd_uninit_async_request_pool(&wd_aead_setting.pool); +out_sched: + wd_clear_sched(&wd_aead_setting.sched); +out: + wd_clear_ctx_config(&wd_aead_setting.config); + return ret; +} + +void wd_aead_uninit(void) +{ + void *priv = wd_aead_setting.priv; + + if (!priv) + return; + + wd_aead_setting.driver->exit(priv); + wd_aead_setting.priv = NULL; + free(priv); + + wd_uninit_async_request_pool(&wd_aead_setting.pool); + wd_clear_sched(&wd_aead_setting.sched); + wd_clear_ctx_config(&wd_aead_setting.config); +} + +static void fill_request_msg(struct wd_aead_msg *msg, struct wd_aead_req *req, + struct wd_aead_sess *sess) +{ + memcpy(&msg->req, req, sizeof(struct wd_aead_req)); + + msg->alg_type = WD_AEAD; + msg->calg = sess->calg; + msg->cmode = sess->cmode; + msg->dalg = sess->dalg; + msg->dmode = sess->dmode; + msg->op_type = req->op_type; + msg->in = req->src; + msg->in_bytes = req->in_bytes; + msg->out = req->dst; + msg->out_bytes = req->out_bytes; + msg->ckey = sess->ckey; + msg->ckey_bytes = sess->ckey_bytes; + msg->akey = sess->akey; + msg->akey_bytes = sess->akey_bytes; + msg->iv = req->iv; + msg->iv_bytes = req->iv_bytes; + msg->assoc_bytes = req->assoc_bytes; + msg->mac = req->mac; + msg->auth_bytes = sess->auth_bytes; + msg->data_fmt = req->data_fmt; +} + +static int send_recv_sync(struct wd_ctx_internal *ctx, + struct wd_aead_msg *msg) +{ + struct wd_msg_handle msg_handle; + int ret; + + msg_handle.send = wd_aead_setting.driver->aead_send; + msg_handle.recv = wd_aead_setting.driver->aead_recv; + + pthread_spin_lock(&ctx->lock); + ret = wd_handle_msg_sync(&msg_handle, ctx->ctx, msg, NULL, + wd_aead_setting.config.epoll_en); + pthread_spin_unlock(&ctx->lock); + return ret; +} + +int wd_do_aead_sync(handle_t h_sess, struct wd_aead_req *req) +{ + struct wd_ctx_config_internal *config = &wd_aead_setting.config; + struct wd_aead_sess *sess = (struct wd_aead_sess *)h_sess; + struct wd_ctx_internal *ctx; + struct wd_aead_msg msg; + __u32 idx; + int ret; + + ret = wd_aead_param_check(sess, req); + if (unlikely(ret)) + return -WD_EINVAL; + + memset(&msg, 0, sizeof(struct wd_aead_msg)); + fill_request_msg(&msg, req, sess); + req->state = 0; + + idx = wd_aead_setting.sched.pick_next_ctx( + wd_aead_setting.sched.h_sched_ctx, + sess->sched_key, CTX_MODE_SYNC); + ret = wd_check_ctx(config, CTX_MODE_SYNC, idx); + if (unlikely(ret)) + return ret; + + wd_dfx_msg_cnt(config->msg_cnt, WD_CTX_CNT_NUM, idx); + ctx = config->ctxs + idx; + ret = send_recv_sync(ctx, &msg); + req->state = msg.result; + + return ret; +} + +int wd_do_aead_async(handle_t h_sess, struct wd_aead_req *req) +{ + struct wd_ctx_config_internal *config = &wd_aead_setting.config; + struct wd_aead_sess *sess = (struct wd_aead_sess *)h_sess; + struct wd_ctx_internal *ctx; + struct wd_aead_msg *msg; + int msg_id, ret; + __u32 idx; + + ret = wd_aead_param_check(sess, req); + if (unlikely(ret)) + return -WD_EINVAL; + + if (unlikely(!req->cb)) { + WD_ERR("invalid: aead input req cb is NULL!\n"); + return -WD_EINVAL; + } + + idx = wd_aead_setting.sched.pick_next_ctx( + wd_aead_setting.sched.h_sched_ctx, + sess->sched_key, CTX_MODE_ASYNC); + ret = wd_check_ctx(config, CTX_MODE_ASYNC, idx); + if (ret) + return ret; + + wd_dfx_msg_cnt(config->msg_cnt, WD_CTX_CNT_NUM, idx); + ctx = config->ctxs + idx; + + msg_id = wd_get_msg_from_pool(&wd_aead_setting.pool, + idx, (void **)&msg); + if (unlikely(msg_id < 0)) { + WD_ERR("failed to get msg from pool!\n"); + return -WD_EBUSY; + } + + fill_request_msg(msg, req, sess); + msg->tag = msg_id; + + ret = wd_aead_setting.driver->aead_send(ctx->ctx, msg); + if (unlikely(ret < 0)) { + if (ret != -WD_EBUSY) + WD_ERR("failed to send BD, hw is err!\n"); + + goto fail_with_msg; + } + + ret = wd_add_task_to_async_queue(&wd_aead_env_config, idx); + if (ret) + goto fail_with_msg; + + return 0; + +fail_with_msg: + wd_put_msg_to_pool(&wd_aead_setting.pool, idx, msg->tag); + return ret; +} + +struct wd_aead_msg *wd_aead_get_msg(__u32 idx, __u32 tag) +{ + return wd_find_msg_in_pool(&wd_aead_setting.pool, idx, tag); +} + +int wd_aead_poll_ctx(__u32 idx, __u32 expt, __u32 *count) +{ + struct wd_ctx_config_internal *config = &wd_aead_setting.config; + struct wd_ctx_internal *ctx; + struct wd_aead_msg resp_msg, *msg; + struct wd_aead_req *req; + __u64 recv_count = 0; + __u32 tmp = expt; + int ret; + + if (unlikely(!count)) { + WD_ERR("invalid: aead poll ctx input param is NULL!\n"); + return -WD_EINVAL; + } + + *count = 0; + + ret = wd_check_ctx(config, CTX_MODE_ASYNC, idx); + if (ret) + return ret; + + ctx = config->ctxs + idx; + + do { + ret = wd_aead_setting.driver->aead_recv(ctx->ctx, &resp_msg); + if (ret == -WD_EAGAIN) { + return ret; + } else if (ret < 0) { + WD_ERR("wd aead recv hw err!\n"); + return ret; + } + + recv_count++; + msg = wd_find_msg_in_pool(&wd_aead_setting.pool, + idx, resp_msg.tag); + if (!msg) { + WD_ERR("failed to get msg from pool!\n"); + return -WD_EINVAL; + } + + msg->tag = resp_msg.tag; + msg->req.state = resp_msg.result; + req = &msg->req; + req->cb(req, req->cb_param); + wd_put_msg_to_pool(&wd_aead_setting.pool, + idx, resp_msg.tag); + *count = recv_count; + } while (--tmp); + + return ret; +} + +int wd_aead_poll(__u32 expt, __u32 *count) +{ + handle_t h_ctx = wd_aead_setting.sched.h_sched_ctx; + struct wd_sched *sched = &wd_aead_setting.sched; + + if (unlikely(!count)) { + WD_ERR("invalid: aead poll input param is NULL!\n"); + return -WD_EINVAL; + } + + return sched->poll_policy(h_ctx, expt, count); +} + +static const struct wd_config_variable table[] = { + { .name = "WD_AEAD_CTX_NUM", + .def_val = "sync:2@0,async:2@0", + .parse_fn = wd_parse_ctx_num + }, + { .name = "WD_AEAD_ASYNC_POLL_EN", + .def_val = "0", + .parse_fn = wd_parse_async_poll_en + } +}; + +static const struct wd_alg_ops wd_aead_ops = { + .alg_name = "aead", + .op_type_num = 1, + .alg_init = wd_aead_init, + .alg_uninit = wd_aead_uninit, + .alg_poll_ctx = wd_aead_poll_ctx +}; + +int wd_aead_env_init(struct wd_sched *sched) +{ + wd_aead_env_config.sched = sched; + + return wd_alg_env_init(&wd_aead_env_config, table, + &wd_aead_ops, ARRAY_SIZE(table), NULL); +} + +void wd_aead_env_uninit(void) +{ + return wd_alg_env_uninit(&wd_aead_env_config, &wd_aead_ops); +} + +int wd_aead_ctx_num_init(__u32 node, __u32 type, __u32 num, __u8 mode) +{ + struct wd_ctx_attr ctx_attr; + int ret; + + ret = wd_set_ctx_attr(&ctx_attr, node, CTX_TYPE_INVALID, mode, num); + if (ret) + return ret; + + return wd_alg_env_init(&wd_aead_env_config, table, + &wd_aead_ops, ARRAY_SIZE(table), &ctx_attr); +} + +void wd_aead_ctx_num_uninit(void) +{ + return wd_alg_env_uninit(&wd_aead_env_config, &wd_aead_ops); +} + +int wd_aead_get_env_param(__u32 node, __u32 type, __u32 mode, + __u32 *num, __u8 *is_enable) +{ + struct wd_ctx_attr ctx_attr; + int ret; + + ret = wd_set_ctx_attr(&ctx_attr, node, CTX_TYPE_INVALID, mode, 0); + if (ret) + return ret; + + return wd_alg_get_env_param(&wd_aead_env_config, + ctx_attr, num, is_enable); +} diff --git a/uadk/wd_cipher.c b/uadk/wd_cipher.c new file mode 100644 index 0000000..8ce975a --- /dev/null +++ b/uadk/wd_cipher.c @@ -0,0 +1,644 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. + * Copyright 2020-2021 Linaro ltd. + */ + +#include +#include +#include +#include "wd_util.h" +#include "include/drv/wd_cipher_drv.h" +#include "wd_cipher.h" + +#define XTS_MODE_KEY_DIVISOR 2 +#define SM4_KEY_SIZE 16 +#define DES_KEY_SIZE 8 +#define DES3_2KEY_SIZE (2 * DES_KEY_SIZE) +#define DES3_3KEY_SIZE (3 * DES_KEY_SIZE) +#define AES_KEYSIZE_128 16 +#define AES_KEYSIZE_192 24 +#define AES_KEYSIZE_256 32 + +#define WD_POOL_MAX_ENTRIES 1024 +#define DES_WEAK_KEY_NUM 16 + +static const unsigned char des_weak_keys[DES_WEAK_KEY_NUM][DES_KEY_SIZE] = { + /* weak keys */ + {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, + {0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE}, + {0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E}, + {0xE0, 0xE0, 0xE0, 0xE0, 0xF1, 0xF1, 0xF1, 0xF1}, + /* semi-weak keys */ + {0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE}, + {0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01}, + {0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1}, + {0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E}, + {0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1}, + {0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01}, + {0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE}, + {0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E}, + {0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E}, + {0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01}, + {0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE}, + {0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1} +}; + +struct wd_cipher_setting { + struct wd_ctx_config_internal config; + struct wd_sched sched; + void *sched_ctx; + struct wd_cipher_driver *driver; + void *priv; + void *dlhandle; + struct wd_async_msg_pool pool; +} wd_cipher_setting; + +struct wd_cipher_sess { + char *alg_name; + enum wd_cipher_alg alg; + enum wd_cipher_mode mode; + wd_dev_mask_t *dev_mask; + struct wd_alg_cipher *drv; + void *priv; + unsigned char key[MAX_CIPHER_KEY_SIZE]; + __u32 key_bytes; + void *sched_key; +}; + +struct wd_env_config wd_cipher_env_config; + +#ifdef WD_STATIC_DRV +static void wd_cipher_set_static_drv(void) +{ + wd_cipher_setting.driver = wd_cipher_get_driver(); + if (!wd_cipher_setting.driver) + WD_ERR("failed to get driver!\n"); +} +#else +static void __attribute__((constructor)) wd_cipher_open_driver(void) +{ + wd_cipher_setting.dlhandle = dlopen("libhisi_sec.so", RTLD_NOW); + if (!wd_cipher_setting.dlhandle) + WD_ERR("failed to open libhisi_sec.so!\n"); +} + +static void __attribute__((destructor)) wd_cipher_close_driver(void) +{ + if (wd_cipher_setting.dlhandle) + dlclose(wd_cipher_setting.dlhandle); +} +#endif + +void wd_cipher_set_driver(struct wd_cipher_driver *drv) +{ + wd_cipher_setting.driver = drv; +} + +static bool is_des_weak_key(const __u8 *key) +{ + int i; + + for (i = 0; i < DES_WEAK_KEY_NUM; i++) { + if (memcmp(des_weak_keys[i], key, DES_KEY_SIZE) == 0) + return true; + } + + return false; +} + +static int aes_key_len_check(__u32 length) +{ + switch (length) { + case AES_KEYSIZE_128: + case AES_KEYSIZE_192: + case AES_KEYSIZE_256: + return 0; + default: + return -WD_EINVAL; + } +} + +static int cipher_key_len_check(struct wd_cipher_sess *sess, __u32 length) +{ + int ret = 0; + + if (sess->mode == WD_CIPHER_XTS && length == AES_KEYSIZE_192) { + WD_ERR("unsupported XTS key length, length = %u\n", length); + return -WD_EINVAL; + } + + switch (sess->alg) { + case WD_CIPHER_SM4: + if (length != SM4_KEY_SIZE) + ret = -WD_EINVAL; + break; + case WD_CIPHER_AES: + ret = aes_key_len_check(length); + break; + case WD_CIPHER_DES: + if (length != DES_KEY_SIZE) + ret = -WD_EINVAL; + break; + case WD_CIPHER_3DES: + if (length != DES3_2KEY_SIZE && length != DES3_3KEY_SIZE) + ret = -WD_EINVAL; + break; + default: + WD_ERR("cipher input alg err, alg = %d\n", sess->alg); + return -WD_EINVAL; + } + + return ret; +} + +int wd_cipher_set_key(handle_t h_sess, const __u8 *key, __u32 key_len) +{ + struct wd_cipher_sess *sess = (struct wd_cipher_sess *)h_sess; + __u32 length = key_len; + int ret; + + if (!key || !sess) { + WD_ERR("invalid: cipher set key input param err!\n"); + return -WD_EINVAL; + } + + if (sess->mode == WD_CIPHER_XTS) + length = key_len / XTS_MODE_KEY_DIVISOR; + + ret = cipher_key_len_check(sess, length); + if (ret) { + WD_ERR("cipher set key input key length err!\n"); + return -WD_EINVAL; + } + if (sess->alg == WD_CIPHER_DES && is_des_weak_key(key)) { + WD_ERR("input des key is weak key!\n"); + return -WD_EINVAL; + } + + sess->key_bytes = key_len; + memcpy(sess->key, key, key_len); + + return 0; +} + +handle_t wd_cipher_alloc_sess(struct wd_cipher_sess_setup *setup) +{ + struct wd_cipher_sess *sess = NULL; + + if (unlikely(!setup)) { + WD_ERR("invalid: cipher input setup is NULL!\n"); + return (handle_t)0; + } + + sess = malloc(sizeof(struct wd_cipher_sess)); + if (!sess) { + WD_ERR("failed to alloc session memory!\n"); + return (handle_t)0; + } + memset(sess, 0, sizeof(struct wd_cipher_sess)); + + sess->alg = setup->alg; + sess->mode = setup->mode; + /* Some simple scheduler don't need scheduling parameters */ + sess->sched_key = (void *)wd_cipher_setting.sched.sched_init( + wd_cipher_setting.sched.h_sched_ctx, setup->sched_param); + if (WD_IS_ERR(sess->sched_key)) { + WD_ERR("failed to init session schedule key!\n"); + free(sess); + return (handle_t)0; + } + + return (handle_t)sess; +} + +void wd_cipher_free_sess(handle_t h_sess) +{ + struct wd_cipher_sess *sess = (struct wd_cipher_sess *)h_sess; + + if (unlikely(!sess)) { + WD_ERR("invalid: cipher input h_sess is NULL!\n"); + return; + } + + wd_memset_zero(sess->key, MAX_CIPHER_KEY_SIZE); + + if (sess->sched_key) + free(sess->sched_key); + free(sess); +} + +int wd_cipher_init(struct wd_ctx_config *config, struct wd_sched *sched) +{ + void *priv; + int ret; + + ret = wd_init_param_check(config, sched); + if (ret) + return ret; + + ret = wd_set_epoll_en("WD_CIPHER_EPOLL_EN", + &wd_cipher_setting.config.epoll_en); + if (ret < 0) + return ret; + + ret = wd_init_ctx_config(&wd_cipher_setting.config, config); + if (ret < 0) + return ret; + + ret = wd_init_sched(&wd_cipher_setting.sched, sched); + if (ret < 0) + goto out; + +#ifdef WD_STATIC_DRV + /* set driver */ + wd_cipher_set_static_drv(); +#endif + + /* allocate async pool for every ctx */ + ret = wd_init_async_request_pool(&wd_cipher_setting.pool, + config->ctx_num, WD_POOL_MAX_ENTRIES, + sizeof(struct wd_cipher_msg)); + if (ret < 0) + goto out_sched; + + /* init ctx related resources in specific driver */ + priv = calloc(1, wd_cipher_setting.driver->drv_ctx_size); + if (!priv) { + ret = -WD_ENOMEM; + goto out_priv; + } + wd_cipher_setting.priv = priv; + + ret = wd_cipher_setting.driver->init(&wd_cipher_setting.config, priv); + if (ret < 0) { + WD_ERR("hisi sec init failed.\n"); + goto out_init; + } + + return 0; + +out_init: + free(priv); + wd_cipher_setting.priv = NULL; +out_priv: + wd_uninit_async_request_pool(&wd_cipher_setting.pool); +out_sched: + wd_clear_sched(&wd_cipher_setting.sched); +out: + wd_clear_ctx_config(&wd_cipher_setting.config); + return ret; +} + +void wd_cipher_uninit(void) +{ + void *priv = wd_cipher_setting.priv; + + if (!priv) + return; + + wd_cipher_setting.driver->exit(priv); + wd_cipher_setting.priv = NULL; + free(priv); + + wd_uninit_async_request_pool(&wd_cipher_setting.pool); + wd_clear_sched(&wd_cipher_setting.sched); + wd_clear_ctx_config(&wd_cipher_setting.config); +} + +static void fill_request_msg(struct wd_cipher_msg *msg, + struct wd_cipher_req *req, + struct wd_cipher_sess *sess) +{ + memcpy(&msg->req, req, sizeof(struct wd_cipher_req)); + + msg->alg_type = WD_CIPHER; + msg->alg = sess->alg; + msg->mode = sess->mode; + msg->op_type = req->op_type; + msg->in = req->src; + msg->in_bytes = req->in_bytes; + msg->out = req->dst; + msg->out_bytes = req->out_bytes; + msg->key = sess->key; + msg->key_bytes = sess->key_bytes; + msg->iv = req->iv; + msg->iv_bytes = req->iv_bytes; + msg->data_fmt = req->data_fmt; +} + +static int cipher_iv_len_check(struct wd_cipher_req *req, + struct wd_cipher_sess *sess) +{ + int ret = 0; + + /* Only the ECB mode does not need iv. */ + if (sess->mode == WD_CIPHER_ECB) + return 0; + + switch (sess->alg) { + case WD_CIPHER_AES: + case WD_CIPHER_SM4: + if (req->iv_bytes != AES_BLOCK_SIZE) { + WD_ERR("AES or SM4 input iv bytes is err, size = %u\n", + req->iv_bytes); + ret = -WD_EINVAL; + } + break; + case WD_CIPHER_3DES: + case WD_CIPHER_DES: + if (req->iv_bytes != DES3_BLOCK_SIZE) { + WD_ERR("3DES or DES input iv bytes is err, size = %u\n", + req->iv_bytes); + ret = -WD_EINVAL; + } + break; + default: + ret = -WD_EINVAL; + break; + } + + return ret; +} + +static int wd_cipher_check_params(handle_t h_sess, + struct wd_cipher_req *req, __u8 mode) +{ + struct wd_cipher_sess *sess = (struct wd_cipher_sess *)h_sess; + int ret; + + if (unlikely(!h_sess || !req)) { + WD_ERR("invalid: cipher input sess or req is NULL!\n"); + return -WD_EINVAL; + } + + if (unlikely(mode == CTX_MODE_ASYNC && !req->cb)) { + WD_ERR("invalid: cipher req cb is NULL!\n"); + return -WD_EINVAL; + } + + if (unlikely(req->out_buf_bytes < req->in_bytes)) { + WD_ERR("cipher set out_buf_bytes is error, size = %u\n", + req->out_buf_bytes); + return -WD_EINVAL; + } + + if (req->data_fmt == WD_SGL_BUF) { + ret = wd_check_datalist(req->list_src, req->in_bytes); + if (unlikely(ret)) { + WD_ERR("failed to check the src datalist, len = %u\n", + req->in_bytes); + return -WD_EINVAL; + } + + /* cipher dst len is equal to src len */ + ret = wd_check_datalist(req->list_dst, req->in_bytes); + if (unlikely(ret)) { + WD_ERR("failed to check the dst datalist, len = %u\n", + req->in_bytes); + return -WD_EINVAL; + } + } + + return cipher_iv_len_check(req, sess); +} + +static int send_recv_sync(struct wd_ctx_internal *ctx, + struct wd_cipher_msg *msg) +{ + struct wd_msg_handle msg_handle; + int ret; + + msg_handle.send = wd_cipher_setting.driver->cipher_send; + msg_handle.recv = wd_cipher_setting.driver->cipher_recv; + + pthread_spin_lock(&ctx->lock); + ret = wd_handle_msg_sync(&msg_handle, ctx->ctx, msg, NULL, + wd_cipher_setting.config.epoll_en); + pthread_spin_unlock(&ctx->lock); + return ret; +} + +int wd_do_cipher_sync(handle_t h_sess, struct wd_cipher_req *req) +{ + struct wd_ctx_config_internal *config = &wd_cipher_setting.config; + struct wd_cipher_sess *sess = (struct wd_cipher_sess *)h_sess; + struct wd_ctx_internal *ctx; + struct wd_cipher_msg msg; + __u32 idx; + int ret; + + ret = wd_cipher_check_params(h_sess, req, CTX_MODE_SYNC); + if (unlikely(ret)) { + WD_ERR("failed to check cipher params!\n"); + return ret; + } + + memset(&msg, 0, sizeof(struct wd_cipher_msg)); + fill_request_msg(&msg, req, sess); + req->state = 0; + + idx = wd_cipher_setting.sched.pick_next_ctx( + wd_cipher_setting.sched.h_sched_ctx, + sess->sched_key, CTX_MODE_SYNC); + ret = wd_check_ctx(config, CTX_MODE_SYNC, idx); + if (unlikely(ret)) + return ret; + + wd_dfx_msg_cnt(config->msg_cnt, WD_CTX_CNT_NUM, idx); + ctx = config->ctxs + idx; + + ret = send_recv_sync(ctx, &msg); + req->state = msg.result; + + return ret; +} + +int wd_do_cipher_async(handle_t h_sess, struct wd_cipher_req *req) +{ + struct wd_ctx_config_internal *config = &wd_cipher_setting.config; + struct wd_cipher_sess *sess = (struct wd_cipher_sess *)h_sess; + struct wd_ctx_internal *ctx; + struct wd_cipher_msg *msg; + int msg_id, ret; + __u32 idx; + + ret = wd_cipher_check_params(h_sess, req, CTX_MODE_ASYNC); + if (unlikely(ret)) { + WD_ERR("failed to check cipher params!\n"); + return ret; + } + + idx = wd_cipher_setting.sched.pick_next_ctx( + wd_cipher_setting.sched.h_sched_ctx, + sess->sched_key, CTX_MODE_ASYNC); + ret = wd_check_ctx(config, CTX_MODE_ASYNC, idx); + if (ret) + return ret; + + ctx = config->ctxs + idx; + wd_dfx_msg_cnt(config->msg_cnt, WD_CTX_CNT_NUM, idx); + + msg_id = wd_get_msg_from_pool(&wd_cipher_setting.pool, idx, + (void **)&msg); + if (unlikely(msg_id < 0)) { + WD_ERR("busy, failed to get msg from pool!\n"); + return -WD_EBUSY; + } + + fill_request_msg(msg, req, sess); + msg->tag = msg_id; + + ret = wd_cipher_setting.driver->cipher_send(ctx->ctx, msg); + if (unlikely(ret < 0)) { + if (ret != -WD_EBUSY) + WD_ERR("wd cipher async send err!\n"); + + goto fail_with_msg; + } + + ret = wd_add_task_to_async_queue(&wd_cipher_env_config, idx); + if (ret) + goto fail_with_msg; + + return 0; + +fail_with_msg: + wd_put_msg_to_pool(&wd_cipher_setting.pool, idx, msg->tag); + return ret; +} + +struct wd_cipher_msg *wd_cipher_get_msg(__u32 idx, __u32 tag) +{ + return wd_find_msg_in_pool(&wd_cipher_setting.pool, idx, tag); +} + +int wd_cipher_poll_ctx(__u32 idx, __u32 expt, __u32 *count) +{ + struct wd_ctx_config_internal *config = &wd_cipher_setting.config; + struct wd_ctx_internal *ctx; + struct wd_cipher_msg resp_msg, *msg; + struct wd_cipher_req *req; + __u64 recv_count = 0; + __u32 tmp = expt; + int ret; + + if (unlikely(!count)) { + WD_ERR("invalid: cipher poll ctx input param is NULL!\n"); + return -WD_EINVAL; + } + + *count = 0; + + ret = wd_check_ctx(config, CTX_MODE_ASYNC, idx); + if (ret) + return ret; + + ctx = config->ctxs + idx; + + do { + ret = wd_cipher_setting.driver->cipher_recv(ctx->ctx, &resp_msg); + if (ret == -WD_EAGAIN) + return ret; + else if (ret < 0) { + WD_ERR("wd cipher recv hw err!\n"); + return ret; + } + recv_count++; + msg = wd_find_msg_in_pool(&wd_cipher_setting.pool, idx, + resp_msg.tag); + if (!msg) { + WD_ERR("failed to get msg from pool!\n"); + return -WD_EINVAL; + } + + msg->tag = resp_msg.tag; + msg->req.state = resp_msg.result; + req = &msg->req; + + req->cb(req, req->cb_param); + /* free msg cache to msg_pool */ + wd_put_msg_to_pool(&wd_cipher_setting.pool, idx, + resp_msg.tag); + *count = recv_count; + } while (--tmp); + + return ret; +} + +int wd_cipher_poll(__u32 expt, __u32 *count) +{ + handle_t h_ctx = wd_cipher_setting.sched.h_sched_ctx; + struct wd_sched *sched = &wd_cipher_setting.sched; + + if (unlikely(!count)) { + WD_ERR("invalid: cipher poll input param is NULL!\n"); + return -WD_EINVAL; + } + + return sched->poll_policy(h_ctx, expt, count); +} + +static const struct wd_config_variable table[] = { + { .name = "WD_CIPHER_CTX_NUM", + .def_val = "sync:2@0,async:2@0", + .parse_fn = wd_parse_ctx_num + }, + { .name = "WD_CIPHER_ASYNC_POLL_EN", + .def_val = "0", + .parse_fn = wd_parse_async_poll_en + } +}; + +static const struct wd_alg_ops wd_cipher_ops = { + .alg_name = "cipher", + .op_type_num = 1, + .alg_init = wd_cipher_init, + .alg_uninit = wd_cipher_uninit, + .alg_poll_ctx = wd_cipher_poll_ctx +}; + +int wd_cipher_env_init(struct wd_sched *sched) +{ + wd_cipher_env_config.sched = sched; + + return wd_alg_env_init(&wd_cipher_env_config, table, + &wd_cipher_ops, ARRAY_SIZE(table), NULL); +} + +void wd_cipher_env_uninit(void) +{ + return wd_alg_env_uninit(&wd_cipher_env_config, &wd_cipher_ops); +} + +int wd_cipher_ctx_num_init(__u32 node, __u32 type, __u32 num, __u8 mode) +{ + struct wd_ctx_attr ctx_attr; + int ret; + + ret = wd_set_ctx_attr(&ctx_attr, node, CTX_TYPE_INVALID, mode, num); + if (ret) + return ret; + + return wd_alg_env_init(&wd_cipher_env_config, table, + &wd_cipher_ops, ARRAY_SIZE(table), &ctx_attr); +} + +void wd_cipher_ctx_num_uninit(void) +{ + return wd_alg_env_uninit(&wd_cipher_env_config, &wd_cipher_ops); +} + +int wd_cipher_get_env_param(__u32 node, __u32 type, __u32 mode, + __u32 *num, __u8 *is_enable) +{ + struct wd_ctx_attr ctx_attr; + int ret; + + ret = wd_set_ctx_attr(&ctx_attr, node, CTX_TYPE_INVALID, mode, 0); + if (ret) + return ret; + + return wd_alg_get_env_param(&wd_cipher_env_config, + ctx_attr, num, is_enable); +} diff --git a/uadk/wd_comp.c b/uadk/wd_comp.c new file mode 100644 index 0000000..eacebd3 --- /dev/null +++ b/uadk/wd_comp.c @@ -0,0 +1,777 @@ +// SPDX-License-Identifier: Apache-2.0 +/* + * Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. + * Copyright 2020-2021 Linaro ltd. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "drv/wd_comp_drv.h" +#include "wd_util.h" +#include "wd_comp.h" + +#define WD_POOL_MAX_ENTRIES 1024 +#define HW_CTX_SIZE (64 * 1024) +#define STREAM_CHUNK (128 * 1024) + +#define swap_byte(x) \ + ((((x) & 0x000000ff) << 24) | \ + (((x) & 0x0000ff00) << 8) | \ + (((x) & 0x00ff0000) >> 8) | \ + (((x) & 0xff000000) >> 24)) + +#define cpu_to_be32(x) swap_byte(x) + +struct wd_comp_sess { + enum wd_comp_alg_type alg_type; + enum wd_comp_level comp_lv; + enum wd_comp_winsz_type win_sz; + enum wd_comp_strm_pos stream_pos; + __u32 isize; + __u32 checksum; + __u8 *ctx_buf; + void *sched_key; +}; + +struct wd_comp_setting { + struct wd_ctx_config_internal config; + struct wd_sched sched; + struct wd_comp_driver *driver; + void *priv; + void *dlhandle; + struct wd_async_msg_pool pool; +} wd_comp_setting; + +struct wd_env_config wd_comp_env_config; + +#ifdef WD_STATIC_DRV +static void wd_comp_set_static_drv(void) +{ + wd_comp_setting.driver = wd_comp_get_driver(); + if (!wd_comp_setting.driver) + WD_ERR("failed to get driver!\n"); +} +#else +static void __attribute__((constructor)) wd_comp_open_driver(void) +{ + wd_comp_setting.dlhandle = dlopen("libhisi_zip.so", RTLD_NOW); + if (!wd_comp_setting.dlhandle) + WD_ERR("failed to open libhisi_zip.so!\n"); +} + +static void __attribute__((destructor)) wd_comp_close_driver(void) +{ + if (wd_comp_setting.dlhandle) + dlclose(wd_comp_setting.dlhandle); +} +#endif + +void wd_comp_set_driver(struct wd_comp_driver *drv) +{ + wd_comp_setting.driver = drv; +} + +int wd_comp_init(struct wd_ctx_config *config, struct wd_sched *sched) +{ + void *priv; + int ret; + + ret = wd_init_param_check(config, sched); + if (ret) + return ret; + + ret = wd_set_epoll_en("WD_COMP_EPOLL_EN", + &wd_comp_setting.config.epoll_en); + if (ret < 0) + return ret; + + ret = wd_init_ctx_config(&wd_comp_setting.config, config); + if (ret < 0) + return ret; + + ret = wd_init_sched(&wd_comp_setting.sched, sched); + if (ret < 0) + goto out; + /* + * Fix me: ctx could be passed into wd_comp_set_static_drv to help to + * choose static compiled vendor driver. For dynamic vendor driver, + * wd_comp_open_driver will be called in the process of opening + * libwd_comp.so to load related driver dynamic library. Vendor driver + * pointer will be passed to wd_comp_setting.driver in the process of + * opening of vendor driver dynamic library. A configure file could be + * introduced to help to define which vendor driver lib should be + * loaded. + */ +#ifdef WD_STATIC_DRV + wd_comp_set_static_drv(); +#endif + + /* fix me: sadly find we allocate async pool for every ctx */ + ret = wd_init_async_request_pool(&wd_comp_setting.pool, + config->ctx_num, WD_POOL_MAX_ENTRIES, + sizeof(struct wd_comp_msg)); + if (ret < 0) + goto out_sched; + + /* init ctx related resources in specific driver */ + priv = calloc(1, wd_comp_setting.driver->drv_ctx_size); + if (!priv) { + ret = -WD_ENOMEM; + goto out_priv; + } + wd_comp_setting.priv = priv; + ret = wd_comp_setting.driver->init(&wd_comp_setting.config, priv); + if (ret < 0) { + WD_ERR("failed to do driver init, ret = %d!\n", ret); + goto out_init; + } + return 0; + +out_init: + free(priv); + wd_comp_setting.priv = NULL; +out_priv: + wd_uninit_async_request_pool(&wd_comp_setting.pool); +out_sched: + wd_clear_sched(&wd_comp_setting.sched); +out: + wd_clear_ctx_config(&wd_comp_setting.config); + return ret; +} + +void wd_comp_uninit(void) +{ + void *priv = wd_comp_setting.priv; + + if (!priv) + return; + + wd_comp_setting.driver->exit(priv); + free(priv); + wd_comp_setting.priv = NULL; + + /* uninit async request pool */ + wd_uninit_async_request_pool(&wd_comp_setting.pool); + + /* unset config, sched, driver */ + wd_clear_sched(&wd_comp_setting.sched); + wd_clear_ctx_config(&wd_comp_setting.config); +} + +struct wd_comp_msg *wd_comp_get_msg(__u32 idx, __u32 tag) +{ + return wd_find_msg_in_pool(&wd_comp_setting.pool, idx, tag); +} + +int wd_comp_poll_ctx(__u32 idx, __u32 expt, __u32 *count) +{ + struct wd_ctx_config_internal *config = &wd_comp_setting.config; + struct wd_ctx_internal *ctx; + struct wd_comp_msg resp_msg; + struct wd_comp_msg *msg; + struct wd_comp_req *req; + __u64 recv_count = 0; + __u32 tmp = expt; + int ret; + + if (unlikely(!count)) { + WD_ERR("invalid: comp poll count is 0!\n"); + return -WD_EINVAL; + } + + *count = 0; + + ret = wd_check_ctx(config, CTX_MODE_ASYNC, idx); + if (unlikely(ret)) + return ret; + + ctx = config->ctxs + idx; + + do { + ret = wd_comp_setting.driver->comp_recv(ctx->ctx, &resp_msg); + if (unlikely(ret < 0)) { + if (ret == -WD_HW_EACCESS) + WD_ERR("wd comp recv hw error!\n"); + return ret; + } + + recv_count++; + + msg = wd_find_msg_in_pool(&wd_comp_setting.pool, idx, + resp_msg.tag); + if (unlikely(!msg)) { + WD_ERR("failed to get msg from pool!\n"); + return -WD_EINVAL; + } + + req = &msg->req; + req->src_len = msg->in_cons; + req->dst_len = msg->produced; + req->cb(req, req->cb_param); + + /* free msg cache to msg_pool */ + wd_put_msg_to_pool(&wd_comp_setting.pool, idx, resp_msg.tag); + *count = recv_count; + } while (--tmp); + + return ret; +} + +static int wd_comp_check_sess_params(struct wd_comp_sess_setup *setup) +{ + if (setup->alg_type >= WD_COMP_ALG_MAX) { + WD_ERR("invalid: alg_type is %d!\n", setup->alg_type); + return -WD_EINVAL; + } + + if (setup->op_type >= WD_DIR_MAX) { + WD_ERR("invalid: op_type is %d!\n", setup->op_type); + return -WD_EINVAL; + } + + if (setup->op_type == WD_DIR_DECOMPRESS) + return WD_SUCCESS; + + if (setup->comp_lv > WD_COMP_L15) { + WD_ERR("invalid: comp_lv is %d!\n", setup->comp_lv); + return -WD_EINVAL; + } + + if (setup->win_sz > WD_COMP_WS_32K) { + WD_ERR("invalid: win_sz is %d!\n", setup->win_sz); + return -WD_EINVAL; + } + + return WD_SUCCESS; +} + +handle_t wd_comp_alloc_sess(struct wd_comp_sess_setup *setup) +{ + struct wd_comp_sess *sess; + int ret; + + if (!setup) + return (handle_t)0; + + ret = wd_comp_check_sess_params(setup); + if (ret) + return (handle_t)0; + + sess = calloc(1, sizeof(struct wd_comp_sess)); + if (!sess) + return (handle_t)0; + + sess->ctx_buf = calloc(1, HW_CTX_SIZE); + if (!sess->ctx_buf) + goto sess_err; + + sess->alg_type = setup->alg_type; + sess->comp_lv = setup->comp_lv; + sess->win_sz = setup->win_sz; + sess->stream_pos = WD_COMP_STREAM_NEW; + /* Some simple scheduler don't need scheduling parameters */ + sess->sched_key = (void *)wd_comp_setting.sched.sched_init( + wd_comp_setting.sched.h_sched_ctx, setup->sched_param); + if (WD_IS_ERR(sess->sched_key)) { + WD_ERR("failed to init session schedule key!\n"); + goto sched_err; + } + + return (handle_t)sess; + +sched_err: + free(sess->ctx_buf); +sess_err: + free(sess); + return (handle_t)0; +} + +void wd_comp_free_sess(handle_t h_sess) +{ + struct wd_comp_sess *sess = (struct wd_comp_sess *)h_sess; + + if (!sess) + return; + + if (sess->ctx_buf) + free(sess->ctx_buf); + + if (sess->sched_key) + free(sess->sched_key); + free(sess); +} + +static void fill_comp_msg(struct wd_comp_sess *sess, struct wd_comp_msg *msg, + struct wd_comp_req *req) +{ + memcpy(&msg->req, req, sizeof(struct wd_comp_req)); + + msg->alg_type = sess->alg_type; + msg->comp_lv = sess->comp_lv; + msg->win_sz = sess->win_sz; + msg->avail_out = req->dst_len; + + /* if is last 1: flush end; other: sync flush */ + msg->req.last = 1; +} + +static int wd_comp_check_buffer(struct wd_comp_req *req) +{ + if (req->data_fmt == WD_FLAT_BUF) { + if (unlikely(!req->src || !req->dst)) { + WD_ERR("invalid: src or dst is NULL!\n"); + return -WD_EINVAL; + } + } else if (req->data_fmt == WD_SGL_BUF) { + if (unlikely(!req->list_src || !req->list_dst)) { + WD_ERR("invalid: list_src or list_dst is NULL!\n"); + return -WD_EINVAL; + } + } + + if (!req->dst_len) { + WD_ERR("invalid: dst_len is NULL!\n"); + return -WD_EINVAL; + } + + return 0; +} + +static int wd_comp_check_params(struct wd_comp_sess *sess, + struct wd_comp_req *req, + __u8 mode) +{ + int ret; + + if (unlikely(!sess || !req)) { + WD_ERR("invalid: sess or req is NULL!\n"); + return -WD_EINVAL; + } + + if (unlikely(req->data_fmt > WD_SGL_BUF)) { + WD_ERR("invalid: data_fmt is %d!\n", req->data_fmt); + return -WD_EINVAL; + } + + ret = wd_comp_check_buffer(req); + if (unlikely(ret)) + return ret; + + if (unlikely(req->op_type != WD_DIR_COMPRESS && + req->op_type != WD_DIR_DECOMPRESS)) { + WD_ERR("invalid: op_type is %d!\n", req->op_type); + return -WD_EINVAL; + } + + if (unlikely(mode == CTX_MODE_ASYNC && !req->cb)) { + WD_ERR("invalid: async comp cb is NULL!\n"); + return -WD_EINVAL; + } + + if (unlikely(mode == CTX_MODE_ASYNC && !req->cb_param)) { + WD_ERR("invalid: async comp cb param is NULL!\n"); + return -WD_EINVAL; + } + + if (unlikely(mode == CTX_MODE_SYNC && req->cb)) { + WD_ERR("invalid: sync comp cb should be NULL!\n"); + return -WD_EINVAL; + } + + return 0; +} + +static int wd_comp_sync_job(struct wd_comp_sess *sess, + struct wd_comp_req *req, + struct wd_comp_msg *msg) +{ + struct wd_ctx_config_internal *config = &wd_comp_setting.config; + handle_t h_sched_ctx = wd_comp_setting.sched.h_sched_ctx; + struct wd_msg_handle msg_handle; + struct wd_ctx_internal *ctx; + __u32 idx; + int ret; + + idx = wd_comp_setting.sched.pick_next_ctx(h_sched_ctx, + sess->sched_key, + CTX_MODE_SYNC); + ret = wd_check_ctx(config, CTX_MODE_SYNC, idx); + if (unlikely(ret)) + return ret; + + wd_dfx_msg_cnt(config->msg_cnt, WD_CTX_CNT_NUM, idx); + ctx = config->ctxs + idx; + + msg_handle.send = wd_comp_setting.driver->comp_send; + msg_handle.recv = wd_comp_setting.driver->comp_recv; + + pthread_spin_lock(&ctx->lock); + ret = wd_handle_msg_sync(&msg_handle, ctx->ctx, msg, + NULL, config->epoll_en); + pthread_spin_unlock(&ctx->lock); + + return ret; +} + +int wd_do_comp_sync(handle_t h_sess, struct wd_comp_req *req) +{ + struct wd_comp_sess *sess = (struct wd_comp_sess *)h_sess; + struct wd_comp_msg msg; + int ret; + + ret = wd_comp_check_params(sess, req, CTX_MODE_SYNC); + if (unlikely(ret)) + return ret; + + if (unlikely(!req->src_len)) { + WD_ERR("invalid: req src_len is 0!\n"); + return -WD_EINVAL; + } + + memset(&msg, 0, sizeof(struct wd_comp_msg)); + + fill_comp_msg(sess, &msg, req); + msg.ctx_buf = sess->ctx_buf; + msg.stream_mode = WD_COMP_STATELESS; + + ret = wd_comp_sync_job(sess, req, &msg); + if (unlikely(ret)) + return ret; + + req->src_len = msg.in_cons; + req->dst_len = msg.produced; + req->status = msg.req.status; + + return 0; +} + +int wd_do_comp_sync2(handle_t h_sess, struct wd_comp_req *req) +{ + struct wd_comp_sess *sess = (struct wd_comp_sess *)h_sess; + struct wd_comp_req strm_req; + __u32 chunk = STREAM_CHUNK; + __u32 total_avail_in; + __u32 total_avail_out; + int ret; + + ret = wd_comp_check_params(sess, req, CTX_MODE_SYNC); + if (unlikely(ret)) + return ret; + + if (unlikely(!req->src_len)) { + WD_ERR("invalid: req src_len is 0!\n"); + return -WD_EINVAL; + } + + total_avail_in = req->src_len; + total_avail_out = req->dst_len; + /* strm_req and req share the same src and dst buffer */ + memcpy(&strm_req, req, sizeof(struct wd_comp_req)); + req->dst_len = 0; + strm_req.last = 0; + + do { + strm_req.src_len = total_avail_in > chunk ? chunk : + total_avail_in; + strm_req.dst_len = total_avail_out > chunk ? chunk : + total_avail_out; + if (req->op_type == WD_DIR_COMPRESS) { + /* find the last chunk to compress */ + if (total_avail_in <= chunk) + strm_req.last = 1; + } + + ret = wd_do_comp_strm(h_sess, &strm_req); + if (unlikely(ret < 0 || strm_req.status == WD_IN_EPARA)) { + WD_ERR("wd comp, invalid or incomplete data! ret = %d, status = %u!\n", + ret, strm_req.status); + return ret; + } + + req->dst_len += strm_req.dst_len; + strm_req.dst += strm_req.dst_len; + total_avail_out -= strm_req.dst_len; + + strm_req.src += strm_req.src_len; + total_avail_in -= strm_req.src_len; + + /* + * When a stream request end, 'stream_pos' will be reset as + * 'WD_COMP_STREAM_NEW' in wd_do_comp_strm. + */ + } while (sess->stream_pos != WD_COMP_STREAM_NEW); + + req->status = 0; + + return 0; +} + +static unsigned int bit_reverse(register unsigned int target) +{ + register unsigned int x = target; + + x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1)); + x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2)); + x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4)); + x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8)); + + return ((x >> 16) | (x << 16)); +} + +/** + * append_store_block() - output an fixed store block when input + * a empty block as last stream block. And supplement the packet + * tail according to the protocol. + * @sess: The session which request will be sent to. + * @req: The last request which is empty. + */ +static int append_store_block(struct wd_comp_sess *sess, + struct wd_comp_req *req) +{ + unsigned char store_block[5] = {0x1, 0x00, 0x00, 0xff, 0xff}; + int blocksize = ARRAY_SIZE(store_block); + __u32 checksum = sess->checksum; + __u32 isize = sess->isize; + + if (sess->alg_type == WD_ZLIB) { + if (unlikely(req->dst_len < blocksize + sizeof(checksum))) + return -WD_EINVAL; + memcpy(req->dst, store_block, blocksize); + req->dst_len = blocksize; + checksum = (__u32) cpu_to_be32(checksum); + /* if zlib, ADLER32 */ + memcpy(req->dst + blocksize, &checksum, sizeof(checksum)); + req->dst_len += sizeof(checksum); + } else if (sess->alg_type == WD_GZIP) { + if (unlikely(req->dst_len < blocksize + + sizeof(checksum) + sizeof(isize))) + return -WD_EINVAL; + memcpy(req->dst, store_block, blocksize); + req->dst_len = blocksize; + checksum = ~checksum; + checksum = bit_reverse(checksum); + /* if gzip, CRC32 and ISIZE */ + memcpy(req->dst + blocksize, &checksum, sizeof(checksum)); + memcpy(req->dst + blocksize + sizeof(checksum), + &isize, sizeof(isize)); + req->dst_len += sizeof(checksum); + req->dst_len += sizeof(isize); + } + + req->status = 0; + sess->stream_pos = WD_COMP_STREAM_NEW; + + return 0; +} + +static void wd_do_comp_strm_end_check(struct wd_comp_sess *sess, + struct wd_comp_req *req, + __u32 src_len) +{ + if (req->op_type == WD_DIR_COMPRESS && req->last == 1 && + req->src_len == src_len) + sess->stream_pos = WD_COMP_STREAM_NEW; + else if (req->op_type == WD_DIR_DECOMPRESS && + req->status == WD_STREAM_END) + sess->stream_pos = WD_COMP_STREAM_NEW; +} + +int wd_do_comp_strm(handle_t h_sess, struct wd_comp_req *req) +{ + struct wd_comp_sess *sess = (struct wd_comp_sess *)h_sess; + struct wd_comp_msg msg; + __u32 src_len; + int ret; + + ret = wd_comp_check_params(sess, req, CTX_MODE_SYNC); + if (unlikely(ret)) + return ret; + + if (unlikely(req->data_fmt > WD_FLAT_BUF)) { + WD_ERR("invalid: data_fmt is %d!\n", req->data_fmt); + return -WD_EINVAL; + } + + if (sess->alg_type <= WD_GZIP && req->op_type == WD_DIR_COMPRESS && + req->last == 1 && req->src_len == 0) + return append_store_block(sess, req); + + fill_comp_msg(sess, &msg, req); + msg.stream_pos = sess->stream_pos; + msg.ctx_buf = sess->ctx_buf; + msg.isize = sess->isize; + msg.checksum = sess->checksum; + /* fill true flag */ + msg.req.last = req->last; + msg.stream_mode = WD_COMP_STATEFUL; + + src_len = req->src_len; + + ret = wd_comp_sync_job(sess, req, &msg); + if (unlikely(ret)) + return ret; + + req->src_len = msg.in_cons; + req->dst_len = msg.produced; + req->status = msg.req.status; + sess->isize = msg.isize; + sess->checksum = msg.checksum; + + sess->stream_pos = WD_COMP_STREAM_OLD; + + wd_do_comp_strm_end_check(sess, req, src_len); + + return 0; +} + +int wd_do_comp_async(handle_t h_sess, struct wd_comp_req *req) +{ + struct wd_ctx_config_internal *config = &wd_comp_setting.config; + struct wd_comp_sess *sess = (struct wd_comp_sess *)h_sess; + handle_t h_sched_ctx = wd_comp_setting.sched.h_sched_ctx; + struct wd_ctx_internal *ctx; + struct wd_comp_msg *msg; + int tag, ret; + __u32 idx; + + ret = wd_comp_check_params(sess, req, CTX_MODE_ASYNC); + if (unlikely(ret)) + return ret; + + if (unlikely(!req->src_len)) { + WD_ERR("invalid: req src_len is 0!\n"); + return -WD_EINVAL; + } + + idx = wd_comp_setting.sched.pick_next_ctx(h_sched_ctx, + sess->sched_key, + CTX_MODE_ASYNC); + ret = wd_check_ctx(config, CTX_MODE_ASYNC, idx); + if (unlikely(ret)) + return ret; + + wd_dfx_msg_cnt(config->msg_cnt, WD_CTX_CNT_NUM, idx); + ctx = config->ctxs + idx; + + tag = wd_get_msg_from_pool(&wd_comp_setting.pool, idx, (void **)&msg); + if (unlikely(tag < 0)) { + WD_ERR("failed to get msg from pool!\n"); + return -WD_EBUSY; + } + fill_comp_msg(sess, msg, req); + msg->tag = tag; + msg->stream_mode = WD_COMP_STATELESS; + + ret = wd_comp_setting.driver->comp_send(ctx->ctx, msg); + if (unlikely(ret < 0)) { + WD_ERR("wd comp send error, ret = %d!\n", ret); + goto fail_with_msg; + } + + ret = wd_add_task_to_async_queue(&wd_comp_env_config, idx); + if (unlikely(ret)) + goto fail_with_msg; + + return 0; + +fail_with_msg: + wd_put_msg_to_pool(&wd_comp_setting.pool, idx, msg->tag); + + return ret; +} + +int wd_comp_poll(__u32 expt, __u32 *count) +{ + handle_t h_sched_ctx; + struct wd_sched *sched; + + h_sched_ctx = wd_comp_setting.sched.h_sched_ctx; + sched = &wd_comp_setting.sched; + + return sched->poll_policy(h_sched_ctx, expt, count); +} + +static const struct wd_config_variable table[] = { + { .name = "WD_COMP_CTX_NUM", + .def_val = "sync-comp:1@0,sync-decomp:1@0,async-comp:1@0,async-decomp:1@0", + .parse_fn = wd_parse_ctx_num + }, + { .name = "WD_COMP_ASYNC_POLL_EN", + .def_val = "0", + .parse_fn = wd_parse_async_poll_en + }, + { .name = "WD_COMP_ASYNC_POLL_NUM", + .def_val = "1@0", + .parse_fn = wd_parse_async_poll_num + } +}; + +static const struct wd_alg_ops wd_comp_ops = { + .alg_name = "zlib", + .op_type_num = 2, + .alg_init = wd_comp_init, + .alg_uninit = wd_comp_uninit, + .alg_poll_ctx = wd_comp_poll_ctx +}; + +int wd_comp_env_init(struct wd_sched *sched) +{ + wd_comp_env_config.sched = sched; + + return wd_alg_env_init(&wd_comp_env_config, table, + &wd_comp_ops, ARRAY_SIZE(table), NULL); +} + +void wd_comp_env_uninit(void) +{ + return wd_alg_env_uninit(&wd_comp_env_config, &wd_comp_ops); +} + +int wd_comp_ctx_num_init(__u32 node, __u32 type, __u32 num, __u8 mode) +{ + struct wd_ctx_attr ctx_attr; + int ret; + + if (type >= WD_DIR_MAX) { + WD_ERR("invalid: op_type is %u!\n", type); + return -WD_EINVAL; + } + + ret = wd_set_ctx_attr(&ctx_attr, node, type, mode, num); + if (ret) + return ret; + + return wd_alg_env_init(&wd_comp_env_config, table, + &wd_comp_ops, ARRAY_SIZE(table), &ctx_attr); +} + +void wd_comp_ctx_num_uninit(void) +{ + return wd_alg_env_uninit(&wd_comp_env_config, &wd_comp_ops); +} + +int wd_comp_get_env_param(__u32 node, __u32 type, __u32 mode, + __u32 *num, __u8 *is_enable) +{ + struct wd_ctx_attr ctx_attr; + int ret; + + if (type >= WD_DIR_MAX) { + WD_ERR("invalid: op_type is %u!\n", type); + return -WD_EINVAL; + } + + ret = wd_set_ctx_attr(&ctx_attr, node, type, mode, 0); + if (ret) + return ret; + + return wd_alg_get_env_param(&wd_comp_env_config, + ctx_attr, num, is_enable); +} diff --git a/uadk/wd_dh.c b/uadk/wd_dh.c new file mode 100644 index 0000000..0bf770d --- /dev/null +++ b/uadk/wd_dh.c @@ -0,0 +1,548 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. + * Copyright 2020-2021 Linaro ltd. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "include/drv/wd_dh_drv.h" +#include "wd_util.h" +#include "wd_dh.h" + +#define WD_POOL_MAX_ENTRIES 1024 +#define DH_MAX_KEY_SIZE 512 +#define WD_DH_G2 2 + +static __thread __u64 balance; + +struct wd_dh_sess { + __u32 alg_type; + __u32 key_size; + struct wd_dtb g; + struct wd_dh_sess_setup setup; + void *sched_key; +}; + +static struct wd_dh_setting { + struct wd_ctx_config_internal config; + struct wd_sched sched; + void *sched_ctx; + const struct wd_dh_driver *driver; + void *priv; + void *dlhandle; + struct wd_async_msg_pool pool; +} wd_dh_setting; + +struct wd_env_config wd_dh_env_config; + +#ifdef WD_STATIC_DRV +static void wd_dh_set_static_drv(void) +{ + wd_dh_setting.driver = wd_dh_get_driver(); + if (!wd_dh_setting.driver) + WD_ERR("failed to get dh driver!\n"); +} +#else +static void __attribute__((constructor)) wd_dh_open_driver(void) +{ + wd_dh_setting.dlhandle = dlopen("libhisi_hpre.so", RTLD_NOW); + if (!wd_dh_setting.dlhandle) + WD_ERR("failed to open libhisi_hpre.so!\n"); +} + +static void __attribute__((destructor)) wd_dh_close_driver(void) +{ + if (wd_dh_setting.dlhandle) + dlclose(wd_dh_setting.dlhandle); +} +#endif + +void wd_dh_set_driver(struct wd_dh_driver *drv) +{ + if (!drv) { + WD_ERR("invalid: dh drv is NULL!\n"); + return; + } + + wd_dh_setting.driver = drv; +} + +int wd_dh_init(struct wd_ctx_config *config, struct wd_sched *sched) +{ + void *priv; + int ret; + + ret = wd_init_param_check(config, sched); + if (ret) + return ret; + + ret = wd_set_epoll_en("WD_DH_EPOLL_EN", + &wd_dh_setting.config.epoll_en); + if (ret < 0) + return ret; + + ret = wd_init_ctx_config(&wd_dh_setting.config, config); + if (ret) + return ret; + + ret = wd_init_sched(&wd_dh_setting.sched, sched); + if (ret) + goto out; + +#ifdef WD_STATIC_DRV + wd_dh_set_static_drv(); +#endif + + /* initialize async request pool */ + ret = wd_init_async_request_pool(&wd_dh_setting.pool, + config->ctx_num, WD_POOL_MAX_ENTRIES, + sizeof(struct wd_dh_msg)); + if (ret) + goto out_sched; + + /* initialize ctx related resources in specific driver */ + priv = calloc(1, wd_dh_setting.driver->drv_ctx_size); + if (!priv) { + ret = -WD_ENOMEM; + goto out_priv; + } + + wd_dh_setting.priv = priv; + ret = wd_dh_setting.driver->init(&wd_dh_setting.config, priv, + wd_dh_setting.driver->alg_name); + if (ret < 0) { + WD_ERR("failed to init dh driver, ret= %d!\n", ret); + goto out_init; + } + + return 0; + +out_init: + free(priv); + wd_dh_setting.priv = NULL; +out_priv: + wd_uninit_async_request_pool(&wd_dh_setting.pool); +out_sched: + wd_clear_sched(&wd_dh_setting.sched); +out: + wd_clear_ctx_config(&wd_dh_setting.config); + + return ret; +} + +void wd_dh_uninit(void) +{ + if (!wd_dh_setting.priv) { + WD_ERR("invalid: repeat uninit dh!\n"); + return; + } + + /* driver uninit */ + wd_dh_setting.driver->exit(wd_dh_setting.priv); + free(wd_dh_setting.priv); + wd_dh_setting.priv = NULL; + + /* uninit async request pool */ + wd_uninit_async_request_pool(&wd_dh_setting.pool); + + /* unset config, sched, driver */ + wd_clear_sched(&wd_dh_setting.sched); + wd_clear_ctx_config(&wd_dh_setting.config); +} + +static int fill_dh_msg(struct wd_dh_msg *msg, struct wd_dh_req *req, + struct wd_dh_sess *sess) +{ + memcpy(&msg->req, req, sizeof(*req)); + msg->result = WD_EINVAL; + msg->key_bytes = sess->key_size; + + if (unlikely(req->pri_bytes < sess->key_size)) { + WD_ERR("invalid: req pri bytes %hu is error!\n", req->pri_bytes); + return -WD_EINVAL; + } + + if (req->op_type == WD_DH_PHASE1) { + msg->g = (__u8 *)sess->g.data; + msg->gbytes = sess->g.dsize; + } else if (req->op_type == WD_DH_PHASE2) { + msg->g = (__u8 *)req->pv; + msg->gbytes = req->pvbytes; + } else { + WD_ERR("invalid: op_type %hhu is error!\n", req->op_type); + return -WD_EINVAL; + } + + if (!msg->g) { + WD_ERR("invalid: request dh g is NULL!\n"); + return -WD_EINVAL; + } + + return 0; +} + +int wd_do_dh_sync(handle_t sess, struct wd_dh_req *req) +{ + struct wd_ctx_config_internal *config = &wd_dh_setting.config; + handle_t h_sched_ctx = wd_dh_setting.sched.h_sched_ctx; + struct wd_dh_sess *sess_t = (struct wd_dh_sess *)sess; + struct wd_msg_handle msg_handle; + struct wd_ctx_internal *ctx; + struct wd_dh_msg msg; + __u32 idx; + int ret; + + if (unlikely(!sess || !req)) { + WD_ERR("invalid: input param NULL!\n"); + return -WD_EINVAL; + } + + idx = wd_dh_setting.sched.pick_next_ctx(h_sched_ctx, + sess_t->sched_key, + CTX_MODE_SYNC); + ret = wd_check_ctx(config, CTX_MODE_SYNC, idx); + if (ret) + return ret; + + wd_dfx_msg_cnt(config->msg_cnt, WD_CTX_CNT_NUM, idx); + ctx = config->ctxs + idx; + + memset(&msg, 0, sizeof(struct wd_dh_msg)); + ret = fill_dh_msg(&msg, req, sess_t); + if (unlikely(ret)) + return ret; + + msg_handle.send = wd_dh_setting.driver->send; + msg_handle.recv = wd_dh_setting.driver->recv; + + pthread_spin_lock(&ctx->lock); + ret = wd_handle_msg_sync(&msg_handle, ctx->ctx, &msg, &balance, + wd_dh_setting.config.epoll_en); + pthread_spin_unlock(&ctx->lock); + if (unlikely(ret)) + return ret; + + req->pri_bytes = msg.req.pri_bytes; + req->status = msg.result; + + return GET_NEGATIVE(msg.result); +} + +int wd_do_dh_async(handle_t sess, struct wd_dh_req *req) +{ + struct wd_ctx_config_internal *config = &wd_dh_setting.config; + handle_t h_sched_ctx = wd_dh_setting.sched.h_sched_ctx; + struct wd_dh_sess *sess_t = (struct wd_dh_sess *)sess; + struct wd_dh_msg *msg = NULL; + struct wd_ctx_internal *ctx; + int ret, mid; + __u32 idx; + + if (unlikely(!req || !sess || !req->cb)) { + WD_ERR("invalid: input param NULL!\n"); + return -WD_EINVAL; + } + + idx = wd_dh_setting.sched.pick_next_ctx(h_sched_ctx, + sess_t->sched_key, + CTX_MODE_ASYNC); + ret = wd_check_ctx(config, CTX_MODE_ASYNC, idx); + if (ret) + return ret; + + wd_dfx_msg_cnt(config->msg_cnt, WD_CTX_CNT_NUM, idx); + ctx = config->ctxs + idx; + + mid = wd_get_msg_from_pool(&wd_dh_setting.pool, idx, (void **)&msg); + if (mid < 0) + return -WD_EBUSY; + + ret = fill_dh_msg(msg, req, (struct wd_dh_sess *)sess); + if (ret) + goto fail_with_msg; + msg->tag = mid; + + ret = wd_dh_setting.driver->send(ctx->ctx, msg); + if (unlikely(ret)) { + if (ret != -WD_EBUSY) + WD_ERR("failed to send dh BD, hw is err!\n"); + + goto fail_with_msg; + } + + ret = wd_add_task_to_async_queue(&wd_dh_env_config, idx); + if (ret) + goto fail_with_msg; + + return 0; + +fail_with_msg: + wd_put_msg_to_pool(&wd_dh_setting.pool, idx, mid); + + return ret; +} + +struct wd_dh_msg *wd_dh_get_msg(__u32 idx, __u32 tag) +{ + return wd_find_msg_in_pool(&wd_dh_setting.pool, idx, tag); +} + +int wd_dh_poll_ctx(__u32 idx, __u32 expt, __u32 *count) +{ + struct wd_ctx_config_internal *config = &wd_dh_setting.config; + struct wd_ctx_internal *ctx; + struct wd_dh_msg rcv_msg; + struct wd_dh_req *req; + struct wd_dh_msg *msg; + __u32 rcv_cnt = 0; + __u32 tmp = expt; + int ret; + + if (unlikely(!count)) { + WD_ERR("invalid: count is NULL!\n"); + return -WD_EINVAL; + } + + *count = 0; + + ret = wd_check_ctx(config, CTX_MODE_ASYNC, idx); + if (ret) + return ret; + + ctx = config->ctxs + idx; + + do { + ret = wd_dh_setting.driver->recv(ctx->ctx, &rcv_msg); + if (ret == -WD_EAGAIN) { + return ret; + } else if (unlikely(ret)) { + WD_ERR("failed to async recv, ret = %d!\n", ret); + *count = rcv_cnt; + wd_put_msg_to_pool(&wd_dh_setting.pool, idx, + rcv_msg.tag); + return ret; + } + rcv_cnt++; + msg = wd_find_msg_in_pool(&wd_dh_setting.pool, + idx, rcv_msg.tag); + if (!msg) { + WD_ERR("failed to find msg!\n"); + return -WD_EINVAL; + } + + msg->req.pri_bytes = rcv_msg.req.pri_bytes; + msg->req.status = rcv_msg.result; + req = &msg->req; + req->cb(req); + wd_put_msg_to_pool(&wd_dh_setting.pool, idx, rcv_msg.tag); + *count = rcv_cnt; + } while (--tmp); + + return ret; +} + +int wd_dh_poll(__u32 expt, __u32 *count) +{ + handle_t h_sched_ctx = wd_dh_setting.sched.h_sched_ctx; + + if (unlikely(!count)) { + WD_ERR("invalid: dh poll count is NULL!\n"); + return -WD_EINVAL; + } + + return wd_dh_setting.sched.poll_policy(h_sched_ctx, expt, count); +} + +int wd_dh_get_mode(handle_t sess, __u8 *alg_mode) +{ + if (!sess || !alg_mode) { + WD_ERR("invalid: dh get mode, param NULL!\n"); + return -WD_EINVAL; + } + + *alg_mode = ((struct wd_dh_sess *)sess)->setup.is_g2; + + return 0; +} + +__u32 wd_dh_key_bits(handle_t sess) +{ + if (!sess) { + WD_ERR("invalid: get dh key bits, sess NULL!\n"); + return 0; + } + + return ((struct wd_dh_sess *)sess)->setup.key_bits; +} + +int wd_dh_set_g(handle_t sess, struct wd_dtb *g) +{ + struct wd_dh_sess *sess_t = (struct wd_dh_sess *)sess; + + if (!sess_t || !g) { + WD_ERR("invalid: dh set g, param NULL!\n"); + return -WD_EINVAL; + } + + if (g->dsize && + g->bsize <= sess_t->g.bsize && + g->dsize <= sess_t->g.bsize) { + memset(sess_t->g.data, 0, g->bsize); + memcpy(sess_t->g.data, g->data, g->dsize); + sess_t->g.dsize = g->dsize; + if (*g->data != WD_DH_G2 && sess_t->setup.is_g2) + return -WD_EINVAL; + return WD_SUCCESS; + } + + return -WD_EINVAL; +} + +void wd_dh_get_g(handle_t sess, struct wd_dtb **g) +{ + if (!sess || !g) { + WD_ERR("invalid: dh get g, param NULL!\n"); + return; + } + + *g = &((struct wd_dh_sess *)sess)->g; +} + +handle_t wd_dh_alloc_sess(struct wd_dh_sess_setup *setup) +{ + struct wd_dh_sess *sess; + + if (!setup) { + WD_ERR("invalid: alloc dh sess setup NULL!\n"); + return (handle_t)0; + } + + /* key width check */ + if (setup->key_bits != 768 && + setup->key_bits != 1024 && + setup->key_bits != 1536 && + setup->key_bits != 2048 && + setup->key_bits != 3072 && + setup->key_bits != 4096) { + WD_ERR("invalid: alloc dh sess key_bit %u is err!\n", setup->key_bits); + return (handle_t)0; + } + + sess = malloc(sizeof(struct wd_dh_sess)); + if (!sess) + return (handle_t)0; + + memset(sess, 0, sizeof(struct wd_dh_sess)); + memcpy(&sess->setup, setup, sizeof(*setup)); + sess->key_size = setup->key_bits >> BYTE_BITS_SHIFT; + + sess->g.data = malloc(sess->key_size); + if (!sess->g.data) + goto sess_err; + + sess->g.bsize = sess->key_size; + /* Some simple scheduler don't need scheduling parameters */ + sess->sched_key = (void *)wd_dh_setting.sched.sched_init( + wd_dh_setting.sched.h_sched_ctx, setup->sched_param); + if (WD_IS_ERR(sess->sched_key)) { + WD_ERR("failed to init session schedule key!\n"); + goto sched_err; + } + + return (handle_t)sess; + +sched_err: + free(sess->g.data); +sess_err: + free(sess); + return (handle_t)0; +} + +void wd_dh_free_sess(handle_t sess) +{ + struct wd_dh_sess *sess_t = (struct wd_dh_sess *)sess; + + if (!sess_t) { + WD_ERR("invalid: free dh sess param NULL!\n"); + return; + } + + if (sess_t->g.data) + free(sess_t->g.data); + + if (sess_t->sched_key) + free(sess_t->sched_key); + free(sess_t); +} + +static const struct wd_config_variable table[] = { + { .name = "WD_DH_CTX_NUM", + .def_val = "sync:2@0,async:2@0", + .parse_fn = wd_parse_ctx_num + }, + { .name = "WD_DH_ASYNC_POLL_EN", + .def_val = "0", + .parse_fn = wd_parse_async_poll_en + } +}; + +static const struct wd_alg_ops wd_dh_ops = { + .alg_name = "dh", + .op_type_num = 1, + .alg_init = wd_dh_init, + .alg_uninit = wd_dh_uninit, + .alg_poll_ctx = wd_dh_poll_ctx +}; + +int wd_dh_env_init(struct wd_sched *sched) +{ + wd_dh_env_config.sched = sched; + + return wd_alg_env_init(&wd_dh_env_config, table, + &wd_dh_ops, ARRAY_SIZE(table), NULL); +} + +void wd_dh_env_uninit(void) +{ + return wd_alg_env_uninit(&wd_dh_env_config, &wd_dh_ops); +} + +int wd_dh_ctx_num_init(__u32 node, __u32 type, __u32 num, __u8 mode) +{ + struct wd_ctx_attr ctx_attr; + int ret; + + ret = wd_set_ctx_attr(&ctx_attr, node, CTX_TYPE_INVALID, mode, num); + if (ret) + return ret; + + return wd_alg_env_init(&wd_dh_env_config, table, + &wd_dh_ops, ARRAY_SIZE(table), &ctx_attr); +} + +void wd_dh_ctx_num_uninit(void) +{ + return wd_alg_env_uninit(&wd_dh_env_config, &wd_dh_ops); +} + +int wd_dh_get_env_param(__u32 node, __u32 type, __u32 mode, + __u32 *num, __u8 *is_enable) +{ + struct wd_ctx_attr ctx_attr; + int ret; + + ret = wd_set_ctx_attr(&ctx_attr, node, CTX_TYPE_INVALID, mode, 0); + if (ret) + return ret; + + return wd_alg_get_env_param(&wd_dh_env_config, + ctx_attr, num, is_enable); +} diff --git a/uadk/wd_digest.c b/uadk/wd_digest.c new file mode 100644 index 0000000..f56be0c --- /dev/null +++ b/uadk/wd_digest.c @@ -0,0 +1,633 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. + * Copyright 2020-2021 Linaro ltd. + */ + +#include +#include +#include "wd_util.h" +#include "include/drv/wd_digest_drv.h" +#include "wd_digest.h" + +#define XTS_MODE_KEY_DIVISOR 2 +#define SM4_KEY_SIZE 16 +#define DES_KEY_SIZE 8 +#define DES3_3KEY_SIZE (3 * DES_KEY_SIZE) +#define GMAC_IV_LEN 16 +#define AES_KEYSIZE_128 16 +#define AES_KEYSIZE_192 24 +#define AES_KEYSIZE_256 32 + +#define WD_POOL_MAX_ENTRIES 1024 +#define DES_WEAK_KEY_NUM 4 + +static int g_digest_mac_len[WD_DIGEST_TYPE_MAX] = { + WD_DIGEST_SM3_LEN, WD_DIGEST_MD5_LEN, WD_DIGEST_SHA1_LEN, + WD_DIGEST_SHA256_LEN, WD_DIGEST_SHA224_LEN, + WD_DIGEST_SHA384_LEN, WD_DIGEST_SHA512_LEN, + WD_DIGEST_SHA512_224_LEN, WD_DIGEST_SHA512_256_LEN, + WD_DIGEST_AES_XCBC_MAC_96_LEN, WD_DIGEST_AES_XCBC_PRF_128_LEN, + WD_DIGEST_AES_CMAC_LEN, WD_DIGEST_AES_GMAC_LEN +}; + +static int g_digest_mac_full_len[WD_DIGEST_TYPE_MAX] = { + WD_DIGEST_SM3_FULL_LEN, WD_DIGEST_MD5_LEN, WD_DIGEST_SHA1_FULL_LEN, + WD_DIGEST_SHA256_FULL_LEN, WD_DIGEST_SHA224_FULL_LEN, + WD_DIGEST_SHA384_FULL_LEN, WD_DIGEST_SHA512_FULL_LEN, + WD_DIGEST_SHA512_224_FULL_LEN, WD_DIGEST_SHA512_256_FULL_LEN +}; + +struct wd_digest_setting { + struct wd_ctx_config_internal config; + struct wd_sched sched; + struct wd_digest_driver *driver; + struct wd_async_msg_pool pool; + void *sched_ctx; + void *priv; + void *dlhandle; +} wd_digest_setting; + +struct wd_digest_sess { + char *alg_name; + enum wd_digest_type alg; + enum wd_digest_mode mode; + void *priv; + unsigned char key[MAX_HMAC_KEY_SIZE]; + __u32 key_bytes; + void *sched_key; + /* + * Notify the BD state, zero is frist BD, non-zero + * is middle or final BD. + */ + int bd_state; + /* Total of data for stream mode */ + __u64 long_data_len; +}; + +struct wd_env_config wd_digest_env_config; + +#ifdef WD_STATIC_DRV +static void wd_digest_set_static_drv(void) +{ + wd_digest_setting.driver = wd_digest_get_driver(); + if (!wd_digest_setting.driver) + WD_ERR("failed to get driver!\n"); +} +#else +static void __attribute__((constructor)) wd_digest_open_driver(void) +{ + /* Fix me: vendor driver should be put in /usr/lib/wd/ */ + wd_digest_setting.dlhandle = dlopen("libhisi_sec.so", RTLD_NOW); + if (!wd_digest_setting.dlhandle) + WD_ERR("failed to open libhisi_sec.so!\n"); +} + +static void __attribute__((destructor)) wd_digest_close_driver(void) +{ + if (wd_digest_setting.dlhandle) + dlclose(wd_digest_setting.dlhandle); +} +#endif + +void wd_digest_set_driver(struct wd_digest_driver *drv) +{ + wd_digest_setting.driver = drv; +} + +static int aes_key_len_check(__u32 length) +{ + switch (length) { + case AES_KEYSIZE_128: + case AES_KEYSIZE_192: + case AES_KEYSIZE_256: + return 0; + default: + return -WD_EINVAL; + } +} + +int wd_digest_set_key(handle_t h_sess, const __u8 *key, __u32 key_len) +{ + struct wd_digest_sess *sess = (struct wd_digest_sess *)h_sess; + int ret; + + if (!key || !sess) { + WD_ERR("failed to check key param!\n"); + return -WD_EINVAL; + } + + if ((sess->alg <= WD_DIGEST_SHA224 && key_len > + MAX_HMAC_KEY_SIZE >> 1) || key_len == 0 || + key_len > MAX_HMAC_KEY_SIZE) { + WD_ERR("failed to check digest key length, size = %u\n", + key_len); + return -WD_EINVAL; + } + + if (sess->alg == WD_DIGEST_AES_GMAC) { + ret = aes_key_len_check(key_len); + if (ret) { + WD_ERR("failed to check aes-gmac key length, size = %u\n", + key_len); + return ret; + } + } + + sess->key_bytes = key_len; + memcpy(sess->key, key, key_len); + + return 0; +} + +handle_t wd_digest_alloc_sess(struct wd_digest_sess_setup *setup) +{ + struct wd_digest_sess *sess = NULL; + + if (unlikely(!setup)) { + WD_ERR("failed to check alloc sess param!\n"); + return (handle_t)0; + } + + sess = malloc(sizeof(struct wd_digest_sess)); + if (!sess) + return (handle_t)0; + memset(sess, 0, sizeof(struct wd_digest_sess)); + + sess->alg = setup->alg; + sess->mode = setup->mode; + /* Some simple scheduler don't need scheduling parameters */ + sess->sched_key = (void *)wd_digest_setting.sched.sched_init( + wd_digest_setting.sched.h_sched_ctx, setup->sched_param); + if (WD_IS_ERR(sess->sched_key)) { + WD_ERR("failed to init session schedule key!\n"); + free(sess); + return (handle_t)0; + } + + return (handle_t)sess; +} + +void wd_digest_free_sess(handle_t h_sess) +{ + struct wd_digest_sess *sess = (struct wd_digest_sess *)h_sess; + + if (unlikely(!sess)) { + WD_ERR("failed to check free sess param!\n"); + return; + } + + wd_memset_zero(sess->key, MAX_HMAC_KEY_SIZE); + if (sess->sched_key) + free(sess->sched_key); + free(sess); +} + +int wd_digest_init(struct wd_ctx_config *config, struct wd_sched *sched) +{ + void *priv; + int ret; + + ret = wd_init_param_check(config, sched); + if (ret) + return ret; + + ret = wd_set_epoll_en("WD_DIGEST_EPOLL_EN", + &wd_digest_setting.config.epoll_en); + if (ret < 0) + return ret; + + ret = wd_init_ctx_config(&wd_digest_setting.config, config); + if (ret < 0) + return ret; + + ret = wd_init_sched(&wd_digest_setting.sched, sched); + if (ret < 0) + goto out; + + /* set driver */ +#ifdef WD_STATIC_DRV + wd_digest_set_static_drv(); +#endif + + /* allocate async pool for every ctx */ + ret = wd_init_async_request_pool(&wd_digest_setting.pool, + config->ctx_num, WD_POOL_MAX_ENTRIES, + sizeof(struct wd_digest_msg)); + if (ret < 0) + goto out_sched; + + /* init ctx related resources in specific driver */ + priv = calloc(1, wd_digest_setting.driver->drv_ctx_size); + if (!priv) { + ret = -WD_ENOMEM; + goto out_priv; + } + wd_digest_setting.priv = priv; + + ret = wd_digest_setting.driver->init(&wd_digest_setting.config, priv); + if (ret < 0) { + WD_ERR("failed to init digest dirver!\n"); + goto out_init; + } + + return 0; + +out_init: + free(priv); + wd_digest_setting.priv = NULL; +out_priv: + wd_uninit_async_request_pool(&wd_digest_setting.pool); +out_sched: + wd_clear_sched(&wd_digest_setting.sched); +out: + wd_clear_ctx_config(&wd_digest_setting.config); + return ret; +} + +void wd_digest_uninit(void) +{ + void *priv = wd_digest_setting.priv; + + if (!priv) + return; + + wd_digest_setting.driver->exit(priv); + wd_digest_setting.priv = NULL; + free(priv); + + wd_uninit_async_request_pool(&wd_digest_setting.pool); + + wd_clear_sched(&wd_digest_setting.sched); + wd_clear_ctx_config(&wd_digest_setting.config); +} + +static int wd_aes_hmac_length_check(struct wd_digest_sess *sess, + struct wd_digest_req *req) +{ + switch (sess->alg) { + case WD_DIGEST_AES_XCBC_MAC_96: + case WD_DIGEST_AES_XCBC_PRF_128: + case WD_DIGEST_AES_CMAC: + if (!req->in_bytes) { + WD_ERR("failed to check 0 packet length, alg = %d\n", + sess->alg); + return -WD_EINVAL; + } + break; + default: + break; + } + + return 0; +} + +static int wd_mac_length_check(struct wd_digest_sess *sess, + struct wd_digest_req *req) +{ + if (unlikely(req->out_bytes == 0)) { + WD_ERR("invalid: digest alg:%d mac length is 0.\n", sess->alg); + return -WD_EINVAL; + } + + if (unlikely(!req->has_next && + req->out_bytes > g_digest_mac_len[sess->alg])) { + WD_ERR("invalid: digest mac length, alg = %d, out_bytes = %u\n", + sess->alg, req->out_bytes); + return -WD_EINVAL; + } + + /* User need to input full mac buffer in first and middle hash */ + if (unlikely(req->has_next && + req->out_bytes != g_digest_mac_full_len[sess->alg])) { + WD_ERR("invalid: digest mac full length is error, alg = %d, out_bytes = %u\n", + sess->alg, req->out_bytes); + return -WD_EINVAL; + } + + return 0; +} + +static int wd_digest_param_check(struct wd_digest_sess *sess, + struct wd_digest_req *req) +{ + int ret; + + if (unlikely(!sess || !req)) { + WD_ERR("invalid: digest input sess or req is NULL!\n"); + return -WD_EINVAL; + } + + if (unlikely(req->out_buf_bytes < req->out_bytes)) { + WD_ERR("failed to check digest out buffer length, size = %u\n", + req->out_buf_bytes); + return -WD_EINVAL; + } + + if (unlikely(sess->alg >= WD_DIGEST_TYPE_MAX)) { + WD_ERR("invalid: check digest type, alg = %d\n", sess->alg); + return -WD_EINVAL; + } + + ret = wd_mac_length_check(sess, req); + if (ret) + return ret; + + if (unlikely(sess->alg == WD_DIGEST_AES_GMAC && + req->iv_bytes != GMAC_IV_LEN)) { + WD_ERR("failed to check digest aes_gmac iv length, iv_bytes = %u\n", + req->iv_bytes); + return -WD_EINVAL; + } + + if (req->data_fmt == WD_SGL_BUF) { + ret = wd_check_datalist(req->list_in, req->in_bytes); + if (unlikely(ret)) { + WD_ERR("failed to check the src datalist, size = %u\n", + req->in_bytes); + return -WD_EINVAL; + } + } + + return wd_aes_hmac_length_check(sess, req); +} + +static void fill_request_msg(struct wd_digest_msg *msg, + struct wd_digest_req *req, + struct wd_digest_sess *sess) +{ + memcpy(&msg->req, req, sizeof(struct wd_digest_req)); + + msg->alg_type = WD_DIGEST; + msg->alg = sess->alg; + msg->mode = sess->mode; + msg->key = sess->key; + msg->key_bytes = sess->key_bytes; + msg->iv = req->iv; + msg->in = req->in; + msg->in_bytes = req->in_bytes; + msg->out = req->out; + msg->out_bytes = req->out_bytes; + msg->data_fmt = req->data_fmt; + msg->has_next = req->has_next; + sess->long_data_len += req->in_bytes; + msg->long_data_len = sess->long_data_len; + + /* To store the stream BD state, iv_bytes also means BD state */ + msg->iv_bytes = sess->bd_state; + if (req->has_next == 0) { + sess->long_data_len = 0; + sess->bd_state = 0; + } +} + +static int send_recv_sync(struct wd_ctx_internal *ctx, struct wd_digest_sess *dsess, + struct wd_digest_msg *msg) +{ + struct wd_msg_handle msg_handle; + int ret; + + msg_handle.send = wd_digest_setting.driver->digest_send; + msg_handle.recv = wd_digest_setting.driver->digest_recv; + + pthread_spin_lock(&ctx->lock); + ret = wd_handle_msg_sync(&msg_handle, ctx->ctx, msg, + NULL, wd_digest_setting.config.epoll_en); + if (unlikely(ret)) + goto out; + + /* + * non-zero is final BD or middle BD as stream mode. + */ + dsess->bd_state = msg->has_next; + +out: + pthread_spin_unlock(&ctx->lock); + return ret; +} + +int wd_do_digest_sync(handle_t h_sess, struct wd_digest_req *req) +{ + struct wd_ctx_config_internal *config = &wd_digest_setting.config; + struct wd_digest_sess *dsess = (struct wd_digest_sess *)h_sess; + struct wd_ctx_internal *ctx; + struct wd_digest_msg msg; + __u32 idx; + int ret; + + ret = wd_digest_param_check(dsess, req); + if (unlikely(ret)) + return -WD_EINVAL; + + memset(&msg, 0, sizeof(struct wd_digest_msg)); + fill_request_msg(&msg, req, dsess); + req->state = 0; + + idx = wd_digest_setting.sched.pick_next_ctx( + wd_digest_setting.sched.h_sched_ctx, + dsess->sched_key, CTX_MODE_SYNC); + ret = wd_check_ctx(config, CTX_MODE_SYNC, idx); + if (unlikely(ret)) + return ret; + + wd_dfx_msg_cnt(config->msg_cnt, WD_CTX_CNT_NUM, idx); + ctx = config->ctxs + idx; + ret = send_recv_sync(ctx, dsess, &msg); + req->state = msg.result; + + return ret; +} + +int wd_do_digest_async(handle_t h_sess, struct wd_digest_req *req) +{ + struct wd_ctx_config_internal *config = &wd_digest_setting.config; + struct wd_digest_sess *dsess = (struct wd_digest_sess *)h_sess; + struct wd_ctx_internal *ctx; + struct wd_digest_msg *msg; + int msg_id, ret; + __u32 idx; + + ret = wd_digest_param_check(dsess, req); + if (unlikely(ret)) + return -WD_EINVAL; + + if (unlikely(!req->cb)) { + WD_ERR("invalid: digest input req cb is NULL!\n"); + return -WD_EINVAL; + } + + idx = wd_digest_setting.sched.pick_next_ctx( + wd_digest_setting.sched.h_sched_ctx, + dsess->sched_key, CTX_MODE_ASYNC); + ret = wd_check_ctx(config, CTX_MODE_ASYNC, idx); + if (ret) + return ret; + + wd_dfx_msg_cnt(config->msg_cnt, WD_CTX_CNT_NUM, idx); + ctx = config->ctxs + idx; + + msg_id = wd_get_msg_from_pool(&wd_digest_setting.pool, idx, + (void **)&msg); + if (unlikely(msg_id < 0)) { + WD_ERR("busy, failed to get msg from pool!\n"); + return -WD_EBUSY; + } + + fill_request_msg(msg, req, dsess); + msg->tag = msg_id; + + ret = wd_digest_setting.driver->digest_send(ctx->ctx, msg); + if (unlikely(ret < 0)) { + if (ret != -WD_EBUSY) + WD_ERR("failed to send BD, hw is err!\n"); + + goto fail_with_msg; + } + + ret = wd_add_task_to_async_queue(&wd_digest_env_config, idx); + if (ret) + goto fail_with_msg; + + return 0; + +fail_with_msg: + wd_put_msg_to_pool(&wd_digest_setting.pool, idx, msg->tag); + return ret; +} + +struct wd_digest_msg *wd_digest_get_msg(__u32 idx, __u32 tag) +{ + return wd_find_msg_in_pool(&wd_digest_setting.pool, idx, tag); +} + +int wd_digest_poll_ctx(__u32 idx, __u32 expt, __u32 *count) +{ + struct wd_ctx_config_internal *config = &wd_digest_setting.config; + struct wd_ctx_internal *ctx; + struct wd_digest_msg recv_msg, *msg; + struct wd_digest_req *req; + __u32 recv_cnt = 0; + __u32 tmp = expt; + int ret; + + if (unlikely(!count)) { + WD_ERR("invalid: digest poll ctx input param is NULL!\n"); + return -WD_EINVAL; + } + + *count = 0; + + ret = wd_check_ctx(config, CTX_MODE_ASYNC, idx); + if (ret) + return ret; + + ctx = config->ctxs + idx; + + do { + ret = wd_digest_setting.driver->digest_recv(ctx->ctx, + &recv_msg); + if (ret == -WD_EAGAIN) { + return ret; + } else if (ret < 0) { + WD_ERR("wd recv err!\n"); + return ret; + } + + recv_cnt++; + + msg = wd_find_msg_in_pool(&wd_digest_setting.pool, idx, + recv_msg.tag); + if (!msg) { + WD_ERR("failed to get msg from pool!\n"); + return -WD_EINVAL; + } + + msg->req.state = recv_msg.result; + req = &msg->req; + if (likely(req)) + req->cb(req); + + wd_put_msg_to_pool(&wd_digest_setting.pool, idx, + recv_msg.tag); + *count = recv_cnt; + } while (--tmp); + + return ret; +} + +int wd_digest_poll(__u32 expt, __u32 *count) +{ + handle_t h_ctx = wd_digest_setting.sched.h_sched_ctx; + struct wd_sched *sched = &wd_digest_setting.sched; + + if (unlikely(!count)) { + WD_ERR("invalid: digest poll input param is NULL!\n"); + return -WD_EINVAL; + } + + return sched->poll_policy(h_ctx, expt, count); +} + +static const struct wd_config_variable table[] = { + { .name = "WD_DIGEST_CTX_NUM", + .def_val = "sync:2@0,async:2@0", + .parse_fn = wd_parse_ctx_num + }, + { .name = "WD_DIGEST_ASYNC_POLL_EN", + .def_val = "0", + .parse_fn = wd_parse_async_poll_en + } +}; + +static const struct wd_alg_ops wd_digest_ops = { + .alg_name = "digest", + .op_type_num = 1, + .alg_init = wd_digest_init, + .alg_uninit = wd_digest_uninit, + .alg_poll_ctx = wd_digest_poll_ctx +}; + +int wd_digest_env_init(struct wd_sched *sched) +{ + wd_digest_env_config.sched = sched; + + return wd_alg_env_init(&wd_digest_env_config, table, + &wd_digest_ops, ARRAY_SIZE(table), NULL); +} + +void wd_digest_env_uninit(void) +{ + return wd_alg_env_uninit(&wd_digest_env_config, &wd_digest_ops); +} + +int wd_digest_ctx_num_init(__u32 node, __u32 type, __u32 num, __u8 mode) +{ + struct wd_ctx_attr ctx_attr; + int ret; + + ret = wd_set_ctx_attr(&ctx_attr, node, CTX_TYPE_INVALID, mode, num); + if (ret) + return ret; + + return wd_alg_env_init(&wd_digest_env_config, table, + &wd_digest_ops, ARRAY_SIZE(table), &ctx_attr); +} + +void wd_digest_ctx_num_uninit(void) +{ + return wd_alg_env_uninit(&wd_digest_env_config, &wd_digest_ops); +} + +int wd_digest_get_env_param(__u32 node, __u32 type, __u32 mode, + __u32 *num, __u8 *is_enable) +{ + struct wd_ctx_attr ctx_attr; + int ret; + + ret = wd_set_ctx_attr(&ctx_attr, node, CTX_TYPE_INVALID, mode, 0); + if (ret) + return ret; + + return wd_alg_get_env_param(&wd_digest_env_config, + ctx_attr, num, is_enable); +} diff --git a/uadk/wd_ecc.c b/uadk/wd_ecc.c new file mode 100644 index 0000000..2266b1d --- /dev/null +++ b/uadk/wd_ecc.c @@ -0,0 +1,2254 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. + * Copyright 2020-2021 Linaro ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "wd_util.h" +#include "include/drv/wd_ecc_drv.h" +#include "include/wd_ecc_curve.h" +#include "wd_ecc.h" + +#define WD_POOL_MAX_ENTRIES 1024 +#define WD_ECC_CTX_MSG_NUM 64 +#define WD_ECC_MAX_CTX 256 +#define ECC_MAX_HW_BITS 521 +#define ECC_MAX_KEY_SIZE BITS_TO_BYTES(ECC_MAX_HW_BITS) +#define ECC_MAX_IN_NUM 4 +#define ECC_MAX_OUT_NUM 4 +#define CURVE_PARAM_NUM 6 +#define ECC_POINT_NUM 2 +#define MAX_CURVE_SIZE (ECC_MAX_KEY_SIZE * CURVE_PARAM_NUM) +#define MAX_HASH_LENS ECC_MAX_KEY_SIZE +#define SM2_KEY_SIZE 32 +#define GET_NEGATIVE(val) (0 - (val)) +#define ZA_PARAM_NUM 6 + +static __thread __u64 balance; + +struct curve_param_desc { + __u32 type; + __u32 pri_offset; + __u32 pub_offset; +}; + +enum wd_ecc_curve_param_type { + ECC_CURVE_P, + ECC_CURVE_A, + ECC_CURVE_B, + ECC_CURVE_N, + ECC_CURVE_G +}; + +struct wd_ecc_sess { + __u32 key_size; + struct wd_ecc_key key; + struct wd_ecc_sess_setup setup; + void *sched_key; +}; + +struct wd_ecc_curve_list { + __u32 id; + const char *name; + __u32 key_bits; + __u8 data[MAX_CURVE_SIZE]; +}; + +static struct wd_ecc_setting { + struct wd_ctx_config_internal config; + struct wd_sched sched; + void *sched_ctx; + const struct wd_ecc_driver *driver; + void *priv; + void *dlhandle; + struct wd_async_msg_pool pool; +} wd_ecc_setting; + +struct wd_env_config wd_ecc_env_config; + +static const struct wd_ecc_curve_list curve_list[] = { + /* parameter 3 is key width */ + { WD_X25519, "x25519", 256, X25519_256_PARAM }, + { WD_X448, "x448", 448, X448_448_PARAM }, + { WD_SECP128R1, "secp128r1", 128, SECG_P128_R1_PARAM }, + { WD_SECP192K1, "secp192k1", 192, SECG_P192_K1_PARAM }, + { WD_SECP224R1, "secp224R1", 224, SECG_P224_R1_PARAM }, + { WD_SECP256K1, "secp256k1", 256, SECG_P256_K1_PARAM }, + { WD_BRAINPOOLP320R1, "bpP320r1", 320, BRAINPOOL_P320_R1_PARAM }, + { WD_BRAINPOOLP384R1, "bpP384r1", 384, BRAINPOOL_P384_R1_PARAM }, + { WD_SECP384R1, "secp384r1", 384, SECG_P384_R1_PARAM }, + { WD_SECP521R1, "secp521r1", 521, SECG_P521_R1_PARAM }, + { WD_SM2P256, "sm2", 256, SM2_P256_V1_PARAM } +}; + +static const struct curve_param_desc curve_pram_list[] = { + { ECC_CURVE_P, offsetof(struct wd_ecc_prikey, p), offsetof(struct wd_ecc_pubkey, p) }, + { ECC_CURVE_A, offsetof(struct wd_ecc_prikey, a), offsetof(struct wd_ecc_pubkey, a) }, + { ECC_CURVE_B, offsetof(struct wd_ecc_prikey, b), offsetof(struct wd_ecc_pubkey, b) }, + { ECC_CURVE_N, offsetof(struct wd_ecc_prikey, n), offsetof(struct wd_ecc_pubkey, n) }, + { ECC_CURVE_G, offsetof(struct wd_ecc_prikey, g), offsetof(struct wd_ecc_pubkey, g) } +}; + +#ifdef WD_STATIC_DRV +static void wd_ecc_set_static_drv(void) +{ + wd_ecc_setting.driver = wd_ecc_get_driver(); + if (!wd_ecc_setting.driver) + WD_ERR("failed to get ecc driver!\n"); +} +#else +static void __attribute__((constructor)) wd_ecc_open_driver(void) +{ + wd_ecc_setting.dlhandle = dlopen("libhisi_hpre.so", RTLD_NOW); + if (!wd_ecc_setting.dlhandle) + WD_ERR("failed to open libhisi_hpre.so!\n"); +} + +static void __attribute__((destructor)) wd_ecc_close_driver(void) +{ + if (wd_ecc_setting.dlhandle) + dlclose(wd_ecc_setting.dlhandle); +} +#endif + +void wd_ecc_set_driver(struct wd_ecc_driver *drv) +{ + if (!drv) { + WD_ERR("invalid: ecc drv is NULL!\n"); + return; + } + + wd_ecc_setting.driver = drv; +} + +int wd_ecc_init(struct wd_ctx_config *config, struct wd_sched *sched) +{ + void *priv; + int ret; + + ret = wd_init_param_check(config, sched); + if (ret) + return ret; + + ret = wd_set_epoll_en("WD_ECC_EPOLL_EN", + &wd_ecc_setting.config.epoll_en); + if (ret < 0) + return ret; + + ret = wd_init_ctx_config(&wd_ecc_setting.config, config); + if (ret < 0) + return ret; + + ret = wd_init_sched(&wd_ecc_setting.sched, sched); + if (ret < 0) + goto out; + +#ifdef WD_STATIC_DRV + wd_ecc_set_static_drv(); +#endif + + /* fix me: sadly find we allocate async pool for every ctx */ + ret = wd_init_async_request_pool(&wd_ecc_setting.pool, + config->ctx_num, WD_POOL_MAX_ENTRIES, + sizeof(struct wd_ecc_msg)); + if (ret < 0) + goto out_sched; + + /* initialize ctx related resources in specific driver */ + priv = calloc(1, wd_ecc_setting.driver->drv_ctx_size); + if (!priv) { + ret = -WD_ENOMEM; + goto out_priv; + } + + wd_ecc_setting.priv = priv; + ret = wd_ecc_setting.driver->init(&wd_ecc_setting.config, priv, + wd_ecc_setting.driver->alg_name); + if (ret < 0) { + WD_ERR("failed to init ecc driver, ret = %d!\n", ret); + goto out_init; + } + + return 0; + +out_init: + free(priv); + wd_ecc_setting.priv = NULL; +out_priv: + wd_uninit_async_request_pool(&wd_ecc_setting.pool); +out_sched: + wd_clear_sched(&wd_ecc_setting.sched); +out: + wd_clear_ctx_config(&wd_ecc_setting.config); + return ret; +} + +void wd_ecc_uninit(void) +{ + if (!wd_ecc_setting.priv) { + WD_ERR("invalid: repeat uninit ecc!\n"); + return; + } + + /* driver uninit */ + wd_ecc_setting.driver->exit(wd_ecc_setting.priv); + free(wd_ecc_setting.priv); + wd_ecc_setting.priv = NULL; + + /* uninit async request pool */ + wd_uninit_async_request_pool(&wd_ecc_setting.pool); + + /* unset config, sched, driver */ + wd_clear_sched(&wd_ecc_setting.sched); + wd_clear_ctx_config(&wd_ecc_setting.config); +} + +static int trans_to_binpad(char *dst, const char *src, + int b_size, int d_size, const char *p_name) +{ + int i = d_size - 1; + int j; + + if (unlikely(!dst || !src || !b_size || !d_size || b_size < d_size)) { + WD_ERR("invalid: %s trans to hpre bin params err!\n", p_name); + return -WD_EINVAL; + } + + if (dst == src) + return WD_SUCCESS; + + for (j = b_size - 1; j >= 0; j--, i--) { + if (i >= 0) + dst[j] = src[i]; + else + dst[j] = 0; + } + + return WD_SUCCESS; +} + +static __u32 get_key_bsz(__u32 ksz) +{ + __u32 size = 0; + + /* key width */ + if (ksz <= BITS_TO_BYTES(256)) + size = BITS_TO_BYTES(256); + else if (ksz <= BITS_TO_BYTES(384)) + size = BITS_TO_BYTES(384); + else if (ksz <= BITS_TO_BYTES(576)) + size = BITS_TO_BYTES(576); + else + WD_ERR("invalid: get key size %u is error!\n", ksz); + + return size; +} + +static __u32 get_hash_bytes(__u8 type) +{ + __u32 val = 0; + + switch (type) { + case WD_HASH_MD4: + case WD_HASH_MD5: + val = BITS_TO_BYTES(128); /* output width */ + break; + case WD_HASH_SHA1: + val = BITS_TO_BYTES(160); + break; + case WD_HASH_SHA224: + val = BITS_TO_BYTES(224); + break; + case WD_HASH_SHA256: + case WD_HASH_SM3: + val = BITS_TO_BYTES(256); + break; + case WD_HASH_SHA384: + val = BITS_TO_BYTES(384); + break; + case WD_HASH_SHA512: + val = BITS_TO_BYTES(512); + break; + default: + break; + } + + return val; +} + +static void init_dtb_param(void *dtb, char *str, + __u32 dsz, __u32 bsz, __u32 num) +{ + struct wd_dtb *tmp = dtb; + char *start = str; + int i = 0; + + while (i++ < num) { + tmp->data = start; + tmp->dsize = dsz; + tmp->bsize = bsz; + tmp += 1; + start += bsz; + } +} + +static void init_ecc_prikey(struct wd_ecc_prikey *prikey, + __u32 ksz, __u32 bsz) +{ + init_dtb_param(prikey, prikey->data, ksz, bsz, ECC_PRIKEY_PARAM_NUM); +} + +static void init_ecc_pubkey(struct wd_ecc_pubkey *pubkey, + __u32 ksz, __u32 bsz) +{ + init_dtb_param(pubkey, pubkey->data, ksz, bsz, ECC_PUBKEY_PARAM_NUM); +} + +static void release_ecc_prikey(struct wd_ecc_sess *sess) +{ + struct wd_ecc_prikey *prikey = sess->key.prikey; + + wd_memset_zero(prikey->data, prikey->size); + free(prikey->data); + free(prikey); + sess->key.prikey = NULL; +} + +static void release_ecc_pubkey(struct wd_ecc_sess *sess) +{ + struct wd_ecc_pubkey *pubkey = sess->key.pubkey; + + free(pubkey->data); + free(pubkey); + sess->key.pubkey = NULL; +} + +static struct wd_ecc_prikey *create_ecc_prikey(struct wd_ecc_sess *sess) +{ + struct wd_ecc_prikey *prikey; + __u32 hsz, dsz; + void *data; + + hsz = get_key_bsz(sess->key_size); + prikey = malloc(sizeof(struct wd_ecc_prikey)); + if (!prikey) { + WD_ERR("failed to malloc prikey!\n"); + return NULL; + } + + dsz = ECC_PRIKEY_SZ(hsz); + data = malloc(dsz); + if (!data) { + WD_ERR("failed to malloc prikey data, sz = %u!\n", dsz); + free(prikey); + return NULL; + } + + memset(data, 0, dsz); + prikey->size = dsz; + prikey->data = data; + init_ecc_prikey(prikey, sess->key_size, hsz); + + return prikey; +} + +static struct wd_ecc_pubkey *create_ecc_pubkey(struct wd_ecc_sess *sess) +{ + struct wd_ecc_pubkey *pubkey; + __u32 hsz, dsz; + void *data; + + hsz = get_key_bsz(sess->key_size); + pubkey = malloc(sizeof(struct wd_ecc_pubkey)); + if (!pubkey) { + WD_ERR("failed to malloc pubkey!\n"); + return NULL; + } + + dsz = ECC_PUBKEY_SZ(hsz); + data = malloc(dsz); + if (!data) { + WD_ERR("failed to malloc pubkey data, sz = %u!\n", dsz); + free(pubkey); + return NULL; + } + + memset(data, 0, dsz); + pubkey->size = dsz; + pubkey->data = data; + init_ecc_pubkey(pubkey, sess->key_size, hsz); + + return pubkey; +} + +static void release_ecc_in(struct wd_ecc_sess *sess, + struct wd_ecc_in *ecc_in) +{ + wd_memset_zero(ecc_in->data, ecc_in->size); + free(ecc_in); +} + +static struct wd_ecc_in *create_ecc_in(struct wd_ecc_sess *sess, __u32 num) +{ + struct wd_ecc_in *in; + __u32 hsz, len; + + if (!sess->key_size || sess->key_size > ECC_MAX_KEY_SIZE) { + WD_ERR("invalid: sess key size %u is error!\n", sess->key_size); + return NULL; + } + + hsz = get_key_bsz(sess->key_size); + len = sizeof(struct wd_ecc_in) + hsz * num; + in = malloc(len); + if (!in) { + WD_ERR("failed to malloc ecc in, sz = %u!\n", len); + return NULL; + } + + memset(in, 0, len); + in->size = hsz * num; + init_dtb_param(in, in->data, sess->key_size, hsz, num); + + return in; +} + +static struct wd_ecc_in *create_sm2_sign_in(struct wd_ecc_sess *sess, + __u64 m_len) +{ + struct wd_dtb *dgst, *k, *plaintext; + __u32 ksz = sess->key_size; + struct wd_ecc_in *in; + __u64 len; + + if (ksz != SM2_KEY_SIZE) { + WD_ERR("invalid: sess key size %u is error!\n", ksz); + return NULL; + } + + len = sizeof(struct wd_ecc_in) + + ECC_SIGN_IN_PARAM_NUM * ksz + m_len; + in = malloc(len); + if (!in) { + WD_ERR("failed to malloc sm2 sign in, sz = %llu!\n", len); + return NULL; + } + + memset(in, 0, len); + in->size = len - sizeof(struct wd_ecc_in); + dgst = (void *)in; + dgst->data = in->data; + dgst->dsize = ksz; + dgst->bsize = ksz; + + k = dgst + 1; + k->data = dgst->data + ksz; + k->dsize = ksz; + k->bsize = ksz; + + plaintext = k + 1; + plaintext->data = k->data + ksz; + plaintext->dsize = m_len; + plaintext->bsize = m_len; + + return in; +} + +static struct wd_ecc_in *create_sm2_enc_in(struct wd_ecc_sess *sess, + __u64 m_len) +{ + struct wd_dtb *k, *plaintext; + __u32 ksz = sess->key_size; + struct wd_ecc_in *in; + __u64 len; + + if (ksz != SM2_KEY_SIZE) { + WD_ERR("invalid: sess key size %u is error!\n", sess->key_size); + return NULL; + } + + len = sizeof(struct wd_ecc_in) + ksz + m_len; + in = malloc(len); + if (!in) { + WD_ERR("failed to malloc sm2 enc in, sz = %llu!\n", len); + return NULL; + } + + memset(in, 0, len); + in->size = ksz + m_len; + k = (void *)in; + k->data = in->data; + k->dsize = ksz; + k->bsize = ksz; + + plaintext = k + 1; + plaintext->data = k->data + ksz; + plaintext->dsize = m_len; + plaintext->bsize = m_len; + + return in; +} + +static void *create_sm2_ciphertext(struct wd_ecc_sess *sess, __u32 m_len, + __u64 *len, __u32 st_sz) +{ + struct wd_hash_mt *hash = &sess->setup.hash; + __u32 ksz = sess->key_size; + struct wd_ecc_point *c1; + struct wd_dtb *c3, *c2; + __u32 h_byts; + void *start; + + if (unlikely(ksz != SM2_KEY_SIZE)) { + WD_ERR("invalid: sess key size %u is error!\n", ksz); + return NULL; + } + + h_byts = get_hash_bytes(hash->type); + if (!h_byts) { + WD_ERR("failed to get hash bytes, type = %u!\n", hash->type); + return NULL; + } + + *len = (__u64)st_sz + ECC_POINT_PARAM_NUM * (__u64)sess->key_size + + (__u64)m_len + (__u64)h_byts; + start = malloc(*len); + if (unlikely(!start)) { + WD_ERR("failed to alloc start, sz = %llu!\n", *len); + return NULL; + } + + c1 = (struct wd_ecc_point *)start; + c1->x.data = (char *)start + st_sz; + c1->x.dsize = ksz; + c1->x.bsize = ksz; + c1->y.data = c1->x.data + ksz; + c1->y.dsize = ksz; + c1->y.bsize = ksz; + + c2 = (struct wd_dtb *)(c1 + 1); + c2->data = c1->y.data + ksz; + c2->dsize = m_len; + c2->bsize = m_len; + + c3 = c2 + 1; + c3->data = c2->data + m_len; + c3->dsize = h_byts; + c3->bsize = h_byts; + + return start; +} + +static struct wd_ecc_in *create_ecc_sign_in(struct wd_ecc_sess *sess, + __u64 m_len, __u8 is_dgst) +{ + if (is_dgst) + return create_ecc_in(sess, ECC_SIGN_IN_PARAM_NUM); + + return create_sm2_sign_in(sess, m_len); +} + +static struct wd_ecc_out *create_ecc_out(struct wd_ecc_sess *sess, __u32 num) +{ + struct wd_ecc_out *out; + __u32 hsz, len; + + if (!sess->key_size || sess->key_size > ECC_MAX_KEY_SIZE) { + WD_ERR("invalid: sess key size %u is error!\n", sess->key_size); + return NULL; + } + + hsz = get_key_bsz(sess->key_size); + len = sizeof(struct wd_ecc_out) + hsz * num; + out = malloc(len); + if (!out) { + WD_ERR("failed to malloc out, sz = %u!\n", len); + return NULL; + } + + memset(out, 0, len); + out->size = hsz * num; + init_dtb_param(out, out->data, sess->key_size, hsz, num); + + return out; +} + +static struct wd_ecc_curve *create_ecc_curve(struct wd_ecc_sess *sess) +{ + struct wd_ecc_curve *cv; + __u32 ksize, len; + + ksize = sess->key_size; + len = sizeof(*cv) + ksize * CURVE_PARAM_NUM; + cv = malloc(len); + if (!cv) { + WD_ERR("failed to malloc curve!\n"); + return NULL; + } + + memset(cv, 0, len); + init_dtb_param(cv, (void *)(cv + 1), ksize, ksize, CURVE_PARAM_NUM); + + return cv; +} + +static struct wd_ecc_point *create_ecc_pub(struct wd_ecc_sess *sess) +{ + struct wd_ecc_point *pub; + __u32 ksize, len; + + ksize = sess->key_size; + len = sizeof(*pub) + ksize * ECC_POINT_NUM; + pub = malloc(len); + if (!pub) { + WD_ERR("failed to malloc pub!\n"); + return NULL; + } + + memset(pub, 0, len); + init_dtb_param(pub, (void *)(pub + 1), ksize, ksize, ECC_POINT_NUM); + + return pub; +} + +static struct wd_dtb *create_ecc_d(struct wd_ecc_sess *sess) +{ + struct wd_dtb *d; + __u32 ksize, len; + + ksize = sess->key_size; + len = sizeof(*d) + ksize; + d = malloc(len); + if (!d) { + WD_ERR("failed to malloc d!\n"); + return NULL; + } + + memset(d, 0, len); + init_dtb_param(d, (void *)(d + 1), ksize, ksize, 1); + + return d; +} + +static void release_ecc_curve(struct wd_ecc_sess *sess) +{ + free(sess->key.cv); + sess->key.cv = NULL; +} + +static void release_ecc_pub(struct wd_ecc_sess *sess) +{ + free(sess->key.pub); + sess->key.pub = NULL; +} + +static void release_ecc_d(struct wd_ecc_sess *sess) +{ + wd_memset_zero(sess->key.d + 1, sess->key_size); + free(sess->key.d); + sess->key.d = NULL; +} + +static int set_param_single(struct wd_dtb *dst, const struct wd_dtb *src, + const char *p_name) +{ + if (unlikely(!src || !src->data)) { + WD_ERR("invalid: %s src or data NULL!\n", p_name); + return -WD_EINVAL; + } + + if (!src->dsize || src->dsize > dst->dsize) { + WD_ERR("invalid: %s src dsz %u or dst dsz %u is error!\n", + p_name, src->dsize, dst->dsize); + return -WD_EINVAL; + } + + dst->dsize = src->dsize; + memset(dst->data, 0, dst->bsize); + memcpy(dst->data, src->data, src->dsize); + + return 0; +} + +int wd_ecc_get_key_bits(handle_t sess) +{ + if (!sess) { + WD_ERR("invalid: get ecc key bits, sess NULL!\n"); + return -WD_EINVAL; + } + + return ((struct wd_ecc_sess *)sess)->setup.key_bits; +} + +static int set_curve_param_single(struct wd_ecc_key *key, + const struct wd_dtb *param, + __u32 type) +{ + struct wd_ecc_prikey *pri = key->prikey; + struct wd_ecc_pubkey *pub = key->pubkey; + struct wd_dtb *tmp1, *tmp2; + int ret; + + tmp1 = (struct wd_dtb *)((char *)pri + + curve_pram_list[type].pri_offset); + tmp2 = (struct wd_dtb *)((char *)pub + + curve_pram_list[type].pub_offset); + if (type == ECC_CURVE_G) { + ret = set_param_single(tmp1 + 1, param + 1, "set cv"); + if (unlikely(ret)) + return ret; + + ret = set_param_single(tmp2 + 1, param + 1, "set cv"); + if (unlikely(ret)) + return ret; + } + + ret = set_param_single(tmp1, param, "set cv"); + if (unlikely(ret)) + return ret; + + return set_param_single(tmp2, param, "set cv"); +} + +static int set_curve_param(struct wd_ecc_key *key, + const struct wd_ecc_curve *param) +{ + int ret; + + ret = set_curve_param_single(key, ¶m->p, ECC_CURVE_P); + if (ret) { + WD_ERR("failed to set curve param: p error!\n"); + return -WD_EINVAL; + } + + ret = set_curve_param_single(key, ¶m->a, ECC_CURVE_A); + if (ret) { + WD_ERR("failed to set curve param: a error!\n"); + return -WD_EINVAL; + } + + ret = set_curve_param_single(key, ¶m->b, ECC_CURVE_B); + if (ret) { + WD_ERR("failed to set curve param: b error!\n"); + return -WD_EINVAL; + } + + ret = set_curve_param_single(key, ¶m->n, ECC_CURVE_N); + if (ret) { + WD_ERR("failed to set curve param: n error!\n"); + return -WD_EINVAL; + } + + ret = set_curve_param_single(key, (void *)¶m->g, ECC_CURVE_G); + if (ret) { + WD_ERR("failed to set curve param: g error!\n"); + return -WD_EINVAL; + } + + return 0; +} + +static const struct wd_ecc_curve_list *find_curve_list(__u32 id) +{ + int len = ARRAY_SIZE(curve_list); + int i = 0; + + while (i < len) { + if (curve_list[i].id == id) + return &curve_list[i]; + i++; + } + + return NULL; +} + +static int fill_param_by_id(struct wd_ecc_curve *c, + __u16 key_bits, __u32 id) +{ + struct wd_ecc_curve_list *item; + __u32 key_size; + + item = (struct wd_ecc_curve_list *)find_curve_list(id); + if (!item) { + WD_ERR("failed to find curve id %u!\n", id); + return -WD_EINVAL; + } + + if (item->key_bits != key_bits) { + WD_ERR("invalid: curve %u and key bits %u not match!\n", id, key_bits); + return -WD_EINVAL; + } + + key_size = BITS_TO_BYTES(item->key_bits); + memcpy(c->p.data, item->data, CURVE_PARAM_NUM * key_size); + + return 0; +} + +static void setup_curve_cfg(struct wd_ecc_sess_setup *setup) +{ + if (!strcmp(setup->alg, "x25519")) { + setup->key_bits = 256; /* key width */ + setup->cv.type = WD_CV_CFG_ID; + setup->cv.cfg.id = WD_X25519; + } else if (!strcmp(setup->alg, "x448")) { + setup->key_bits = 448; + setup->cv.type = WD_CV_CFG_ID; + setup->cv.cfg.id = WD_X448; + } else if ((!strcmp(setup->alg, "sm2"))) { + setup->key_bits = 256; + setup->cv.type = WD_CV_CFG_ID; + setup->cv.cfg.id = WD_SM2P256; + } +} + +static int set_key_cv(struct wd_ecc_curve *dst, + struct wd_ecc_curve *src) +{ + int ret; + + if (unlikely(!src)) { + WD_ERR("invalid: set key cv, praram NULL!\n"); + return -WD_EINVAL; + } + + ret = set_param_single(&dst->p, &src->p, "cv p"); + if (ret) + return ret; + + ret = set_param_single(&dst->a, &src->a, "cv a"); + if (ret) + return ret; + + ret = set_param_single(&dst->b, &src->b, "cv b"); + if (ret) + return ret; + + ret = set_param_single(&dst->g.x, &src->g.x, "cv gx"); + if (ret) + return ret; + + ret = set_param_single(&dst->g.y, &src->g.y, "cv gy"); + if (ret) + return ret; + + return set_param_single(&dst->n, &src->n, "cv n"); +} + +static int fill_user_curve_cfg(struct wd_ecc_curve *param, + struct wd_ecc_sess_setup *setup) +{ + struct wd_ecc_curve *src_param = setup->cv.cfg.pparam; + __u32 curve_id; + int ret = 0; + + if (setup->cv.type == WD_CV_CFG_ID) { + curve_id = setup->cv.cfg.id; + ret = fill_param_by_id(param, setup->key_bits, curve_id); + WD_DEBUG("set curve id %u!\n", curve_id); + } else if (setup->cv.type == WD_CV_CFG_PARAM) { + ret = set_key_cv(param, src_param); + if (ret) { + WD_ERR("failed to set key cv!\n"); + return ret; + } + WD_DEBUG("set curve by user param!\n"); + } else { + WD_ERR("invalid: fill curve cfg type %u is error!\n", setup->cv.type); + return -WD_EINVAL; + } + + if (!param->p.dsize || + param->p.dsize > BITS_TO_BYTES(setup->key_bits)) { + WD_ERR("invalid: fill curve cfg dsize %u is error!\n", param->p.dsize); + return -WD_EINVAL; + } + + return ret; +} + +static int create_sess_key(struct wd_ecc_sess_setup *setup, + struct wd_ecc_sess *sess) +{ + int ret = -WD_ENOMEM; + + sess->key.prikey = create_ecc_prikey(sess); + if (!sess->key.prikey) + return -WD_ENOMEM; + + sess->key.pubkey = create_ecc_pubkey(sess); + if (!sess->key.pubkey) + goto free_prikey; + + sess->key.cv = create_ecc_curve(sess); + if (!sess->key.cv) + goto free_pubkey; + + sess->key.pub = create_ecc_pub(sess); + if (!sess->key.pub) + goto free_curve; + + sess->key.d = create_ecc_d(sess); + if (!sess->key.d) + goto free_pub; + + ret = fill_user_curve_cfg(sess->key.cv, setup); + if (ret) { + WD_ERR("failed to fill user curve cfg!\n"); + goto free_d; + } + + ret = set_curve_param(&sess->key, sess->key.cv); + if (ret) { + WD_ERR("failed to set curve param!\n"); + goto free_d; + } + + return 0; + +free_d: + release_ecc_d(sess); + +free_pub: + release_ecc_pub(sess); + +free_curve: + release_ecc_curve(sess); + +free_pubkey: + release_ecc_pubkey(sess); + +free_prikey: + release_ecc_prikey(sess); + + return ret; +} + +static bool is_key_width_support(__u32 key_bits) +{ + /* key bit width check */ + if (unlikely(key_bits != 128 && key_bits != 192 && + key_bits != 224 && key_bits != 256 && + key_bits != 320 && key_bits != 384 && + key_bits != 448 && key_bits != 521)) + return false; + + return true; +} + +static bool is_alg_support(const char *alg) +{ + if (unlikely(strcmp(alg, "ecdh") && strcmp(alg, "ecdsa") && + strcmp(alg, "x25519") && strcmp(alg, "x448") && + strcmp(alg, "sm2"))) + return false; + + return true; +} + +static int setup_param_check(struct wd_ecc_sess_setup *setup) +{ + if (unlikely(!setup || !setup->alg)) { + WD_ERR("invalid: input parameter error!\n"); + return -WD_EINVAL; + } + + if (unlikely(!is_alg_support(setup->alg))) { + WD_ERR("invalid: algorithms %s not supported!\n", setup->alg); + return -WD_EINVAL; + } + + setup_curve_cfg(setup); + + if (unlikely(!is_key_width_support(setup->key_bits))) { + WD_ERR("invalid: key_bits %u is error!\n", setup->key_bits); + return -WD_EINVAL; + } + + return 0; +} + +static void del_sess_key(struct wd_ecc_sess *sess) +{ + if (sess->key.prikey) { + wd_memset_zero(sess->key.prikey->data, sess->key.prikey->size); + free(sess->key.prikey->data); + free(sess->key.prikey); + sess->key.prikey = NULL; + } + + if (sess->key.pubkey) { + free(sess->key.pubkey->data); + free(sess->key.pubkey); + sess->key.pubkey = NULL; + } + + if (sess->key.cv) + free(sess->key.cv); + if (sess->key.pub) + free(sess->key.pub); + if (sess->key.d) { + wd_memset_zero(sess->key.d + 1, sess->key_size); + free(sess->key.d); + } +} + +handle_t wd_ecc_alloc_sess(struct wd_ecc_sess_setup *setup) +{ + struct wd_ecc_sess *sess; + int ret; + + if (setup_param_check(setup)) + return (handle_t)0; + + sess = calloc(1, sizeof(struct wd_ecc_sess)); + if (!sess) + return (handle_t)0; + + memcpy(&sess->setup, setup, sizeof(*setup)); + sess->key_size = BITS_TO_BYTES(setup->key_bits); + + ret = create_sess_key(setup, sess); + if (ret) { + WD_ERR("failed to creat ecc sess keys!\n"); + goto sess_err; + } + + /* Some simple scheduler don't need scheduling parameters */ + sess->sched_key = (void *)wd_ecc_setting.sched.sched_init( + wd_ecc_setting.sched.h_sched_ctx, setup->sched_param); + if (WD_IS_ERR(sess->sched_key)) { + WD_ERR("failed to init session schedule key!\n"); + goto sched_err; + } + + return (handle_t)sess; + +sched_err: + del_sess_key(sess); +sess_err: + free(sess); + return (handle_t)0; +} + +void wd_ecc_free_sess(handle_t sess) +{ + struct wd_ecc_sess *sess_t = (struct wd_ecc_sess *)sess; + + if (!sess_t) { + WD_ERR("invalid: free ecc sess parameter err!\n"); + return; + } + + if (sess_t->sched_key) + free(sess_t->sched_key); + del_sess_key(sess_t); + free(sess_t); +} + +struct wd_ecc_key *wd_ecc_get_key(handle_t sess) +{ + struct wd_ecc_sess *sess_t = (struct wd_ecc_sess *)sess; + + if (!sess_t) { + WD_ERR("invalid: get ecc key sess NULL!\n"); + return NULL; + } + + return &sess_t->key; +} + +int wd_ecc_set_prikey(struct wd_ecc_key *ecc_key, + struct wd_dtb *prikey) +{ + struct wd_ecc_prikey *ecc_prikey; + struct wd_dtb *d; + int ret; + + if (!ecc_key || !prikey) { + WD_ERR("invalid: set ecc prikey parameter NULL!\n"); + return -WD_EINVAL; + } + + ecc_prikey = ecc_key->prikey; + d = ecc_key->d; + if (!ecc_prikey || !d) { + WD_ERR("invalid: ecc_prikey or d NULL!\n"); + return -WD_EINVAL; + } + + ret = set_param_single(&ecc_prikey->d, prikey, "set prikey d"); + if (ret) + return ret; + + return set_param_single(d, prikey, "set d"); +} + +int wd_ecc_get_prikey(struct wd_ecc_key *ecc_key, + struct wd_dtb **prikey) +{ + if (!ecc_key || !prikey) { + WD_ERR("invalid: get ecc prikey parameter err!\n"); + return -WD_EINVAL; + } + + *prikey = ecc_key->d; + + return WD_SUCCESS; +} + +int wd_ecc_set_pubkey(struct wd_ecc_key *ecc_key, struct wd_ecc_point *pubkey) +{ + struct wd_ecc_pubkey *ecc_pubkey; + struct wd_ecc_point *pub; + int ret; + + if (!ecc_key || !pubkey) { + WD_ERR("invalid: set ecc pubkey parameter err!\n"); + return -WD_EINVAL; + } + + pub = ecc_key->pub; + ecc_pubkey = ecc_key->pubkey; + if (!ecc_pubkey || !pub) { + WD_ERR("invalid: ecc_pubkey or pub NULL!\n"); + return -WD_EINVAL; + } + + ret = set_param_single(&ecc_pubkey->pub.x, &pubkey->x, "ecc pubkey x"); + if (ret) + return ret; + + ret = set_param_single(&ecc_pubkey->pub.y, &pubkey->y, "ecc pubkey y"); + if (ret) + return ret; + + ret = trans_to_binpad(pub->x.data, pubkey->x.data, + pub->x.bsize, pubkey->x.dsize, "ecc pub x"); + if (ret) + return ret; + + return trans_to_binpad(pub->y.data, pubkey->y.data, + pub->y.bsize, pubkey->y.dsize, "ecc pub y"); +} + +int wd_ecc_get_pubkey(struct wd_ecc_key *ecc_key, + struct wd_ecc_point **pubkey) +{ + if (!ecc_key || !pubkey) { + WD_ERR("invalid: get ecc pubkey parameter err!\n"); + return -WD_EINVAL; + } + + *pubkey = ecc_key->pub; + + return WD_SUCCESS; +} + +int wd_ecc_get_curve(struct wd_ecc_key *ecc_key, + struct wd_ecc_curve **cv) +{ + if (!ecc_key || !cv) { + WD_ERR("invalid: get ecc pubkey parameter err!\n"); + return -WD_EINVAL; + } + + *cv = ecc_key->cv; + + return WD_SUCCESS; +} + +void wd_ecc_get_prikey_params(struct wd_ecc_key *key, + struct wd_dtb **p, struct wd_dtb **a, + struct wd_dtb **b, struct wd_dtb **n, + struct wd_ecc_point **g, + struct wd_dtb **d) +{ + struct wd_ecc_prikey *prk; + + if (!key || !key->prikey) { + WD_ERR("invalid: input NULL in get ecc prikey param!\n"); + return; + } + + prk = key->prikey; + + if (p) + *p = &prk->p; + + if (a) + *a = &prk->a; + + if (b) + *b = &prk->b; + + if (n) + *n = &prk->n; + + if (g) + *g = &prk->g; + + if (d) + *d = &prk->d; +} + +void wd_ecc_get_pubkey_params(struct wd_ecc_key *key, + struct wd_dtb **p, struct wd_dtb **a, + struct wd_dtb **b, struct wd_dtb **n, + struct wd_ecc_point **g, + struct wd_ecc_point **pub) +{ + struct wd_ecc_pubkey *pbk; + + if (!key || !key->pubkey) { + WD_ERR("invalid: input NULL in get ecc pubkey param!\n"); + return; + } + + pbk = key->pubkey; + + if (p) + *p = &pbk->p; + + if (a) + *a = &pbk->a; + + if (b) + *b = &pbk->b; + + if (n) + *n = &pbk->n; + + if (g) + *g = &pbk->g; + + if (pub) + *pub = &pbk->pub; +} + +struct wd_ecc_in *wd_ecxdh_new_in(handle_t sess, struct wd_ecc_point *in) +{ + struct wd_ecc_sess *s = (struct wd_ecc_sess *)sess; + struct wd_ecc_dh_in *dh_in; + struct wd_ecc_in *ecc_in; + int ret; + + if (!s || !in) { + WD_ERR("invalid: new ecc dh in parameter error!\n"); + return NULL; + } + + ecc_in = create_ecc_in(s, ECDH_IN_PARAM_NUM); + if (!ecc_in) + return NULL; + + dh_in = &ecc_in->param.dh_in; + ret = set_param_single(&dh_in->pbk.x, &in->x, "ecc in x"); + if (ret) + goto set_param_error; + + ret = set_param_single(&dh_in->pbk.y, &in->y, "ecc in y"); + if (ret) + goto set_param_error; + + return ecc_in; + +set_param_error: + release_ecc_in(s, ecc_in); + return NULL; +} + +struct wd_ecc_out *wd_ecxdh_new_out(handle_t sess) +{ + if (!sess) { + WD_ERR("invalid: new ecc dh out sess NULL!\n"); + return NULL; + } + + return create_ecc_out((struct wd_ecc_sess *)sess, ECDH_OUT_PARAM_NUM); +} + +void wd_ecxdh_get_out_params(struct wd_ecc_out *out, struct wd_ecc_point **pbk) +{ + struct wd_ecc_dh_out *dh_out = (void *)out; + + if (!dh_out) { + WD_ERR("invalid: input NULL in get ecdh out!\n"); + return; + } + + if (pbk) + *pbk = &dh_out->out; +} + +void wd_ecc_del_in(handle_t sess, struct wd_ecc_in *in) +{ + __u32 bsz; + + if (!in) { + WD_ERR("invalid: del ecc in parameter error!\n"); + return; + } + + bsz = in->size; + if (!bsz) { + WD_ERR("invalid: del ecc in, bsz 0!\n"); + return; + } + + wd_memset_zero(in->data, bsz); + free(in); +} + +void wd_ecc_del_out(handle_t sess, struct wd_ecc_out *out) +{ + __u32 bsz; + + if (!out) { + WD_ERR("invalid: del ecc out parameter error!\n"); + return; + } + + bsz = out->size; + if (!bsz) { + WD_ERR("invalid: del ecc out, bsz 0!\n"); + return; + } + + wd_memset_zero(out->data, bsz); + free(out); +} + +static int fill_ecc_msg(struct wd_ecc_msg *msg, struct wd_ecc_req *req, + struct wd_ecc_sess *sess) +{ + void *key = NULL; + + memcpy(&msg->req, req, sizeof(msg->req)); + msg->hash = sess->setup.hash; + msg->key_bytes = sess->key_size; + msg->curve_id = sess->setup.cv.cfg.id; + msg->result = WD_EINVAL; + + switch (req->op_type) { + case WD_ECXDH_GEN_KEY: + case WD_ECXDH_COMPUTE_KEY: + case WD_ECDSA_SIGN: + case WD_ECDSA_VERIFY: + case WD_SM2_ENCRYPT: + case WD_SM2_DECRYPT: + case WD_SM2_SIGN: + case WD_SM2_VERIFY: + case WD_SM2_KG: + key = &sess->key; + break; + default: + WD_ERR("invalid: ecc request op type %u is error!\n", req->op_type); + return -WD_EINVAL; + } + msg->key = key; + + if (req->op_type == WD_ECXDH_GEN_KEY || + req->op_type == WD_SM2_KG) { + struct wd_ecc_point *g = NULL; + + wd_ecc_get_prikey_params((void *)key, NULL, NULL, + NULL, NULL, &g, NULL); + msg->req.src = g; + } + + if (!msg->req.src || (!req->dst && (req->op_type != WD_ECDSA_VERIFY && + req->op_type != WD_SM2_VERIFY))) { + WD_ERR("invalid: req in/out NULL!\n"); + return -WD_EINVAL; + } + + return WD_SUCCESS; +} + +static void msg_pack(char *dst, __u64 *out_len, + const void *src, __u32 src_len) +{ + if (!src || !src_len) + return; + + memcpy(dst + *out_len, src, src_len); + *out_len += src_len; +} + +int wd_do_ecc_sync(handle_t h_sess, struct wd_ecc_req *req) +{ + struct wd_ctx_config_internal *config = &wd_ecc_setting.config; + handle_t h_sched_ctx = wd_ecc_setting.sched.h_sched_ctx; + struct wd_ecc_sess *sess = (struct wd_ecc_sess *)h_sess; + struct wd_msg_handle msg_handle; + struct wd_ctx_internal *ctx; + struct wd_ecc_msg msg; + __u32 idx; + int ret; + + if (unlikely(!h_sess || !req)) { + WD_ERR("invalid: input parameter NULL!\n"); + return -WD_EINVAL; + } + + idx = wd_ecc_setting.sched.pick_next_ctx(h_sched_ctx, + sess->sched_key, + CTX_MODE_SYNC); + ret = wd_check_ctx(config, CTX_MODE_SYNC, idx); + if (ret) + return ret; + + wd_dfx_msg_cnt(config->msg_cnt, WD_CTX_CNT_NUM, idx); + ctx = config->ctxs + idx; + + memset(&msg, 0, sizeof(struct wd_ecc_msg)); + ret = fill_ecc_msg(&msg, req, sess); + if (unlikely(ret)) + return ret; + + msg_handle.send = wd_ecc_setting.driver->send; + msg_handle.recv = wd_ecc_setting.driver->recv; + + pthread_spin_lock(&ctx->lock); + ret = wd_handle_msg_sync(&msg_handle, ctx->ctx, &msg, &balance, + wd_ecc_setting.config.epoll_en); + pthread_spin_unlock(&ctx->lock); + if (unlikely(ret)) + return ret; + + req->dst_bytes = msg.req.dst_bytes; + req->status = msg.result; + + return GET_NEGATIVE(msg.result); +} + +static void get_sign_out_params(struct wd_ecc_out *out, + struct wd_dtb **r, struct wd_dtb **s) +{ + struct wd_ecc_sign_out *sout = (void *)out; + + if (!sout) { + WD_ERR("invalid: input NULL in get ecc sign out!\n"); + return; + } + + if (r) + *r = &sout->r; + + if (s) + *s = &sout->s; +} + +void wd_sm2_get_sign_out_params(struct wd_ecc_out *out, + struct wd_dtb **r, struct wd_dtb **s) +{ + return get_sign_out_params(out, r, s); +} + +static int set_sign_in_param(struct wd_ecc_sign_in *sin, + struct wd_dtb *dgst, + struct wd_dtb *k, + struct wd_dtb *plaintext) +{ + int ret; + + if (k) { + ret = set_param_single(&sin->k, k, "sign k"); + if (ret) + return ret; + } + + if (dgst) { + ret = set_param_single(&sin->dgst, dgst, "sign dgst"); + if (ret) + return ret; + } + + if (plaintext && plaintext->dsize) { + ret = set_param_single(&sin->plaintext, plaintext, "sign m"); + if (ret) + return ret; + } + + return 0; +} + +static int generate_random(struct wd_ecc_sess *sess, struct wd_dtb *k) +{ + struct wd_rand_mt rand_t = sess->setup.rand; + int ret; + + ret = rand_t.cb(k->data, k->dsize, rand_t.usr); + if (ret) + WD_ERR("failed to do rand cb, ret = %d!\n", ret); + + return ret; +} + +static int sm2_compute_za_hash(__u8 *za, __u32 *len, struct wd_dtb *id, + struct wd_ecc_sess *sess) + +{ + __u32 key_size = BITS_TO_BYTES(sess->setup.key_bits); + struct wd_hash_mt *hash = &sess->setup.hash; + struct wd_ecc_point *pub = sess->key.pub; + struct wd_ecc_curve *cv = sess->key.cv; + __u16 id_bytes = 0; + __u16 id_bits = 0; + __u64 in_len = 0; + __u32 hash_bytes; + char *p_in; + __u64 lens; + __u8 temp; + int ret; + + if (id && (!BYTES_TO_BITS(id->dsize) || !id->data || + BYTES_TO_BITS(id->dsize) > UINT16_MAX)) { + WD_ERR("invalid: id error, lens = %u!\n", id->dsize); + return -WD_EINVAL; + } + + if (id) { + id_bits = BYTES_TO_BITS(id->dsize); + id_bytes = id->dsize; + } + + /* ZA = h(ENTL || ID || a || b || xG || yG || xA || yA) */ + lens = sizeof(__u16) + id_bytes + ZA_PARAM_NUM * key_size; + p_in = malloc(lens); + if (unlikely(!p_in)) + return -WD_ENOMEM; + + memset(p_in, 0, lens); + temp = id_bits >> 8; + msg_pack(p_in, &in_len, &temp, sizeof(__u8)); + temp = id_bits & 0xFF; + msg_pack(p_in, &in_len, &temp, sizeof(__u8)); + if (id) + msg_pack(p_in, &in_len, id->data, id_bytes); + msg_pack(p_in, &in_len, cv->a.data, key_size); + msg_pack(p_in, &in_len, cv->b.data, key_size); + msg_pack(p_in, &in_len, cv->g.x.data, key_size); + msg_pack(p_in, &in_len, cv->g.y.data, key_size); + msg_pack(p_in, &in_len, pub->x.data, key_size); + msg_pack(p_in, &in_len, pub->y.data, key_size); + hash_bytes = get_hash_bytes(hash->type); + *len = hash_bytes; + ret = hash->cb((const char *)p_in, in_len, + (void *)za, hash_bytes, hash->usr); + + free(p_in); + + return ret; +} + +static int sm2_compute_digest(struct wd_ecc_sess *sess, struct wd_dtb *hash_msg, + struct wd_dtb *plaintext, struct wd_dtb *id) + +{ + struct wd_hash_mt *hash = &sess->setup.hash; + __u8 za[SM2_KEY_SIZE] = {0}; + __u32 za_len = SM2_KEY_SIZE; + __u32 hash_bytes; + __u64 in_len = 0; + char *p_in; + __u64 lens; + int ret; + + hash_bytes = get_hash_bytes(hash->type); + if (unlikely(!hash_bytes || hash_bytes > SM2_KEY_SIZE)) { + WD_ERR("invalid: hash type %hhu is error!\n", hash->type); + return -WD_EINVAL; + } + + ret = sm2_compute_za_hash(za, &za_len, id, sess); + if (unlikely(ret)) { + WD_ERR("failed to compute za, ret = %d!\n", ret); + return ret; + } + + lens = plaintext->dsize + hash_bytes; + p_in = malloc(lens); + if (unlikely(!p_in)) + return -WD_ENOMEM; + + /* e = h(ZA || M) */ + memset(p_in, 0, lens); + msg_pack(p_in, &in_len, za, za_len); + msg_pack(p_in, &in_len, plaintext->data, plaintext->dsize); + hash_msg->dsize = hash_bytes; + ret = hash->cb((const char *)p_in, in_len, hash_msg->data, + hash_bytes, hash->usr); + if (unlikely(ret)) + WD_ERR("failed to compute e, ret = %d!\n", ret); + + free(p_in); + + return ret; +} + +static struct wd_ecc_in *new_sign_in(struct wd_ecc_sess *sess, + struct wd_dtb *e, struct wd_dtb *k, + struct wd_dtb *id, __u8 is_dgst) +{ + struct wd_ecc_sess *sess_t = (struct wd_ecc_sess *)sess; + struct wd_dtb *plaintext = NULL; + struct wd_dtb *hash_msg = NULL; + struct wd_ecc_sign_in *sin; + struct wd_ecc_in *ecc_in; + int ret; + + if (!sess || !e) { + WD_ERR("invalid: new ecc sign in, sess or e NULL!\n"); + return NULL; + } + + ecc_in = create_ecc_sign_in(sess_t, e->dsize, is_dgst); + if (!ecc_in) + return NULL; + + sin = &ecc_in->param.sin; + if (!k && sess_t->setup.rand.cb) { + ret = generate_random(sess_t, &sin->k); + if (ret) + goto release_in; + } + + if (k || sess_t->setup.rand.cb) + sin->k_set = 1; + + if (!is_dgst) { + plaintext = e; + if (sess_t->setup.hash.cb) { + ret = sm2_compute_digest(sess_t, &sin->dgst, e, id); + if (ret) + goto release_in; + sin->dgst_set = 1; + } + } else { + hash_msg = e; + sin->dgst_set = 1; + } + + ret = set_sign_in_param(sin, hash_msg, k, plaintext); + if (ret) + goto release_in; + + return ecc_in; + +release_in: + release_ecc_in(sess_t, ecc_in); + + return NULL; +} + +static int set_verf_in_param(struct wd_ecc_verf_in *vin, + struct wd_dtb *dgst, + struct wd_dtb *r, + struct wd_dtb *s, + struct wd_dtb *plaintext) +{ + int ret; + + if (dgst) { + ret = set_param_single(&vin->dgst, dgst, "vrf dgst"); + if (ret) + return ret; + } + + if (plaintext && plaintext->dsize) { + ret = set_param_single(&vin->plaintext, plaintext, "vrf m"); + if (ret) + return ret; + } + + ret = set_param_single(&vin->s, s, "vrf s"); + if (ret) + return ret; + + ret = set_param_single(&vin->r, r, "vrf r"); + if (ret) + return ret; + + return 0; +} + +static struct wd_ecc_in *create_sm2_verf_in(struct wd_ecc_sess *sess, + __u64 m_len) +{ + struct wd_dtb *dgst, *s, *r, *plaintext; + struct wd_ecc_in *in; + __u64 len; + __u32 hsz; + + if (sess->key_size != SM2_KEY_SIZE) { + WD_ERR("invalid: sess key size %u is error!\n", sess->key_size); + return NULL; + } + + hsz = get_key_bsz(sess->key_size); + len = sizeof(struct wd_ecc_in) + ECC_VERF_IN_PARAM_NUM * hsz + + m_len; + in = malloc(len); + if (!in) { + WD_ERR("failed to malloc sm2 verf in, sz = %llu!\n", len); + return NULL; + } + + memset(in, 0, len); + in->size = len - sizeof(struct wd_ecc_in); + dgst = (void *)in; + dgst->data = in->data; + dgst->dsize = sess->key_size; + dgst->bsize = hsz; + + s = dgst + 1; + s->data = dgst->data + hsz; + s->dsize = sess->key_size; + s->bsize = hsz; + + r = s + 1; + r->data = s->data + hsz; + r->dsize = sess->key_size; + r->bsize = hsz; + + plaintext = r + 1; + plaintext->data = r->data + hsz; + plaintext->dsize = m_len; + plaintext->bsize = m_len; + + return in; +} + +static struct wd_ecc_in *create_ecc_verf_in(struct wd_ecc_sess *sess, + __u64 m_len, __u8 is_dgst) +{ + if (is_dgst) + return create_ecc_in(sess, ECC_VERF_IN_PARAM_NUM); + else + return create_sm2_verf_in(sess, m_len); +} + +static struct wd_ecc_in *new_verf_in(handle_t sess, + struct wd_dtb *e, + struct wd_dtb *r, + struct wd_dtb *s, + struct wd_dtb *id, + __u8 is_dgst) +{ + struct wd_ecc_sess *sess_t = (struct wd_ecc_sess *)sess; + struct wd_dtb *plaintext = NULL; + struct wd_dtb *hash_msg = NULL; + struct wd_ecc_verf_in *vin; + struct wd_ecc_in *ecc_in; + int ret; + + if (!sess_t || !r || !e || !s) { + WD_ERR("invalid: new ecc verf in parameter error!\n"); + return NULL; + } + + ecc_in = create_ecc_verf_in(sess_t, e->dsize, is_dgst); + if (!ecc_in) + return NULL; + + vin = &ecc_in->param.vin; + + if (!is_dgst) { + plaintext = e; + if (sess_t->setup.hash.cb) { + ret = sm2_compute_digest(sess_t, &vin->dgst, e, id); + if (ret) + goto release_in; + vin->dgst_set = 1; + } + } else { + hash_msg = e; + vin->dgst_set = 1; + } + + ret = set_verf_in_param(vin, hash_msg, r, s, plaintext); + if (ret) + goto release_in; + + return ecc_in; + +release_in: + release_ecc_in(sess_t, ecc_in); + + return NULL; +} + +struct wd_ecc_in *wd_sm2_new_sign_in(handle_t sess, + struct wd_dtb *e, + struct wd_dtb *k, + struct wd_dtb *id, + __u8 is_dgst) +{ + return new_sign_in((void *)sess, e, k, id, is_dgst); +} + +struct wd_ecc_in *wd_sm2_new_verf_in(handle_t sess, + struct wd_dtb *e, + struct wd_dtb *r, + struct wd_dtb *s, + struct wd_dtb *id, + __u8 is_dgst) +{ + return new_verf_in(sess, e, r, s, id, is_dgst); +} + +static struct wd_ecc_out *wd_ecc_new_sign_out(struct wd_ecc_sess *sess) +{ + if (!sess) { + WD_ERR("invalid: new ecc sout ctx NULL!\n"); + return NULL; + } + + return create_ecc_out(sess, ECC_SIGN_OUT_PARAM_NUM); +} + +struct wd_ecc_out *wd_sm2_new_sign_out(handle_t sess) +{ + return wd_ecc_new_sign_out((void *)sess); +} + +struct wd_ecc_out *wd_sm2_new_kg_out(handle_t sess) +{ + if (!sess) { + WD_ERR("invalid: new sm2 kg out sess NULL!\n"); + return NULL; + } + + return create_ecc_out((struct wd_ecc_sess *)sess, SM2_KG_OUT_PARAM_NUM); +} + +void wd_sm2_get_kg_out_params(struct wd_ecc_out *out, + struct wd_dtb **privkey, + struct wd_ecc_point **pubkey) +{ + struct wd_sm2_kg_out *kout = (void *)out; + + if (!kout) { + WD_ERR("invalid: input NULL in get sm2 kg out!\n"); + return; + } + + if (privkey) + *privkey = &kout->priv; + + if (pubkey) + *pubkey = &kout->pub; +} + +struct wd_ecc_in *wd_sm2_new_enc_in(handle_t sess, + struct wd_dtb *k, + struct wd_dtb *plaintext) +{ + struct wd_ecc_sess *sess_t = (struct wd_ecc_sess *)sess; + struct wd_sm2_enc_in *ein; + struct wd_ecc_in *ecc_in; + int ret; + + if (!sess_t || !plaintext) { + WD_ERR("invalid: new sm2 enc in parameter error!\n"); + return NULL; + } + + ecc_in = create_sm2_enc_in(sess_t, plaintext->dsize); + if (!ecc_in) { + WD_ERR("failed to create sm2 enc in!\n"); + return NULL; + } + + ein = &ecc_in->param.ein; + if (!k && sess_t->setup.rand.cb) { + ret = generate_random(sess_t, &ein->k); + if (ret) + goto fail_set_param; + } + + if (k || sess_t->setup.rand.cb) + ein->k_set = 1; + + if (k) { + ret = set_param_single(&ein->k, k, "ein k"); + if (ret) + goto fail_set_param; + } + + ret = set_param_single(&ein->plaintext, plaintext, "ein plaintext"); + if (ret) + goto fail_set_param; + + return ecc_in; + +fail_set_param: + release_ecc_in(sess_t, ecc_in); + + return NULL; +} + +struct wd_ecc_in *wd_sm2_new_dec_in(handle_t sess, + struct wd_ecc_point *c1, + struct wd_dtb *c2, + struct wd_dtb *c3) +{ + struct wd_ecc_sess *sess_t = (struct wd_ecc_sess *)sess; + __u32 struct_size = sizeof(struct wd_ecc_in); + struct wd_sm2_dec_in *din; + struct wd_ecc_in *ecc_in; + __u64 len = 0; + int ret; + + if (!sess_t || !c1 || !c2 || !c3) { + WD_ERR("invalid: new sm2 dec in parameter error!\n"); + return NULL; + } + + ecc_in = create_sm2_ciphertext(sess_t, c2->dsize, &len, struct_size); + if (!ecc_in) { + WD_ERR("failed to create sm2 dec in!\n"); + return NULL; + } + ecc_in->size = len - struct_size; + + din = &ecc_in->param.din; + ret = set_param_single(&din->c1.x, &c1->x, "c1 x"); + if (ret) + goto fail_set_param; + + ret = set_param_single(&din->c1.y, &c1->y, "c1 y"); + if (ret) + goto fail_set_param; + + ret = set_param_single(&din->c2, c2, "c2"); + if (ret) + goto fail_set_param; + + ret = set_param_single(&din->c3, c3, "c3"); + if (ret) + goto fail_set_param; + + return ecc_in; + +fail_set_param: + release_ecc_in(sess_t, ecc_in); + + return NULL; +} + +struct wd_ecc_out *wd_sm2_new_enc_out(handle_t sess, __u32 plaintext_len) +{ + struct wd_ecc_sess *sess_t = (struct wd_ecc_sess *)sess; + __u32 struct_size = sizeof(struct wd_ecc_out); + struct wd_ecc_out *ecc_out; + __u64 len = 0; + + if (!sess_t) { + WD_ERR("invalid: new ecc sout sess NULL!\n"); + return NULL; + } + + ecc_out = create_sm2_ciphertext(sess_t, plaintext_len, &len, struct_size); + if (!ecc_out) { + WD_ERR("failed to create sm2 enc out!\n"); + return NULL; + } + ecc_out->size = len - struct_size; + + return ecc_out; +} + +struct wd_ecc_out *wd_sm2_new_dec_out(handle_t sess, __u32 plaintext_len) +{ + struct wd_ecc_sess *sess_t = (struct wd_ecc_sess *)sess; + struct wd_sm2_dec_out *dout; + struct wd_ecc_out *ecc_out; + __u64 len; + + if (!sess || !plaintext_len) { + WD_ERR("new ecc sout sess NULL!\n"); + return NULL; + } + + if (sess_t->key_size != SM2_KEY_SIZE) { + WD_ERR("sess key size %u error!\n", sess_t->key_size); + return NULL; + } + + len = sizeof(*ecc_out) + plaintext_len; + ecc_out = malloc(len); + if (!ecc_out) { + WD_ERR("failed to malloc ecc_out, sz = %llu!\n", len); + return NULL; + } + memset(ecc_out, 0, len); + ecc_out->size = plaintext_len; + dout = &ecc_out->param.dout; + dout->plaintext.data = ecc_out->data; + dout->plaintext.dsize = plaintext_len; + dout->plaintext.bsize = plaintext_len; + + return ecc_out; +} + +void wd_sm2_get_enc_out_params(struct wd_ecc_out *out, + struct wd_ecc_point **c1, + struct wd_dtb **c2, + struct wd_dtb **c3) +{ + struct wd_sm2_enc_out *eout = (void *)out; + + if (!eout) { + WD_ERR("invalid: input NULL in get sm2 enc out!\n"); + return; + } + + if (c1) + *c1 = &eout->c1; + + if (c2) + *c2 = &eout->c2; + + if (c3) + *c3 = &eout->c3; +} + +void wd_sm2_get_dec_out_params(struct wd_ecc_out *out, + struct wd_dtb **plaintext) +{ + struct wd_sm2_dec_out *dout = (void *)out; + + if (!dout) { + WD_ERR("invalid: input NULL in get sm2 dec out!\n"); + return; + } + + if (plaintext) + *plaintext = &dout->plaintext; +} + + +struct wd_ecc_in *wd_ecdsa_new_sign_in(handle_t sess, + struct wd_dtb *dgst, + struct wd_dtb *k) +{ + return new_sign_in((struct wd_ecc_sess *)sess, dgst, k, NULL, 1); +} + +struct wd_ecc_out *wd_ecdsa_new_sign_out(handle_t sess) +{ + return wd_ecc_new_sign_out((void *)sess); +} + +void wd_ecdsa_get_sign_out_params(struct wd_ecc_out *out, + struct wd_dtb **r, struct wd_dtb **s) +{ + return get_sign_out_params(out, r, s); +} + +struct wd_ecc_in *wd_ecdsa_new_verf_in(handle_t sess, + struct wd_dtb *dgst, + struct wd_dtb *r, + struct wd_dtb *s) +{ + return new_verf_in(sess, dgst, r, s, NULL, 1); +} + +int wd_do_ecc_async(handle_t sess, struct wd_ecc_req *req) +{ + struct wd_ctx_config_internal *config = &wd_ecc_setting.config; + handle_t h_sched_ctx = wd_ecc_setting.sched.h_sched_ctx; + struct wd_ecc_sess *sess_t = (struct wd_ecc_sess *)sess; + struct wd_ecc_msg *msg = NULL; + struct wd_ctx_internal *ctx; + int ret, mid; + int idx; + + if (unlikely(!req || !sess || !req->cb)) { + WD_ERR("invalid: input parameter NULL!\n"); + return -WD_EINVAL; + } + + idx = wd_ecc_setting.sched.pick_next_ctx(h_sched_ctx, + sess_t->sched_key, + CTX_MODE_ASYNC); + ret = wd_check_ctx(config, CTX_MODE_ASYNC, idx); + if (ret) + return ret; + + wd_dfx_msg_cnt(config->msg_cnt, WD_CTX_CNT_NUM, idx); + ctx = config->ctxs + idx; + + mid = wd_get_msg_from_pool(&wd_ecc_setting.pool, idx, (void **)&msg); + if (mid < 0) + return -WD_EBUSY; + + ret = fill_ecc_msg(msg, req, (struct wd_ecc_sess *)sess); + if (ret) + goto fail_with_msg; + msg->tag = mid; + + ret = wd_ecc_setting.driver->send(ctx->ctx, msg); + if (unlikely(ret)) { + if (ret != -WD_EBUSY) + WD_ERR("failed to send ecc BD, hw is err!\n"); + + goto fail_with_msg; + } + + ret = wd_add_task_to_async_queue(&wd_ecc_env_config, idx); + if (ret) + goto fail_with_msg; + + return 0; + +fail_with_msg: + wd_put_msg_to_pool(&wd_ecc_setting.pool, idx, mid); + return ret; +} + +struct wd_ecc_msg *wd_ecc_get_msg(__u32 idx, __u32 tag) +{ + return wd_find_msg_in_pool(&wd_ecc_setting.pool, idx, tag); +} + +int wd_ecc_poll_ctx(__u32 idx, __u32 expt, __u32 *count) +{ + struct wd_ctx_config_internal *config = &wd_ecc_setting.config; + struct wd_ecc_msg recv_msg, *msg; + struct wd_ctx_internal *ctx; + struct wd_ecc_req *req; + __u32 rcv_cnt = 0; + __u32 tmp = expt; + int ret; + + if (unlikely(!count)) { + WD_ERR("invalid: param count is NULL!\n"); + return -WD_EINVAL; + } + + *count = 0; + + ret = wd_check_ctx(config, CTX_MODE_ASYNC, idx); + if (ret) + return ret; + + ctx = config->ctxs + idx; + + do { + ret = wd_ecc_setting.driver->recv(ctx->ctx, &recv_msg); + if (ret == -WD_EAGAIN) { + return ret; + } else if (ret < 0) { + WD_ERR("failed to async recv, ret = %d!\n", ret); + *count = rcv_cnt; + wd_put_msg_to_pool(&wd_ecc_setting.pool, idx, + recv_msg.tag); + return ret; + } + rcv_cnt++; + msg = wd_find_msg_in_pool(&wd_ecc_setting.pool, idx, + recv_msg.tag); + if (!msg) { + WD_ERR("failed to get msg from pool!\n"); + return -WD_EINVAL; + } + + msg->req.dst_bytes = recv_msg.req.dst_bytes; + msg->req.status = recv_msg.result; + req = &msg->req; + req->cb(req); + wd_put_msg_to_pool(&wd_ecc_setting.pool, idx, recv_msg.tag); + *count = rcv_cnt; + } while (--tmp); + + return ret; +} + +int wd_ecc_poll(__u32 expt, __u32 *count) +{ + handle_t h_sched_sess = wd_ecc_setting.sched.h_sched_ctx; + + if (unlikely(!count)) { + WD_ERR("invalid: ecc poll param count is NULL!\n"); + return -WD_EINVAL; + } + + return wd_ecc_setting.sched.poll_policy(h_sched_sess, expt, count); +} + +static const struct wd_config_variable table[] = { + { .name = "WD_ECC_CTX_NUM", + .def_val = "sync:2@0,async:2@0", + .parse_fn = wd_parse_ctx_num + }, + { .name = "WD_ECC_ASYNC_POLL_EN", + .def_val = "0", + .parse_fn = wd_parse_async_poll_en + } +}; + +static const struct wd_alg_ops wd_ecc_ops = { + .alg_name = "sm2", + .op_type_num = 1, + .alg_init = wd_ecc_init, + .alg_uninit = wd_ecc_uninit, + .alg_poll_ctx = wd_ecc_poll_ctx +}; + +int wd_ecc_env_init(struct wd_sched *sched) +{ + wd_ecc_env_config.sched = sched; + + return wd_alg_env_init(&wd_ecc_env_config, table, + &wd_ecc_ops, ARRAY_SIZE(table), NULL); +} + +void wd_ecc_env_uninit(void) +{ + return wd_alg_env_uninit(&wd_ecc_env_config, &wd_ecc_ops); +} + +int wd_ecc_ctx_num_init(__u32 node, __u32 type, __u32 num, __u8 mode) +{ + struct wd_ctx_attr ctx_attr; + int ret; + + ret = wd_set_ctx_attr(&ctx_attr, node, CTX_TYPE_INVALID, mode, num); + if (ret) + return ret; + + return wd_alg_env_init(&wd_ecc_env_config, table, + &wd_ecc_ops, ARRAY_SIZE(table), &ctx_attr); +} + +void wd_ecc_ctx_num_uninit(void) +{ + return wd_alg_env_uninit(&wd_ecc_env_config, &wd_ecc_ops); +} + +int wd_ecc_get_env_param(__u32 node, __u32 type, __u32 mode, + __u32 *num, __u8 *is_enable) +{ + struct wd_ctx_attr ctx_attr; + int ret; + + ret = wd_set_ctx_attr(&ctx_attr, node, CTX_TYPE_INVALID, mode, 0); + if (ret) + return ret; + + return wd_alg_get_env_param(&wd_ecc_env_config, + ctx_attr, num, is_enable); +} diff --git a/uadk/wd_mempool.c b/uadk/wd_mempool.c new file mode 100644 index 0000000..b27d28c --- /dev/null +++ b/uadk/wd_mempool.c @@ -0,0 +1,1016 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. + * Copyright 2020-2021 Linaro ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "wd.h" + +#define SYSFS_NODE_PATH "/sys/devices/system/node/node" +#define MAX_HP_STR_SIZE 64 +#define HUGETLB_FLAG_ENCODE_SHIFT 26 + +#define BITS_PER_LONG ((unsigned int)sizeof(unsigned long) * 8) +#define BITS_TO_LONGS(bits) \ + (((bits) + BITS_PER_LONG - 1) / BITS_PER_LONG) +#define BIT_MASK(nr) ((unsigned long)(1) << ((nr) % BITS_PER_LONG)) +#define BIT_WORD(nr) ((nr) / BITS_PER_LONG) +#define BITMAP_FIRST_WORD_MASK(start) \ + (~0UL << ((start) & (BITS_PER_LONG - 1))) + +#define wd_round_mask(x, y) ((__typeof__(x))((y)-1)) +#define round_down(x, y) ((x) & ~wd_round_mask(x, y)) +#define WD_MEMPOOL_BLOCK_SIZE ((unsigned long)1 << 12) +#define WD_MEMPOOL_SIZE_MASK (WD_MEMPOOL_BLOCK_SIZE - 1) +#define WD_HUNDRED 100 +#define PAGE_SIZE_OFFSET 10 + +struct wd_lock { + __u32 lock; +}; + +static inline void wd_spinlock(struct wd_lock *lock) +{ + while (__atomic_test_and_set(&lock->lock, __ATOMIC_ACQUIRE)) + while (__atomic_load_n(&lock->lock, __ATOMIC_RELAXED)); +} + +static inline void wd_unspinlock(struct wd_lock *lock) +{ + __atomic_clear(&lock->lock, __ATOMIC_RELEASE); +} + +struct wd_ref { + __u32 ref; +}; + +/* + * wd_atomic_test_add - add unless the number is already a given value + * @ref: pointer of type struct wd_ref + * @a: the amount to add to ref->ref... + * @u: ...unless ref->ref is equal to u. + * + * Return number of ref->ref if successful; On error, u is returned. + */ +static inline int wd_atomic_test_add(struct wd_ref *ref, int a, int u) +{ + int c; + + do { + c = __atomic_load_n(&ref->ref, __ATOMIC_RELAXED); + if (c == u) + break; + } while (! __atomic_compare_exchange_n(&ref->ref, &c, c + a, true, + __ATOMIC_RELAXED, __ATOMIC_RELAXED)); + + return c; +} + +static inline void wd_atomic_add(struct wd_ref *ref, int a) +{ + __atomic_add_fetch(&ref->ref, a, __ATOMIC_RELAXED); +} + +static inline void wd_atomic_sub(struct wd_ref *ref, int a) +{ + __atomic_sub_fetch(&ref->ref, a, __ATOMIC_RELAXED); +} + +static inline int wd_atomic_load(struct wd_ref *ref) +{ + return __atomic_load_n(&ref->ref, __ATOMIC_RELAXED); +} + +/* + * one memzone may include some continuous block in mempool + * @addr: Base address of blocks in this memzone + * @blk_num: Number of blocks in this memzone + * @begin: Begin position in mempool bitmap + * @end: End position in mempool bitmap + */ +struct memzone { + void *addr; + size_t blk_num; + size_t begin; + size_t end; + TAILQ_ENTRY(memzone) node; +}; +TAILQ_HEAD(memzone_list, memzone); + +/* + * @blk_elem: All the block unit addrs saved in blk_elem + * @depth: The block pool deph, stack depth + * @top: The stack top pos for blk_elem + * @blk_size: The size of one block + * @mp: Record from which mempool + * @mz_list: List of memzone allocated from mempool + * @free_block_num: Number of free blocks currently + * @lock: lock of blkpool + * @ref: ref of blkpool + */ +struct blkpool { + void **blk_elem; + size_t depth; + size_t top; + size_t blk_size; + struct mempool *mp; + struct memzone_list mz_list; + unsigned long free_block_num; + struct wd_lock lock; + struct wd_ref ref; +}; + +struct sys_hugepage_config { + /* unit is Byte */ + unsigned long page_size; + size_t total_num; + size_t free_num; + TAILQ_ENTRY(sys_hugepage_config) node; +}; +TAILQ_HEAD(sys_hugepage_list, sys_hugepage_config); + +struct bitmap { + unsigned long *map; + unsigned long bits; + unsigned long map_byte; +}; + +struct mempool { + enum wd_page_type page_type; + unsigned long page_size; + unsigned int page_num; + unsigned long blk_size; + unsigned int blk_num; + /* numa node id */ + int node; + /* fd for page pin */ + int fd; + int mp_ref; + void *addr; + size_t size; + size_t real_size; + struct bitmap *bitmap; + /* use self-define lock to avoid to use pthread lib in libwd */ + struct wd_lock lock; + struct wd_ref ref; + struct sys_hugepage_list hp_list; + unsigned long free_blk_num; +}; + +/* + * This function is copied from kernel head file. It finds first bit in word. + * @word: The word to search + * + * Undefined if no bit exists, so code should check against 0 first. + */ +static __always_inline unsigned long wd_ffs(unsigned long target_word) +{ + unsigned long word = target_word; + int num = 0; + + if ((word & 0xffffffff) == 0) { + num += 32; + word >>= 32; + } + + if ((word & 0xffff) == 0) { + num += 16; + word >>= 16; + } + if ((word & 0xff) == 0) { + num += 8; + word >>= 8; + } + if ((word & 0xf) == 0) { + num += 4; + word >>= 4; + } + if ((word & 0x3) == 0) { + num += 2; + word >>= 2; + } + if ((word & 0x1) == 0) + num += 1; + return num; +} + +static struct bitmap *create_bitmap(int bits) +{ + struct bitmap *bm; + + bm = calloc(1, sizeof(*bm)); + if (!bm) { + WD_ERR("failed to alloc memory for bitmap!\n"); + return NULL; + } + + bm->map = calloc(BITS_TO_LONGS(bits), sizeof(unsigned long)); + if (!bm->map) { + WD_ERR("failed to alloc memory for bitmap map!\n"); + free(bm); + return NULL; + } + + bm->bits = bits; + bm->map_byte = BITS_TO_LONGS(bits); + + return bm; +} + +static void destroy_bitmap(struct bitmap *bm) +{ + free(bm->map); + free(bm); +} + +static unsigned long _find_next_bit(unsigned long *map, unsigned long bits, + unsigned long begin_position, + unsigned long invert) +{ + unsigned long tmp, mask, next_bit; + unsigned long start = begin_position; + + if (start >= bits) + return bits; + + tmp = map[start / BITS_PER_LONG]; + tmp ^= invert; + + mask = BITMAP_FIRST_WORD_MASK(start); + tmp &= mask; + start = round_down(start, BITS_PER_LONG); + + while (!tmp) { + start += BITS_PER_LONG; + if (start > bits) + return bits; + + tmp = map[start / BITS_PER_LONG]; + tmp ^= invert; + } + + next_bit = start + wd_ffs(tmp); + return MIN(next_bit, bits); +} + +static unsigned long find_next_zero_bit(struct bitmap *bm, unsigned long start) +{ + return _find_next_bit(bm->map, bm->bits, start, ~0UL); +} + +static void set_bit(struct bitmap *bm, unsigned int pos) +{ + unsigned long *map = bm->map; + unsigned long mask = BIT_MASK(pos); + unsigned long *p = map + BIT_WORD(pos); + + *p |= mask; +} + +static void clear_bit(struct bitmap *bm, unsigned int pos) +{ + unsigned long *map = bm->map; + unsigned long mask = BIT_MASK(pos); + unsigned long *p = map + BIT_WORD(pos); + + *p &= ~mask; +} + +static int test_bit(struct bitmap *bm, unsigned int nr) +{ + unsigned long *p = bm->map + BIT_WORD(nr); + unsigned long mask = BIT_MASK(nr); + + return !(*p & mask); +} + +inline static size_t wd_get_page_size(void) +{ + return sysconf(_SC_PAGESIZE); +} + +void *wd_block_alloc(handle_t blkpool) +{ + struct blkpool *bp = (struct blkpool*)blkpool; + void *p; + + if (!bp) { + WD_ERR("invalid: block pool is NULL!\n"); + return NULL; + } + + if (!wd_atomic_test_add(&bp->ref, 1, 0)) { + WD_ERR("failed to alloc block, block pool is busy now!\n"); + return NULL; + } + + wd_spinlock(&bp->lock); + if (bp->top > 0) { + bp->top--; + bp->free_block_num--; + p = bp->blk_elem[bp->top]; + wd_unspinlock(&bp->lock); + return p; + } + + wd_unspinlock(&bp->lock); + wd_atomic_sub(&bp->ref, 1); + + return NULL; +} + +void wd_block_free(handle_t blkpool, void *addr) +{ + struct blkpool *bp = (struct blkpool*)blkpool; + + if (!bp || !addr) + return; + + wd_spinlock(&bp->lock); + if (bp->top < bp->depth) { + bp->blk_elem[bp->top] = addr; + bp->top++; + bp->free_block_num++; + wd_unspinlock(&bp->lock); + wd_atomic_sub(&bp->ref, 1); + return; + } + + wd_unspinlock(&bp->lock); +} + +static int alloc_memzone(struct blkpool *bp, void *addr, size_t blk_num, + size_t begin, size_t end) +{ + struct memzone *zone; + + zone = calloc(1, sizeof(struct memzone)); + if (!zone) { + WD_ERR("failed to alloc memory for memzone!\n"); + return -WD_ENOMEM; + } + + zone->addr = addr; + zone->blk_num = blk_num; + zone->begin = begin; + zone->end = end; + TAILQ_INSERT_TAIL(&bp->mz_list, zone, node); + + return 0; +} + +static void free_mem_to_mempool_nolock(struct blkpool *bp) +{ + struct mempool *mp = bp->mp; + struct memzone *iter; + size_t blks; + int i; + + while ((iter = TAILQ_LAST(&bp->mz_list, memzone_list))) { + for (i = iter->begin; i <= iter->end; i++) + clear_bit(mp->bitmap, i); + blks = iter->end - iter->begin + 1; + mp->free_blk_num += blks; + mp->real_size += blks * mp->blk_size; + + TAILQ_REMOVE(&bp->mz_list, iter, node); + free(iter); + } +} + +static void free_mem_to_mempool(struct blkpool *bp) +{ + struct mempool *mp = bp->mp; + + wd_spinlock(&mp->lock); + free_mem_to_mempool_nolock(bp); + wd_unspinlock(&mp->lock); +} + +static int check_mempool_real_size(struct mempool *mp, struct blkpool *bp) +{ + if (bp->blk_size * bp->depth > mp->real_size) { + WD_ERR("invalid: mempool size is too small: %lu!\n", + mp->real_size); + return -WD_ENOMEM; + } + + return 0; +} + +static int alloc_block_from_mempool(struct mempool *mp, + struct blkpool *bp, + int pos, + int mem_combined_num, + int mem_splited_num) +{ + int pos_last = pos; + int pos_first; + int i, ret; + + do { + pos_first = find_next_zero_bit(mp->bitmap, pos_last); + if (pos_first == mp->bitmap->bits) { + WD_ERR("failed to find free block from mempool!\n"); + return -WD_ENOMEM; + } + + pos_last = pos_first; + for (i = 0; i < mem_combined_num - 1; i++) + if (!test_bit(mp->bitmap, ++pos_last)) + break; + } while (i != mem_combined_num - 1); + + for (i = pos_last; i >= pos_first; i--) + set_bit(mp->bitmap, i); + + ret = alloc_memzone(bp, mp->addr + pos_first * mp->blk_size, + mem_splited_num, pos_first, pos_last); + if (ret < 0) + goto err_clear_bit; + + return pos_last; + +err_clear_bit: + for (i = pos_last; i >= pos_first; i--) + clear_bit(mp->bitmap, i); + return -WD_ENOMEM; +} + +/* In this case, multiple blocks are in one mem block */ +static int alloc_mem_multi_in_one(struct mempool *mp, struct blkpool *bp) +{ + int mem_splited_num = mp->blk_size / bp->blk_size; + int blk_num = bp->depth; + int ret = -WD_ENOMEM; + int pos = 0; + + wd_spinlock(&mp->lock); + if (check_mempool_real_size(mp, bp)) + goto err_check_size; + + while (blk_num > 0) { + ret = alloc_block_from_mempool(mp, bp, pos, 1, + MIN(blk_num, mem_splited_num)); + if (ret < 0) + goto err_free_memzone; + + mp->free_blk_num--; + mp->real_size -= mp->blk_size; + blk_num -= mem_splited_num; + pos = ret; + } + + wd_unspinlock(&mp->lock); + return 0; + +err_free_memzone: + free_mem_to_mempool_nolock(bp); +err_check_size: + wd_unspinlock(&mp->lock); + return ret; +} + +/* + * In this case, multiple continuous mem blocks should be allocated for one + * block in blkpool + */ +static int alloc_mem_one_need_multi(struct mempool *mp, struct blkpool *bp) +{ + int mem_combined_num = bp->blk_size / mp->blk_size + + (bp->blk_size % mp->blk_size ? 1 : 0); + int blk_num = bp->depth; + int ret = -WD_ENOMEM; + int pos = 0; + + wd_spinlock(&mp->lock); + if (check_mempool_real_size(mp, bp)) + goto err_check_size; + + while (blk_num > 0) { + ret = alloc_block_from_mempool(mp, bp, pos, + mem_combined_num, 1); + if (ret < 0) + goto err_free_memzone; + + pos = ret; + blk_num--; + mp->free_blk_num -= mem_combined_num; + mp->real_size -= mp->blk_size * mem_combined_num; + } + + wd_unspinlock(&mp->lock); + return 0; + +err_free_memzone: + free_mem_to_mempool_nolock(bp); +err_check_size: + wd_unspinlock(&mp->lock); + return ret; +} + +static int alloc_mem_from_mempool(struct mempool *mp, struct blkpool *bp) +{ + TAILQ_INIT(&bp->mz_list); + + if (mp->blk_size >= bp->blk_size) + return alloc_mem_multi_in_one(mp, bp); + + return alloc_mem_one_need_multi(mp, bp); +} + +static int init_blkpool_elem(struct blkpool *bp) +{ + struct memzone *iter; + int idx = 0; + int i; + + bp->blk_elem = calloc(bp->depth, sizeof(void *)); + if (!bp->blk_elem) { + WD_ERR("failed to alloc memory for blk_elem!\n"); + return -WD_ENOMEM; + } + + TAILQ_FOREACH(iter, &bp->mz_list, node) + for (i = 0; i < iter->blk_num; i++) + bp->blk_elem[idx++] = iter->addr + i * bp->blk_size; + + return 0; +} + +handle_t wd_blockpool_create(handle_t mempool, size_t block_size, + size_t block_num) +{ + struct mempool *mp = (struct mempool*)mempool; + struct blkpool *bp; + int ret; + + if (!mp || !block_size || !block_num) { + WD_ERR("invalid: mempool is NULL or block param is 0!\n"); + return (handle_t)(-WD_EINVAL); + } + + if (!wd_atomic_test_add(&mp->ref, 1, 0)) { + WD_ERR("failed to create blockpool, mempool is busy now!\n"); + return (handle_t)(-WD_EBUSY); + } + + bp = calloc(1, sizeof(struct blkpool)); + if (!bp) { + WD_ERR("failed to alloc memory for blkpool!\n"); + return (handle_t)(-WD_ENOMEM); + } + + bp->top = block_num; + bp->depth = block_num; + bp->blk_size = block_size; + bp->free_block_num = block_num; + bp->mp = mp; + + ret = alloc_mem_from_mempool(mp, bp); + if (ret < 0) + goto err_free_bp; + + ret = init_blkpool_elem(bp); + if (ret < 0) + goto err_free_mem; + + wd_atomic_add(&bp->ref, 1); + return (handle_t)bp; + +err_free_mem: + free_mem_to_mempool(bp); +err_free_bp: + free(bp); + wd_atomic_sub(&mp->ref, 1); + return (handle_t)(-WD_ENOMEM); +} + +void wd_blockpool_destroy(handle_t blkpool) +{ + struct blkpool *bp = (struct blkpool *)blkpool; + struct mempool *mp; + + if (!bp) { + WD_ERR("invalid: blkpool is NULL!\n"); + return; + } + + mp = bp->mp; + wd_atomic_sub(&bp->ref, 1); + while (wd_atomic_load(&bp->ref)) + sched_yield(); + + free_mem_to_mempool(bp); + free(bp->blk_elem); + free(bp); + wd_atomic_sub(&mp->ref, 1); +} + +static int get_value_from_sysfs(const char *path, ssize_t path_size) +{ + char buf[MAX_ATTR_STR_SIZE] = {'\0'}; + char dev_path[PATH_MAX]; + char *ptrRet = NULL; + ssize_t size; + int fd, ret; + + ptrRet = realpath(path, dev_path); + if (!ptrRet) { + WD_ERR("failed to resolve path: %s!\n", path); + return -WD_ENODEV; + } + + fd = open(dev_path, O_RDONLY, 0); + if (fd < 0) { + WD_ERR("failed to open %s!\n", dev_path); + goto err_open; + } + + size = read(fd, buf, MAX_ATTR_STR_SIZE - 1); + if (size <= 0) { + WD_ERR("failed to read %s!\n", dev_path); + goto err_read; + } + + close(fd); + + ret = strtol(buf, NULL, 10); + if (errno == ERANGE) { + WD_ERR("failed to strtol %s, out of range!\n", buf); + goto err_read; + } + + return ret; + +err_read: + close(fd); +err_open: + return -errno; +} + +/* hp_dir is e.g. /sys/devices/system/node/nodex/hugepages/hugepages-64kB */ +static int get_hugepage_info_per_type(const char *hugepage_path, int path_size, + struct dirent *hp_dir, struct sys_hugepage_config *cfg) +{ + char path[MAX_ATTR_STR_SIZE]; + char *name = hp_dir->d_name; + unsigned long size; + char *size_pos; + int ret; + + size_pos = index(name, '-'); + if (!size_pos) { + WD_ERR("failed to resolve dir name: %s!\n", name); + return -WD_EINVAL; + } + + size_pos++; + + errno = 0; + size = strtol(size_pos, NULL, 10); + if (errno) { + WD_ERR("failed to resolve size pos to number: %s!\n", size_pos); + return -errno; + } + cfg->page_size = size << PAGE_SIZE_OFFSET; + + ret = snprintf(path, sizeof(path), "%s/%s/nr_hugepages", hugepage_path, + name); + if (ret < 0) { + WD_ERR("failed to get nr hugepages path!\n"); + return -WD_EINVAL; + } + + ret = get_value_from_sysfs(path, MAX_ATTR_STR_SIZE); + if (ret < 0) + return ret; + + cfg->total_num = ret; + + ret = snprintf(path, sizeof(path), "%s/%s/free_hugepages", + hugepage_path, name); + if (ret < 0) { + WD_ERR("failed to get free hugepages path!\n"); + return -WD_EINVAL; + } + + ret = get_value_from_sysfs(path, MAX_ATTR_STR_SIZE); + if (ret < 0) + return ret; + cfg->free_num = ret; + + return 0; +} + +static void put_hugepage_info(struct mempool *mp) +{ + struct sys_hugepage_config *tmp; + + while ((tmp = TAILQ_LAST(&mp->hp_list, sys_hugepage_list))) { + TAILQ_REMOVE(&mp->hp_list, tmp, node); + free(tmp); + } +} + +/* This function also sorts hugepage from small to big */ +static int get_hugepage_info(struct mempool *mp) +{ + struct sys_hugepage_config *tmp, *iter; + char hugepage_path[MAX_HP_STR_SIZE]; + struct dirent *hp_dir; + DIR *dir; + int ret; + + ret = snprintf(hugepage_path, sizeof(hugepage_path), "%s%d/hugepages", + SYSFS_NODE_PATH, mp->node); + if (ret < 0) { + WD_ERR("failed to get hugepages path!\n"); + return -WD_EINVAL; + } + + dir = opendir(hugepage_path); + if (!dir) { + WD_ERR("failed to open %s\n!", hugepage_path); + return -errno; + } + + TAILQ_INIT(&mp->hp_list); + for (hp_dir = readdir(dir); hp_dir != NULL; hp_dir = readdir(dir)) { + if (!strncmp(hp_dir->d_name, ".", LINUX_CRTDIR_SIZE) || + !strncmp(hp_dir->d_name, "..", LINUX_PRTDIR_SIZE)) + continue; + + tmp = calloc(1, sizeof(*tmp)); + if (!tmp) { + WD_ERR("failed to calloc for sys_hugepage_config!\n"); + goto err_free_list; + } + ret = get_hugepage_info_per_type(hugepage_path, MAX_HP_STR_SIZE, + hp_dir, tmp); + if (ret < 0) + goto err_free; + + /* list: page size small -> big */ + TAILQ_FOREACH(iter, &mp->hp_list, node) { + if (tmp->page_size < iter->page_size) { + TAILQ_INSERT_BEFORE(iter, tmp, node); + break; + } + } + + if (!iter) + TAILQ_INSERT_TAIL(&mp->hp_list, tmp, node); + } + + closedir(dir); + + return 0; + +err_free: + free(tmp); +err_free_list: + put_hugepage_info(mp); + + closedir(dir); + return -WD_EIO; +} + +static int mbind_memory(void *addr, size_t size, int node) +{ + unsigned long max_node = numa_max_node() + 2; + unsigned long node_mask; + int ret = 0; + + node_mask = 1U << (unsigned int)node; + ret = mbind(addr, size, MPOL_BIND, &node_mask, max_node, 0); + if (ret < 0) { + WD_ERR("failed to mbind memory, ret is %d!\n", ret); + return ret; + } + + return ret; +} + +static int alloc_mem_from_hugepage(struct mempool *mp) +{ + struct sys_hugepage_config *iter; + unsigned long bits = sizeof(iter->page_size) * 8; + size_t page_num, real_size; + unsigned long flags = 0; + void *p; + int ret; + + ret = get_hugepage_info(mp); + if (ret < 0) + return ret; + + /* find proper hugepage: use small huge page if possible */ + TAILQ_FOREACH(iter, &mp->hp_list, node) + if (iter->page_size * iter->free_num >= mp->size) + break; + + if (!iter) { + WD_ERR("failed to find proper hugepage!\n"); + ret = -WD_ENOMEM; + goto err_put_info; + } + + /* alloc hugepage and bind */ + page_num = mp->size / iter->page_size + + (mp->size % iter->page_size ? 1 : 0); + real_size = page_num * iter->page_size; + /* + * man mmap will tell, flags of mmap can be used to indicate hugepage + * size. In fact, after kernel 3.18, it has been supported. See more + * in kernel header file: linux/include/uapi/linux/mman.h. As related + * macro has not been put into glibc, we caculate them here, e.g. + * flags for 64KB is 16 << 26. + */ + flags = _find_next_bit(&iter->page_size, bits, 0, 0UL) << + HUGETLB_FLAG_ENCODE_SHIFT; + p = mmap(NULL, real_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | + MAP_ANONYMOUS | MAP_HUGETLB | flags, -1, 0); + if (p == MAP_FAILED) { + WD_ERR("failed to allocate huge page!\n"); + ret = -WD_ENOMEM; + goto err_put_info; + } + + ret = mbind_memory(p, real_size, mp->node); + if (ret < 0) + goto err_unmap; + + mp->page_type = WD_HUGE_PAGE; + mp->page_size = iter->page_size; + mp->page_num = page_num; + mp->addr = p; + mp->real_size = real_size; + + return 0; + +err_unmap: + munmap(p, real_size); +err_put_info: + put_hugepage_info(mp); + return ret; +} + +static void free_hugepage_mem(struct mempool *mp) +{ + munmap(mp->addr, mp->page_size * mp->page_num); + put_hugepage_info(mp); +} + +static int init_mempool(struct mempool *mp) +{ + /* size of mp should align to 4KB */ + int bits = mp->size / mp->blk_size; + struct bitmap *bm; + + bm = create_bitmap(bits); + if (!bm) + return -WD_ENOMEM; + mp->bitmap = bm; + mp->free_blk_num = bits; + mp->blk_num = bits; + + return 0; +} + +static void uninit_mempool(struct mempool *mp) +{ + destroy_bitmap(mp->bitmap); + mp->bitmap = NULL; +} + +handle_t wd_mempool_create(size_t size, int node) +{ + struct mempool *mp; + size_t tmp = size; + int ret; + + if (!tmp || node < 0 || node > numa_max_node()) { + WD_ERR("invalid: numa node is %d, size is %ld!\n", node, tmp); + return (handle_t)(-WD_EINVAL); + } + + if (WD_MEMPOOL_SIZE_MASK & tmp) + tmp += WD_MEMPOOL_BLOCK_SIZE - (WD_MEMPOOL_SIZE_MASK & tmp); + + mp = calloc(1, sizeof(*mp)); + if (!mp) { + WD_ERR("failed to alloc memory for mempool!\n"); + return (handle_t)(-WD_ENOMEM); + } + + mp->node = node; + mp->size = tmp; + mp->blk_size = WD_MEMPOOL_BLOCK_SIZE; + + ret = alloc_mem_from_hugepage(mp); + if (ret < 0) + goto free_pool; + + ret = init_mempool(mp); + if (ret < 0) + goto free_pool_memory; + + wd_atomic_add(&mp->ref, 1); + return (handle_t)mp; + +free_pool_memory: + free_hugepage_mem(mp); +free_pool: + free(mp); + return (handle_t)(-WD_ENOMEM); +} + +void wd_mempool_destroy(handle_t mempool) +{ + struct mempool *mp = (struct mempool *)mempool; + + if (!mp) { + WD_ERR("invalid: mempool is NULL!\n"); + return; + } + + wd_atomic_sub(&mp->ref, 1); + while(wd_atomic_load(&mp->ref)); + uninit_mempool(mp); + free_hugepage_mem(mp); + free(mp); +} + +void wd_mempool_stats(handle_t mempool, struct wd_mempool_stats *stats) +{ + struct mempool *mp = (struct mempool *)mempool; + + if (!mp) { + WD_ERR("invalid: mempool is NULL!\n"); + return; + } + + if (!stats) { + WD_ERR("invalid: mempool stats is NULL!\n"); + return; + } + + wd_spinlock(&mp->lock); + + stats->page_type = mp->page_type; + stats->page_size = mp->page_size; + stats->page_num = mp->page_num; + stats->blk_size = mp->blk_size; + stats->blk_num = mp->blk_num; + stats->free_blk_num = mp->free_blk_num; + stats->blk_usage_rate = (stats->blk_num - mp->free_blk_num) / + stats->blk_num * WD_HUNDRED; + + wd_unspinlock(&mp->lock); +} + +void wd_blockpool_stats(handle_t blkpool, struct wd_blockpool_stats *stats) +{ + struct blkpool *bp = (struct blkpool*)blkpool; + unsigned long size = 0; + struct memzone *iter; + + if (!bp || !stats) { + WD_ERR("invalid: blkpool or stats is NULL!\n"); + return; + } + + wd_spinlock(&bp->lock); + + stats->block_size = bp->blk_size; + stats->block_num = bp->depth; + stats->free_block_num = bp->free_block_num; + stats->block_usage_rate = (bp->depth - bp->free_block_num) / + bp->depth * WD_HUNDRED; + + TAILQ_FOREACH(iter, &bp->mz_list, node) + size += (iter->end - iter->begin + 1) * bp->mp->blk_size; + + if (!size) { + WD_ERR("invalid: blkpool size is zero!\n"); + wd_unspinlock(&bp->lock); + return; + } + + stats->mem_waste_rate = (size - bp->blk_size * bp->depth) / + size * WD_HUNDRED; + + wd_unspinlock(&bp->lock); +} diff --git a/uadk/wd_rsa.c b/uadk/wd_rsa.c new file mode 100644 index 0000000..489833e --- /dev/null +++ b/uadk/wd_rsa.c @@ -0,0 +1,1148 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. + * Copyright 2020-2021 Linaro ltd. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "include/drv/wd_rsa_drv.h" +#include "wd_util.h" + +#define WD_POOL_MAX_ENTRIES 1024 +#define WD_HW_EACCESS 62 + +#define RSA_MAX_KEY_SIZE 512 + +static __thread __u64 balance; + +struct wd_rsa_pubkey { + struct wd_dtb n; + struct wd_dtb e; + __u32 key_size; + void *data[]; +}; + +struct wd_rsa_prikey1 { + struct wd_dtb n; + struct wd_dtb d; + __u32 key_size; + void *data[]; +}; + +/* RSA CRT mode private key */ +struct wd_rsa_prikey2 { + struct wd_dtb p; + struct wd_dtb q; + struct wd_dtb dp; + struct wd_dtb dq; + struct wd_dtb qinv; + __u32 key_size; + void *data[]; +}; + +struct wd_rsa_prikey { + struct wd_rsa_prikey1 pkey1; + struct wd_rsa_prikey2 pkey2; +}; + +/* RSA private key parameter types */ +enum wd_rsa_crt_prikey_para { + WD_CRT_PRIKEY_DQ, + WD_CRT_PRIKEY_DP, + WD_CRT_PRIKEY_QINV, + WD_CRT_PRIKEY_Q, + WD_CRT_PRIKEY_P +}; + +struct wd_rsa_sess { + __u32 alg_type; + __u32 key_size; + struct wd_rsa_pubkey *pubkey; + struct wd_rsa_prikey *prikey; + struct wd_rsa_sess_setup setup; + void *sched_key; +}; + +static struct wd_rsa_setting { + struct wd_ctx_config_internal config; + struct wd_sched sched; + void *sched_ctx; + const struct wd_rsa_driver *driver; + void *priv; + void *dlhandle; + struct wd_async_msg_pool pool; +} wd_rsa_setting; + +struct wd_env_config wd_rsa_env_config; + +#ifdef WD_STATIC_DRV +static void wd_rsa_set_static_drv(void) +{ + wd_rsa_setting.driver = wd_rsa_get_driver(); + if (!wd_rsa_setting.driver) + WD_ERR("failed to get rsa driver!\n"); +} +#else +static void __attribute__((constructor)) wd_rsa_open_driver(void) +{ + wd_rsa_setting.dlhandle = dlopen("libhisi_hpre.so", RTLD_NOW); + if (!wd_rsa_setting.dlhandle) + WD_ERR("failed to open libhisi_hpre.so!\n"); +} + +static void __attribute__((destructor)) wd_rsa_close_driver(void) +{ + if (wd_rsa_setting.dlhandle) + dlclose(wd_rsa_setting.dlhandle); +} +#endif + +void wd_rsa_set_driver(struct wd_rsa_driver *drv) +{ + if (!drv) { + WD_ERR("invalid: rsa drv is NULL!\n"); + return; + } + + wd_rsa_setting.driver = drv; +} + +int wd_rsa_init(struct wd_ctx_config *config, struct wd_sched *sched) +{ + void *priv; + int ret; + + ret = wd_init_param_check(config, sched); + if (ret) + return ret; + + ret = wd_set_epoll_en("WD_RSA_EPOLL_EN", + &wd_rsa_setting.config.epoll_en); + if (ret < 0) + return ret; + + ret = wd_init_ctx_config(&wd_rsa_setting.config, config); + if (ret < 0) + return ret; + + ret = wd_init_sched(&wd_rsa_setting.sched, sched); + if (ret < 0) + goto out; + +#ifdef WD_STATIC_DRV + wd_rsa_set_static_drv(); +#endif + + /* fix me: sadly find we allocate async pool for every ctx */ + ret = wd_init_async_request_pool(&wd_rsa_setting.pool, + config->ctx_num, WD_POOL_MAX_ENTRIES, + sizeof(struct wd_rsa_msg)); + if (ret < 0) + goto out_sched; + + /* initialize ctx related resources in specific driver */ + priv = calloc(1, wd_rsa_setting.driver->drv_ctx_size); + if (!priv) { + ret = -WD_ENOMEM; + goto out_priv; + } + + wd_rsa_setting.priv = priv; + ret = wd_rsa_setting.driver->init(&wd_rsa_setting.config, priv, + wd_rsa_setting.driver->alg_name); + if (ret < 0) { + WD_ERR("failed to init rsa driver, ret = %d!\n", ret); + goto out_init; + } + + return 0; + +out_init: + free(priv); + wd_rsa_setting.priv = NULL; +out_priv: + wd_uninit_async_request_pool(&wd_rsa_setting.pool); +out_sched: + wd_clear_sched(&wd_rsa_setting.sched); +out: + wd_clear_ctx_config(&wd_rsa_setting.config); + return ret; +} + +void wd_rsa_uninit(void) +{ + if (!wd_rsa_setting.priv) { + WD_ERR("invalid: repeat uninit rsa!\n"); + return; + } + + /* driver uninit */ + wd_rsa_setting.driver->exit(wd_rsa_setting.priv); + free(wd_rsa_setting.priv); + wd_rsa_setting.priv = NULL; + + /* uninit async request pool */ + wd_uninit_async_request_pool(&wd_rsa_setting.pool); + + /* unset config, sched, driver */ + wd_clear_sched(&wd_rsa_setting.sched); + wd_clear_ctx_config(&wd_rsa_setting.config); +} + +static int fill_rsa_msg(struct wd_rsa_msg *msg, struct wd_rsa_req *req, + struct wd_rsa_sess *sess) +{ + __u8 *key = NULL; + + if (sess->setup.is_crt) + msg->key_type = WD_RSA_PRIKEY2; + else + msg->key_type = WD_RSA_PRIKEY1; + + memcpy(&msg->req, req, sizeof(*req)); + msg->key_bytes = sess->key_size; + msg->result = WD_EINVAL; + + switch (msg->req.op_type) { + case WD_RSA_SIGN: + key = (__u8 *)sess->prikey; + break; + case WD_RSA_VERIFY: + key = (__u8 *)sess->pubkey; + break; + case WD_RSA_GENKEY: + key = (__u8 *)req->src; + break; + default: + WD_ERR("invalid: rsa msg req op type %u is err!\n", msg->req.op_type); + return -WD_EINVAL; + } + + if (unlikely(!key)) { + WD_ERR("invalid: rsa msg key null!\n"); + return -WD_EINVAL; + } + + if (msg->req.op_type == WD_RSA_SIGN || + msg->req.op_type == WD_RSA_VERIFY) { + if (unlikely(msg->req.src_bytes != sess->key_size)) { + WD_ERR("invalid: sign or verf src_bytes != key_size!\n"); + return -WD_EINVAL; + } + + if (unlikely(req->dst_bytes != sess->key_size)) { + WD_ERR("invalid: req dst bytes %hu is error!\n", req->dst_bytes); + return -WD_EINVAL; + } + } + + msg->key = key; + + return 0; +} + +int wd_do_rsa_sync(handle_t h_sess, struct wd_rsa_req *req) +{ + struct wd_ctx_config_internal *config = &wd_rsa_setting.config; + handle_t h_sched_ctx = wd_rsa_setting.sched.h_sched_ctx; + struct wd_rsa_sess *sess = (struct wd_rsa_sess *)h_sess; + struct wd_msg_handle msg_handle; + struct wd_ctx_internal *ctx; + struct wd_rsa_msg msg; + __u32 idx; + int ret; + + if (unlikely(!h_sess || !req)) { + WD_ERR("invalid: input param NULL!\n"); + return -WD_EINVAL; + } + + idx = wd_rsa_setting.sched.pick_next_ctx(h_sched_ctx, + sess->sched_key, + CTX_MODE_SYNC); + ret = wd_check_ctx(config, CTX_MODE_SYNC, idx); + if (ret) + return ret; + + wd_dfx_msg_cnt(config->msg_cnt, WD_CTX_CNT_NUM, idx); + ctx = config->ctxs + idx; + + memset(&msg, 0, sizeof(struct wd_rsa_msg)); + ret = fill_rsa_msg(&msg, req, sess); + if (unlikely(ret)) + return ret; + + msg_handle.send = wd_rsa_setting.driver->send; + msg_handle.recv = wd_rsa_setting.driver->recv; + + pthread_spin_lock(&ctx->lock); + ret = wd_handle_msg_sync(&msg_handle, ctx->ctx, &msg, &balance, + wd_rsa_setting.config.epoll_en); + pthread_spin_unlock(&ctx->lock); + if (unlikely(ret)) + return ret; + + req->dst_bytes = msg.req.dst_bytes; + req->status = msg.result; + + return GET_NEGATIVE(msg.result); +} + +int wd_do_rsa_async(handle_t sess, struct wd_rsa_req *req) +{ + struct wd_ctx_config_internal *config = &wd_rsa_setting.config; + handle_t h_sched_ctx = wd_rsa_setting.sched.h_sched_ctx; + struct wd_rsa_sess *sess_t = (struct wd_rsa_sess *)sess; + struct wd_rsa_msg *msg = NULL; + struct wd_ctx_internal *ctx; + int ret, mid; + __u32 idx; + + if (unlikely(!req || !sess || !req->cb)) { + WD_ERR("invalid: input param NULL!\n"); + return -WD_EINVAL; + } + + idx = wd_rsa_setting.sched.pick_next_ctx(h_sched_ctx, + sess_t->sched_key, + CTX_MODE_ASYNC); + ret = wd_check_ctx(config, CTX_MODE_ASYNC, idx); + if (ret) + return ret; + + wd_dfx_msg_cnt(config->msg_cnt, WD_CTX_CNT_NUM, idx); + ctx = config->ctxs + idx; + + mid = wd_get_msg_from_pool(&wd_rsa_setting.pool, idx, (void **)&msg); + if (mid < 0) + return -WD_EBUSY; + + ret = fill_rsa_msg(msg, req, (struct wd_rsa_sess *)sess); + if (ret) + goto fail_with_msg; + msg->tag = mid; + + ret = wd_rsa_setting.driver->send(ctx->ctx, msg); + if (unlikely(ret)) { + if (ret != -WD_EBUSY) + WD_ERR("failed to send rsa BD, hw is err!\n"); + + goto fail_with_msg; + } + + ret = wd_add_task_to_async_queue(&wd_rsa_env_config, idx); + if (ret) + goto fail_with_msg; + + return 0; + +fail_with_msg: + wd_put_msg_to_pool(&wd_rsa_setting.pool, idx, mid); + return ret; +} + +struct wd_rsa_msg *wd_rsa_get_msg(__u32 idx, __u32 tag) +{ + return wd_find_msg_in_pool(&wd_rsa_setting.pool, idx, tag); +} + +int wd_rsa_poll_ctx(__u32 idx, __u32 expt, __u32 *count) +{ + struct wd_ctx_config_internal *config = &wd_rsa_setting.config; + struct wd_ctx_internal *ctx; + struct wd_rsa_req *req; + struct wd_rsa_msg recv_msg, *msg; + __u32 rcv_cnt = 0; + __u32 tmp = expt; + int ret; + + if (unlikely(!count)) { + WD_ERR("invalid: param count is NULL!\n"); + return -WD_EINVAL; + } + + *count = 0; + + ret = wd_check_ctx(config, CTX_MODE_ASYNC, idx); + if (ret) + return ret; + + ctx = config->ctxs + idx; + + do { + ret = wd_rsa_setting.driver->recv(ctx->ctx, &recv_msg); + if (ret == -WD_EAGAIN) { + return ret; + } else if (ret < 0) { + WD_ERR("failed to async recv, ret = %d!\n", ret); + wd_put_msg_to_pool(&wd_rsa_setting.pool, idx, + recv_msg.tag); + return ret; + } + rcv_cnt++; + msg = wd_find_msg_in_pool(&wd_rsa_setting.pool, idx, + recv_msg.tag); + if (!msg) { + WD_ERR("failed to get msg from pool!\n"); + return -WD_EINVAL; + } + + msg->req.dst_bytes = recv_msg.req.dst_bytes; + msg->req.status = recv_msg.result; + req = &msg->req; + req->cb(req); + wd_put_msg_to_pool(&wd_rsa_setting.pool, idx, recv_msg.tag); + *count = rcv_cnt; + } while (--tmp); + + return ret; +} + +int wd_rsa_poll(__u32 expt, __u32 *count) +{ + handle_t h_sched_ctx = wd_rsa_setting.sched.h_sched_ctx; + + if (unlikely(!count)) { + WD_ERR("invalid: rsa poll count is NULL!\n"); + return -WD_EINVAL; + } + + return wd_rsa_setting.sched.poll_policy(h_sched_ctx, expt, count); +} + +int wd_rsa_kg_in_data(struct wd_rsa_kg_in *ki, char **data) +{ + if (!ki || !data) { + WD_ERR("invalid: param is NULL!\n"); + return -WD_EINVAL; + } + + *data = (char *)ki->data; + return (int)GEN_PARAMS_SZ(ki->key_size); +} + +int wd_rsa_kg_out_data(struct wd_rsa_kg_out *ko, char **data) +{ + if (!ko || !data) { + WD_ERR("invalid: param is NULL!\n"); + return -WD_EINVAL; + } + + *data = (char *)ko->data; + + return ko->size; +} + +/* Create a RSA key generate operation input with parameter e, p and q */ +struct wd_rsa_kg_in *wd_rsa_new_kg_in(handle_t sess, struct wd_dtb *e, + struct wd_dtb *p, struct wd_dtb *q) +{ + struct wd_rsa_kg_in *kg_in; + struct wd_rsa_sess *c = (struct wd_rsa_sess *)sess; + int kg_in_size; + + if (!c || !e || !p || !q) { + WD_ERR("invalid: sess malloc kg_in memory params err!\n"); + return NULL; + } + + if (!c->key_size || c->key_size > RSA_MAX_KEY_SIZE) { + WD_ERR("invalid: key size err at create kg in!\n"); + return NULL; + } + + if (!e->dsize || e->dsize > c->key_size) { + WD_ERR("invalid: e para err at create kg in!\n"); + return NULL; + } + if (!p->dsize || p->dsize > CRT_PARAM_SZ(c->key_size)) { + WD_ERR("invalid: p para err at create kg in!\n"); + return NULL; + } + if (!q->dsize || q->dsize > CRT_PARAM_SZ(c->key_size)) { + WD_ERR("invalid: q para err at create kg in!\n"); + return NULL; + } + + kg_in_size = GEN_PARAMS_SZ(c->key_size); + kg_in = malloc(kg_in_size + sizeof(*kg_in)); + if (!kg_in) { + WD_ERR("failed to malloc kg_in memory!\n"); + return NULL; + } + memset(kg_in, 0, kg_in_size + sizeof(*kg_in)); + kg_in->key_size = c->key_size; + kg_in->ebytes = e->dsize; + kg_in->pbytes = p->dsize; + kg_in->qbytes = q->dsize; + kg_in->e = (void *)kg_in->data; + kg_in->p = (void *)kg_in->e + c->key_size; + kg_in->q = (void *)kg_in->p + CRT_PARAM_SZ(c->key_size); + + memcpy(kg_in->e, e->data, e->dsize); + memcpy(kg_in->p, p->data, p->dsize); + memcpy(kg_in->q, q->data, q->dsize); + + return kg_in; +} + +void wd_rsa_get_kg_in_params(struct wd_rsa_kg_in *kin, struct wd_dtb *e, + struct wd_dtb *q, struct wd_dtb *p) +{ + if (!kin || !e || !q || !p) { + WD_ERR("invalid: para err at get input parameters key generate!\n"); + return; + } + + e->bsize = kin->key_size; + e->dsize = kin->ebytes; + e->data = (void *)kin->e; + q->bsize = CRT_PARAM_SZ(kin->key_size); + q->dsize = kin->qbytes; + q->data = (void *)kin->q; + p->bsize = CRT_PARAM_SZ(kin->key_size); + p->dsize = kin->pbytes; + p->data = (void *)kin->p; +} + +static void del_kg(void *k) +{ + if (!k) { + WD_ERR("invalid: del key generate params err!\n"); + return; + } + + free(k); +} + +void wd_rsa_del_kg_in(handle_t sess, struct wd_rsa_kg_in *ki) +{ + del_kg(ki); +} + +struct wd_rsa_kg_out *wd_rsa_new_kg_out(handle_t sess) +{ + struct wd_rsa_sess *c = (struct wd_rsa_sess *)sess; + struct wd_rsa_kg_out *kg_out; + int kg_out_size; + __u32 kz; + + if (!c) { + WD_ERR("invalid: sess null at new rsa key gen out!\n"); + return NULL; + } + + kz = c->key_size; + if (!kz || kz > RSA_MAX_KEY_SIZE) { + WD_ERR("invalid: new kg out key size error!\n"); + return NULL; + } + + if (c->setup.is_crt) + kg_out_size = CRT_GEN_PARAMS_SZ(c->key_size); + else + kg_out_size = GEN_PARAMS_SZ(c->key_size); + + kg_out = malloc(kg_out_size + sizeof(*kg_out)); + if (!kg_out) { + WD_ERR("failed to malloc kg_out memory!\n"); + return NULL; + } + + memset(kg_out, 0, kg_out_size + sizeof(*kg_out)); + kg_out->key_size = kz; + kg_out->d = (void *)kg_out->data; + kg_out->n = kg_out->d + kz; + kg_out->size = kg_out_size; + if (c->setup.is_crt) { + kg_out->qinv = (void *)kg_out->n + kz; + kg_out->dq = kg_out->qinv + CRT_PARAM_SZ(kz); + kg_out->dp = kg_out->dq + CRT_PARAM_SZ(kz); + } + + return kg_out; +} + +void wd_rsa_del_kg_out(handle_t sess, struct wd_rsa_kg_out *kout) +{ + if (!kout) { + WD_ERR("invalid: param null at del kg out!\n"); + return; + } + + wd_memset_zero(kout->data, kout->size); + del_kg(kout); +} + +void wd_rsa_get_kg_out_params(struct wd_rsa_kg_out *kout, struct wd_dtb *d, + struct wd_dtb *n) +{ + if (!kout) { + WD_ERR("invalid: input null at get key gen params!\n"); + return; + } + + if (d && kout->d) { + d->bsize = kout->key_size; + d->dsize = kout->dbytes; + d->data = (void *)kout->d; + } + + if (n && kout->n) { + n->bsize = kout->key_size; + n->dsize = kout->nbytes; + n->data = (void *)kout->n; + } +} + +void wd_rsa_get_kg_out_crt_params(struct wd_rsa_kg_out *kout, + struct wd_dtb *qinv, + struct wd_dtb *dq, struct wd_dtb *dp) +{ + if (!kout || !qinv || !dq || !dp) { + WD_ERR("invalid: input null at get key gen crt para!\n"); + return; + } + + if (qinv && kout->qinv) { + qinv->bsize = CRT_PARAM_SZ(kout->key_size); + qinv->dsize = kout->qinvbytes; + qinv->data = (void *)kout->qinv; + } + + if (dq && kout->dq) { + dq->bsize = CRT_PARAM_SZ(kout->key_size); + dq->dsize = kout->dqbytes; + dq->data = (void *)kout->dq; + } + + if (dp && kout->dp) { + dp->bsize = CRT_PARAM_SZ(kout->key_size); + dp->dsize = kout->dpbytes; + dp->data = (void *)kout->dp; + } +} + +void wd_rsa_set_kg_out_crt_psz(struct wd_rsa_kg_out *kout, + size_t qinv_sz, + size_t dq_sz, + size_t dp_sz) +{ + kout->qinvbytes = qinv_sz; + kout->dqbytes = dq_sz; + kout->dpbytes = dp_sz; +} + +void wd_rsa_set_kg_out_psz(struct wd_rsa_kg_out *kout, + size_t d_sz, + size_t n_sz) +{ + kout->dbytes = d_sz; + kout->nbytes = n_sz; +} + +static void init_pkey2(struct wd_rsa_prikey2 *pkey2, __u32 ksz) +{ + __u32 hlf_ksz = CRT_PARAM_SZ(ksz); + + pkey2->dq.data = (char *)pkey2->data; + pkey2->dp.data = pkey2->dq.data + hlf_ksz; + pkey2->q.data = pkey2->dp.data + hlf_ksz; + pkey2->p.data = pkey2->q.data + hlf_ksz; + pkey2->qinv.data = pkey2->p.data + hlf_ksz; + pkey2->dq.bsize = hlf_ksz; + pkey2->dp.bsize = hlf_ksz; + pkey2->q.bsize = hlf_ksz; + pkey2->p.bsize = hlf_ksz; + pkey2->qinv.bsize = hlf_ksz; + pkey2->key_size = ksz; +} + +static void init_pkey1(struct wd_rsa_prikey1 *pkey1, int ksz) +{ + pkey1->d.data = (char *)pkey1->data; + pkey1->n.data = pkey1->d.data + ksz; + pkey1->d.bsize = ksz; + pkey1->n.bsize = ksz; + pkey1->key_size = ksz; +} + +static void init_pubkey(struct wd_rsa_pubkey *pubkey, int ksz) +{ + pubkey->e.data = (char *)pubkey->data; + pubkey->n.data = pubkey->e.data + ksz; + pubkey->e.bsize = ksz; + pubkey->n.bsize = ksz; + pubkey->key_size = ksz; +} + +static int create_sess_key(struct wd_rsa_sess_setup *setup, + struct wd_rsa_sess *sess) +{ + struct wd_rsa_prikey2 *pkey2; + struct wd_rsa_prikey1 *pkey1; + int len; + + if (setup->is_crt) { + len = sizeof(struct wd_rsa_prikey) + + CRT_PARAMS_SZ(sess->key_size); + sess->prikey = malloc(len); + if (!sess->prikey) { + WD_ERR("failed to alloc sess prikey2!\n"); + return -WD_ENOMEM; + } + pkey2 = &sess->prikey->pkey2; + memset(sess->prikey, 0, len); + init_pkey2(pkey2, sess->key_size); + } else { + len = sizeof(struct wd_rsa_prikey) + + GEN_PARAMS_SZ(sess->key_size); + sess->prikey = malloc(len); + if (!sess->prikey) { + WD_ERR("failed to alloc sess prikey1!\n"); + return -WD_ENOMEM; + } + pkey1 = &sess->prikey->pkey1; + memset(sess->prikey, 0, len); + init_pkey1(pkey1, sess->key_size); + } + + len = sizeof(struct wd_rsa_pubkey) + + GEN_PARAMS_SZ(sess->key_size); + sess->pubkey = malloc(len); + if (!sess->pubkey) { + free(sess->prikey); + WD_ERR("failed to alloc sess pubkey!\n"); + return -WD_ENOMEM; + } + + memset(sess->pubkey, 0, len); + init_pubkey(sess->pubkey, sess->key_size); + + return WD_SUCCESS; +} + +static void del_sess_key(struct wd_rsa_sess *sess) +{ + struct wd_rsa_prikey *prk = sess->prikey; + struct wd_rsa_pubkey *pub = sess->pubkey; + + if (!prk || !pub) { + WD_ERR("invalid: del sess key error, prk or pub NULL!\n"); + return; + } + + if (sess->setup.is_crt) + wd_memset_zero(prk->pkey2.data, CRT_PARAMS_SZ(sess->key_size)); + else + wd_memset_zero(prk->pkey1.data, GEN_PARAMS_SZ(sess->key_size)); + free(sess->prikey); + free(sess->pubkey); +} + +static void del_sess(struct wd_rsa_sess *c) +{ + if (c) + free(c); +} + +/* Before initiate this context, we should get a queue from WD */ +handle_t wd_rsa_alloc_sess(struct wd_rsa_sess_setup *setup) +{ + struct wd_rsa_sess *sess; + int ret; + + if (!setup) { + WD_ERR("invalid: alloc rsa sess setup NULL!\n"); + return(handle_t)0; + } + + if (setup->key_bits != 1024 && + setup->key_bits != 2048 && + setup->key_bits != 3072 && + setup->key_bits != 4096) { + WD_ERR("invalid: alloc rsa sess key_bit %u err!\n", setup->key_bits); + return (handle_t)0; + } + + sess = calloc(1, sizeof(struct wd_rsa_sess)); + if (!sess) + return (handle_t)sess; + + memcpy(&sess->setup, setup, sizeof(*setup)); + sess->key_size = setup->key_bits >> BYTE_BITS_SHIFT; + + ret = create_sess_key(setup, sess); + if (ret) { + WD_ERR("failed to create rsa sess keys!\n"); + goto sess_err; + } + + /* Some simple scheduler don't need scheduling parameters */ + sess->sched_key = (void *)wd_rsa_setting.sched.sched_init( + wd_rsa_setting.sched.h_sched_ctx, setup->sched_param); + if (WD_IS_ERR(sess->sched_key)) { + WD_ERR("failed to init session schedule key!\n"); + goto sched_err; + } + + return (handle_t)sess; + +sched_err: + del_sess_key(sess); +sess_err: + free(sess); + return (handle_t)0; +} + +void wd_rsa_free_sess(handle_t sess) +{ + struct wd_rsa_sess *sess_t = (struct wd_rsa_sess *)sess; + + if (!sess_t) { + WD_ERR("invalid: free rsa sess param err!\n"); + return; + } + + if (sess_t->sched_key) + free(sess_t->sched_key); + del_sess_key(sess_t); + del_sess(sess_t); +} + + +bool wd_rsa_is_crt(handle_t sess) +{ + if (!sess) { + WD_ERR("invalid: rsa is crt judge, sess NULL, return false!\n"); + return false; + } + + return ((struct wd_rsa_sess *)sess)->setup.is_crt; +} + +__u32 wd_rsa_get_key_bits(handle_t sess) +{ + if (!sess) { + WD_ERR("invalid: get rsa key bits, sess NULL!\n"); + return 0; + } + + return ((struct wd_rsa_sess *)sess)->setup.key_bits; +} + +int wd_rsa_set_pubkey_params(handle_t sess, struct wd_dtb *e, struct wd_dtb *n) +{ + struct wd_rsa_sess *c = (struct wd_rsa_sess *)sess; + + if (!c || !c->pubkey || !c->pubkey->key_size) { + WD_ERR("invalid: sess NULL in set rsa public key!\n"); + return -WD_EINVAL; + } + + if (e) { + if (!e->dsize || !e->data || e->dsize > c->pubkey->key_size) { + WD_ERR("invalid: e err in set rsa public key!\n"); + return -WD_EINVAL; + } + + c->pubkey->e.dsize = e->dsize; + memset(c->pubkey->e.data, 0, c->pubkey->e.bsize); + memcpy(c->pubkey->e.data, e->data, e->dsize); + } + + if (n) { + if (!n->dsize || !n->data || n->dsize > c->pubkey->key_size) { + WD_ERR("invalid: n err in set rsa public key!\n"); + return -WD_EINVAL; + } + + c->pubkey->n.dsize = n->dsize; + memset(c->pubkey->n.data, 0, c->pubkey->n.bsize); + memcpy(c->pubkey->n.data, n->data, n->dsize); + } + + return WD_SUCCESS; +} + +void wd_rsa_get_pubkey_params(struct wd_rsa_pubkey *pbk, struct wd_dtb **e, + struct wd_dtb **n) +{ + if (!pbk) { + WD_ERR("invalid: input NULL in get rsa public key!\n"); + return; + } + if (e) + *e = &pbk->e; + + if (n) + *n = &pbk->n; +} + +int wd_rsa_set_prikey_params(handle_t sess, struct wd_dtb *d, struct wd_dtb *n) +{ + struct wd_rsa_prikey1 *pkey1; + struct wd_rsa_sess *c = (struct wd_rsa_sess *)sess; + + if (!c || wd_rsa_is_crt(sess) || !c->prikey) { + WD_ERR("invalid: sess err in set rsa private key1!\n"); + return -WD_EINVAL; + } + pkey1 = &c->prikey->pkey1; + if (d) { + if (!d->dsize || !d->data || d->dsize > pkey1->key_size) { + WD_ERR("invalid: d err in set rsa private key1!\n"); + return -WD_EINVAL; + } + + pkey1->d.dsize = d->dsize; + memset(pkey1->d.data, 0, pkey1->d.bsize); + memcpy(pkey1->d.data, d->data, d->dsize); + } + if (n) { + if (!n->dsize || !n->data || n->dsize > pkey1->key_size) { + WD_ERR("invalid: en err in set rsa private key1!\n"); + return -WD_EINVAL; + } + + pkey1->n.dsize = n->dsize; + memset(pkey1->n.data, 0, pkey1->n.bsize); + memcpy(pkey1->n.data, n->data, n->dsize); + } + + return WD_SUCCESS; +} + +void wd_rsa_get_prikey_params(struct wd_rsa_prikey *pvk, struct wd_dtb **d, + struct wd_dtb **n) +{ + struct wd_rsa_prikey1 *pkey1; + + if (!pvk) { + WD_ERR("invalid: pvk is NULL!\n"); + return; + } + + pkey1 = &pvk->pkey1; + + if (d) + *d = &pkey1->d; + if (n) + *n = &pkey1->n; +} + +static int rsa_set_param(struct wd_dtb *src, struct wd_dtb *dst) +{ + if (!src || !dst || dst->dsize > src->bsize) + return -WD_EINVAL; + + src->dsize = dst->dsize; + memset(src->data, 0, src->bsize); + memcpy(src->data, dst->data, dst->dsize); + + return WD_SUCCESS; +} + +static int rsa_prikey2_param_set(struct wd_rsa_prikey2 *pkey2, + struct wd_dtb *param, + enum wd_rsa_crt_prikey_para type) +{ + int ret = -WD_EINVAL; + + if (param->dsize > pkey2->key_size || !param->data) + return -WD_EINVAL; + + switch (type) { + case WD_CRT_PRIKEY_DQ: + ret = rsa_set_param(&pkey2->dq, param); + break; + + case WD_CRT_PRIKEY_DP: + ret = rsa_set_param(&pkey2->dp, param); + break; + + case WD_CRT_PRIKEY_QINV: + ret = rsa_set_param(&pkey2->qinv, param); + break; + + case WD_CRT_PRIKEY_P: + ret = rsa_set_param(&pkey2->p, param); + break; + + case WD_CRT_PRIKEY_Q: + ret = rsa_set_param(&pkey2->q, param); + break; + } + + return ret; +} + +int wd_rsa_set_crt_prikey_params(handle_t sess, struct wd_dtb *dq, + struct wd_dtb *dp, struct wd_dtb *qinv, + struct wd_dtb *q, struct wd_dtb *p) +{ + struct wd_rsa_sess *c = (struct wd_rsa_sess *)sess; + struct wd_rsa_prikey2 *pkey2; + int ret = -WD_EINVAL; + + if (!sess || !wd_rsa_is_crt(sess)) { + WD_ERR("invalid: sess err in set rsa crt private key2!\n"); + return ret; + } + + if (!dq || !dp || !qinv || !q || !p) { + WD_ERR("invalid: para err in set rsa crt private key2!\n"); + return ret; + } + + pkey2 = &c->prikey->pkey2; + ret = rsa_prikey2_param_set(pkey2, dq, WD_CRT_PRIKEY_DQ); + if (ret) { + WD_ERR("failed to set dq for rsa private key2!\n"); + return ret; + } + + ret = rsa_prikey2_param_set(pkey2, dp, WD_CRT_PRIKEY_DP); + if (ret) { + WD_ERR("failed to set dp for rsa private key2!\n"); + return ret; + } + + ret = rsa_prikey2_param_set(pkey2, qinv, WD_CRT_PRIKEY_QINV); + if (ret) { + WD_ERR("failed to set qinv for rsa private key2!\n"); + return ret; + } + + ret = rsa_prikey2_param_set(pkey2, q, WD_CRT_PRIKEY_Q); + if (ret) { + WD_ERR("failed to set q for rsa private key2!\n"); + return ret; + } + + ret = rsa_prikey2_param_set(pkey2, p, WD_CRT_PRIKEY_P); + if (ret) { + WD_ERR("failed to set p for rsa private key2!\n"); + return ret; + } + + return WD_SUCCESS; +} + +void wd_rsa_get_crt_prikey_params(struct wd_rsa_prikey *pvk, + struct wd_dtb **dq, + struct wd_dtb **dp, struct wd_dtb **qinv, + struct wd_dtb **q, struct wd_dtb **p) +{ + struct wd_rsa_prikey2 *pkey2; + + if (!pvk) { + WD_ERR("invalid: pvk is NULL!\n"); + return; + } + + pkey2 = &pvk->pkey2; + + if (dq) + *dq = &pkey2->dq; + if (dp) + *dp = &pkey2->dp; + if (qinv) + *qinv = &pkey2->qinv; + if (q) + *q = &pkey2->q; + if (p) + *p = &pkey2->p; +} + +void wd_rsa_get_pubkey(handle_t sess, struct wd_rsa_pubkey **pubkey) +{ + if (!sess || !pubkey) { + WD_ERR("invalid: param is NULL!\n"); + return; + } + + *pubkey = ((struct wd_rsa_sess *)sess)->pubkey; +} + +void wd_rsa_get_prikey(handle_t sess, struct wd_rsa_prikey **prikey) +{ + if (!sess || !prikey) { + WD_ERR("invalid: param is NULL!\n"); + return; + } + + *prikey = ((struct wd_rsa_sess *)sess)->prikey; +} + +static const struct wd_config_variable table[] = { + { .name = "WD_RSA_CTX_NUM", + .def_val = "sync:2@0,async:2@0", + .parse_fn = wd_parse_ctx_num + }, + { .name = "WD_RSA_ASYNC_POLL_EN", + .def_val = "0", + .parse_fn = wd_parse_async_poll_en + } +}; + +static const struct wd_alg_ops wd_rsa_ops = { + .alg_name = "rsa", + .op_type_num = 1, + .alg_init = wd_rsa_init, + .alg_uninit = wd_rsa_uninit, + .alg_poll_ctx = wd_rsa_poll_ctx +}; + +int wd_rsa_env_init(struct wd_sched *sched) +{ + wd_rsa_env_config.sched = sched; + + return wd_alg_env_init(&wd_rsa_env_config, table, + &wd_rsa_ops, ARRAY_SIZE(table), NULL); +} + +void wd_rsa_env_uninit(void) +{ + return wd_alg_env_uninit(&wd_rsa_env_config, &wd_rsa_ops); +} + +int wd_rsa_ctx_num_init(__u32 node, __u32 type, __u32 num, __u8 mode) +{ + struct wd_ctx_attr ctx_attr; + int ret; + + ret = wd_set_ctx_attr(&ctx_attr, node, CTX_TYPE_INVALID, mode, num); + if (ret) + return ret; + + return wd_alg_env_init(&wd_rsa_env_config, table, + &wd_rsa_ops, ARRAY_SIZE(table), &ctx_attr); +} + +void wd_rsa_ctx_num_uninit(void) +{ + return wd_alg_env_uninit(&wd_rsa_env_config, &wd_rsa_ops); +} + +int wd_rsa_get_env_param(__u32 node, __u32 type, __u32 mode, + __u32 *num, __u8 *is_enable) +{ + struct wd_ctx_attr ctx_attr; + int ret; + + ret = wd_set_ctx_attr(&ctx_attr, node, CTX_TYPE_INVALID, mode, 0); + if (ret) + return ret; + + return wd_alg_get_env_param(&wd_rsa_env_config, + ctx_attr, num, is_enable); +} diff --git a/uadk/wd_sched.c b/uadk/wd_sched.c new file mode 100644 index 0000000..98f4cfd --- /dev/null +++ b/uadk/wd_sched.c @@ -0,0 +1,562 @@ +// SPDX-License-Identifier: Apache-2.0 +/* + * Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. + * Copyright 2020-2021 Linaro ltd. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include "wd_sched.h" + +#define MAX_POLL_TIMES 1000 + +enum sched_region_mode { + SCHED_MODE_SYNC = 0, + SCHED_MODE_ASYNC = 1, + SCHED_MODE_BUTT +}; + +/* + * sched_key - The key if schedule region. + * @numa_id: The schedule numa region id. + * @mode: Sync mode:0, async_mode:1 + * @type: Service type , the value must smaller than type_num. + * @sync_ctxid: alloc ctx id for sync mode + * @async_ctxid: alloc ctx id for async mode + */ +struct sched_key { + int numa_id; + __u8 type; + __u8 mode; + __u32 sync_ctxid; + __u32 async_ctxid; +}; + +/* + * struct sched_ctx_range - define one ctx pos. + * @begin: the start pos in ctxs of config. + * @end: the end pos in ctxx of config. + * @last: the last one which be distributed. + * @valid: the region used flag. + * @lock: lock the currentscheduling region. + */ +struct sched_ctx_region { + __u32 begin; + __u32 end; + __u32 last; + bool valid; + pthread_mutex_t lock; +}; + +/* + * wd_sched_info - define the context of the scheduler. + * @ctx_region: define the map for the comp ctxs, using for quickly search. + * the x range: two(sync and async), the y range: + * two(e.g. comp and uncomp) the map[x][y]'s value is the ctx + * begin and end pos. + * @valid: the region used flag. + */ +struct wd_sched_info { + struct sched_ctx_region *ctx_region[SCHED_MODE_BUTT]; + bool valid; +}; + +/* + * wd_sched_ctx - define the context of the scheduler. + * @policy: define the policy of the scheduler. + * @numa_num: the max numa numbers of the scheduler. + * @type_num: the max operation types of the scheduler. + * @poll_func: the task's poll operation function. + * @numa_map: a map of cpus to devices. + * @sched_info: the context of the scheduler. + */ +struct wd_sched_ctx { + __u32 policy; + __u32 type_num; + __u16 numa_num; + user_poll_func poll_func; + int numa_map[NUMA_NUM_NODES]; + struct wd_sched_info sched_info[0]; +}; + +static bool sched_key_valid(struct wd_sched_ctx *sched_ctx, const struct sched_key *key) +{ + if (key->numa_id >= sched_ctx->numa_num || + key->mode >= SCHED_MODE_BUTT || + key->type >= sched_ctx->type_num) { + WD_ERR("invalid: sched key's numa: %d, mode: %u, type: %u!\n", + key->numa_id, key->mode, key->type); + return false; + } + + return true; +} + +/* + * sched_get_ctx_range - Get ctx range from ctx_map by the wd comp arg + */ +static struct sched_ctx_region *sched_get_ctx_range(struct wd_sched_ctx *sched_ctx, + const struct sched_key *key) +{ + struct wd_sched_info *sched_info; + int numa_id; + int type; + + sched_info = sched_ctx->sched_info; + if (key->numa_id >= 0 && + sched_info[key->numa_id].ctx_region[key->mode][key->type].valid) + return &sched_info[key->numa_id].ctx_region[key->mode][key->type]; + + /* If the key->numa_id is not exist, we should scan for a region */ + for (numa_id = 0; numa_id < sched_ctx->numa_num; numa_id++) { + for (type = 0; type < sched_ctx->type_num; type++) { + if (sched_info[numa_id].ctx_region[key->mode][type].valid) + return &sched_info[numa_id].ctx_region[key->mode][type]; + } + } + + return NULL; +} + +/* + * sched_get_next_pos_rr - Get next resource pos by RR schedule. + * The second para is reserved for future. + */ +static __u32 sched_get_next_pos_rr(struct sched_ctx_region *region, void *para) +{ + __u32 pos; + + pthread_mutex_lock(®ion->lock); + + pos = region->last; + + if (pos < region->end) + region->last++; + else + region->last = region->begin; + + pthread_mutex_unlock(®ion->lock); + + return pos; +} + +/* + * session_sched_init_ctx - Get one ctx from ctxs by the sched_ctx and arg. + * @sched_ctx: Schedule ctx, reference the struct sample_sched_ctx. + * @sched_key: The key of schedule region. + * @sched_mode: The sched async/sync mode. + * + * The user must init the schedule info through wd_sched_rr_instance + */ +static __u32 session_sched_init_ctx(struct wd_sched_ctx *sched_ctx, struct sched_key *key, + const int sched_mode) +{ + struct sched_ctx_region *region = NULL; + bool ret; + + key->mode = sched_mode; + ret = sched_key_valid(sched_ctx, key); + if (!ret) + return INVALID_POS; + + region = sched_get_ctx_range(sched_ctx, key); + if (!region) + return INVALID_POS; + + return sched_get_next_pos_rr(region, NULL); +} + +static handle_t session_sched_init(handle_t h_sched_ctx, void *sched_param) +{ + struct wd_sched_ctx *sched_ctx = (struct wd_sched_ctx *)h_sched_ctx; + struct sched_params *param = (struct sched_params *)sched_param; + int cpu = sched_getcpu(); + int node = numa_node_of_cpu(cpu); + struct sched_key *skey; + + if (!sched_ctx) { + WD_ERR("invalid: sched ctx is NULL!\n"); + return (handle_t)(-WD_EINVAL); + } + + skey = malloc(sizeof(struct sched_key)); + if (!skey) { + WD_ERR("failed to alloc memory for session sched key!\n"); + return (handle_t)(-WD_ENOMEM); + } + + if (!param) { + memset(skey, 0, sizeof(struct sched_key)); + skey->numa_id = sched_ctx->numa_map[node]; + } else if (param->numa_id < 0) { + skey->type = param->type; + skey->numa_id = sched_ctx->numa_map[node]; + } else { + skey->type = param->type; + skey->numa_id = param->numa_id; + } + + if (skey->numa_id < 0) { + WD_ERR("failed to get valid sched numa region!\n"); + free(skey); + return (handle_t)(-WD_EINVAL); + } + + skey->sync_ctxid = session_sched_init_ctx(sched_ctx, skey, CTX_MODE_SYNC); + skey->async_ctxid = session_sched_init_ctx(sched_ctx, skey, CTX_MODE_ASYNC); + + return (handle_t)skey; +} + +/* + * session_pick_next_ctx - Get one ctx from ctxs by the sched_ctx and arg. + * @sched_ctx: Schedule ctx, reference the struct sample_sched_ctx. + * @sched_key: The key of schedule region. + * @sched_mode: The sched async/sync mode. + * + * The user must init the schedule info through session_sched_init + */ +static __u32 session_sched_pick_next_ctx(handle_t h_sched_ctx, void *sched_key, + const int sched_mode) +{ + struct sched_key *key = (struct sched_key *)sched_key; + + if (unlikely(!h_sched_ctx || !key)) { + WD_ERR("invalid: sched ctx or key is NULL!\n"); + return INVALID_POS; + } + + /* return in do task */ + if (sched_mode == CTX_MODE_SYNC) + return key->sync_ctxid; + return key->async_ctxid; +} + +static int session_poll_region(struct wd_sched_ctx *sched_ctx, __u32 begin, + __u32 end, __u32 expect, __u32 *count) +{ + __u32 poll_num = 0; + __u32 i; + int ret; + + /* i is the pos of ctxs, the max is end */ + for (i = begin; i <= end; i++) { + /* + * RR schedule, one time poll one package, + * poll_num is always not more than one here. + */ + ret = sched_ctx->poll_func(i, 1, &poll_num); + if ((ret < 0) && (ret != -EAGAIN)) + return ret; + else if (ret == -EAGAIN) + continue; + *count += poll_num; + if (*count == expect) + break; + } + + return 0; +} + +static int session_poll_policy_rr(struct wd_sched_ctx *sched_ctx, int numa_id, + __u32 expect, __u32 *count) +{ + struct sched_ctx_region **region = sched_ctx->sched_info[numa_id].ctx_region; + __u32 begin, end; + __u32 i; + int ret; + + for (i = 0; i < sched_ctx->type_num; i++) { + if (!region[SCHED_MODE_ASYNC][i].valid) + continue; + + begin = region[SCHED_MODE_ASYNC][i].begin; + end = region[SCHED_MODE_ASYNC][i].end; + ret = session_poll_region(sched_ctx, begin, end, expect, count); + if (unlikely(ret)) + return ret; + } + + return 0; +} + +/* + * session_poll_policy - The polling policy matches the pick next ctx. + * @sched_ctx: Schedule ctx, reference the struct sample_sched_ctx. + * @cfg: The global resoure info. + * @expect: User expect poll msg num. + * @count: The actually poll num. + * + * The user must init the schedule info through wd_sched_rr_instance, the + * func interval will not check the valid, becouse it will affect performance. + */ +static int session_sched_poll_policy(handle_t h_sched_ctx, __u32 expect, __u32 *count) +{ + struct wd_sched_ctx *sched_ctx = (struct wd_sched_ctx *)h_sched_ctx; + struct wd_sched_info *sched_info; + __u32 loop_time = 0; + __u32 last_count = 0; + __u16 i; + int ret; + + if (unlikely(!count || !sched_ctx)) { + WD_ERR("invalid: sched ctx is NULL or count is zero!\n"); + return -WD_EINVAL; + } + + if (unlikely(sched_ctx->numa_num > NUMA_NUM_NODES)) { + WD_ERR("invalid: ctx's numa number is %u!\n", sched_ctx->numa_num); + return -WD_EINVAL; + } + + sched_info = sched_ctx->sched_info; + + /* + * Try different numa's ctx if we can't receive any + * package last time, it is more efficient. In most + * bad situation, poll ends after MAX_POLL_TIMES loop. + */ + while (++loop_time < MAX_POLL_TIMES) { + for (i = 0; i < sched_ctx->numa_num;) { + /* If current numa is not valid, find next. */ + if (!sched_info[i].valid) { + i++; + continue; + } + + last_count = *count; + ret = session_poll_policy_rr(sched_ctx, i, expect, count); + if (unlikely(ret)) + return ret; + + if (expect == *count) + return 0; + + /* + * If no package is received, find next numa, + * otherwise, keep receiving packets at this node. + */ + if (last_count == *count) + i++; + } + } + + return 0; +} + +static struct wd_sched sched_table[SCHED_POLICY_BUTT] = { + { + .name = "RR scheduler", + .sched_policy = SCHED_POLICY_RR, + .sched_init = session_sched_init, + .pick_next_ctx = session_sched_pick_next_ctx, + .poll_policy = session_sched_poll_policy, + }, +}; + +static int wd_sched_get_nearby_numa_id(struct wd_sched_info *sched_info, int node, int numa_num) +{ + int dis = INT32_MAX; + int valid_id = -1; + int i, tmp; + + for (i = 0; i < numa_num; i++) { + if (sched_info[i].valid) { + tmp = numa_distance(node, i); + if (dis > tmp) { + valid_id = i; + dis = tmp; + } + } + } + + return valid_id; +} + +static void wd_sched_map_cpus_to_dev(struct wd_sched_ctx *sched_ctx) +{ + struct wd_sched_info *sched_info = sched_ctx->sched_info; + int i, numa_num = sched_ctx->numa_num; + int *numa_map = sched_ctx->numa_map; + + for (i = 0; i < numa_num; i++) { + if (sched_info[i].valid) + numa_map[i] = i; + else + numa_map[i] = wd_sched_get_nearby_numa_id(sched_info, i, numa_num); + } +} + +int wd_sched_rr_instance(const struct wd_sched *sched, struct sched_params *param) +{ + struct wd_sched_info *sched_info = NULL; + struct wd_sched_ctx *sched_ctx = NULL; + __u8 type, mode; + int numa_id; + + if (!sched || !sched->h_sched_ctx || !param) { + WD_ERR("invalid: sched or sched_params is NULL!\n"); + return -WD_EINVAL; + } + + if (param->begin > param->end) { + WD_ERR("invalid: sched_params's begin is larger than end!\n"); + return -WD_EINVAL; + } + + numa_id = param->numa_id; + type = param->type; + mode = param->mode; + sched_ctx = (struct wd_sched_ctx *)sched->h_sched_ctx; + + if (numa_id >= sched_ctx->numa_num || numa_id < 0) { + WD_ERR("invalid: sched_ctx's numa_id is %d, numa_num is %u!\n", + numa_id, sched_ctx->numa_num); + return -WD_EINVAL; + } + + if (type >= sched_ctx->type_num) { + WD_ERR("invalid: sched_ctx's type is %u, type_num is %u!\n", + type, sched_ctx->type_num); + return -WD_EINVAL; + } + + if (mode >= SCHED_MODE_BUTT) { + WD_ERR("invalid: sched_ctx's mode is %u, mode_num is %d!\n", + mode, SCHED_MODE_BUTT); + return -WD_EINVAL; + } + + sched_info = sched_ctx->sched_info; + + if (!sched_info[numa_id].ctx_region[mode]) { + WD_ERR("invalid: ctx_region is NULL, numa: %d, mode: %u!\n", + numa_id, mode); + return -WD_EINVAL; + } + + sched_info[numa_id].ctx_region[mode][type].begin = param->begin; + sched_info[numa_id].ctx_region[mode][type].end = param->end; + sched_info[numa_id].ctx_region[mode][type].last = param->begin; + sched_info[numa_id].ctx_region[mode][type].valid = true; + sched_info[numa_id].valid = true; + + wd_sched_map_cpus_to_dev(sched_ctx); + + pthread_mutex_init(&sched_info[numa_id].ctx_region[mode][type].lock, + NULL); + + return 0; +} + +void wd_sched_rr_release(struct wd_sched *sched) +{ + struct wd_sched_info *sched_info; + struct wd_sched_ctx *sched_ctx; + int i, j; + + if (!sched) + return; + + sched_ctx = (struct wd_sched_ctx *)sched->h_sched_ctx; + if (!sched_ctx) + goto out; + + sched_info = sched_ctx->sched_info; + for (i = 0; i < sched_ctx->numa_num; i++) { + for (j = 0; j < SCHED_MODE_BUTT; j++) { + if (sched_info[i].ctx_region[j]) { + free(sched_info[i].ctx_region[j]); + sched_info[i].ctx_region[j] = NULL; + } + } + } + + free(sched_ctx); + +out: + free(sched); + + return; +} + +static int numa_num_check(__u16 numa_num) +{ + int max_node; + + max_node = numa_max_node() + 1; + if (max_node <= 0) { + WD_ERR("invalid: numa max node is %d!\n", max_node); + return -WD_EINVAL; + } + + if (!numa_num || numa_num > max_node) { + WD_ERR("invalid: numa number is %u!\n", numa_num); + return -WD_EINVAL; + } + + return 0; +} + +struct wd_sched *wd_sched_rr_alloc(__u8 sched_type, __u8 type_num, + __u16 numa_num, user_poll_func func) +{ + struct wd_sched_info *sched_info; + struct wd_sched_ctx *sched_ctx; + struct wd_sched *sched; + int i, j; + + if (numa_num_check(numa_num)) + return NULL; + + if (sched_type >= SCHED_POLICY_BUTT || !type_num) { + WD_ERR("invalid: sched_type is %u or type_num is %u!\n", sched_type, type_num); + return NULL; + } + + sched = calloc(1, sizeof(struct wd_sched)); + if (!sched) { + WD_ERR("failed to alloc memory for wd_sched!\n"); + return NULL; + } + + sched_ctx = calloc(1, sizeof(struct wd_sched_ctx) + + sizeof(struct wd_sched_info) * numa_num); + if (!sched_ctx) { + WD_ERR("failed to alloc memory for sched_ctx!\n"); + goto err_out; + } + + sched->h_sched_ctx = (handle_t)sched_ctx; + sched_info = sched_ctx->sched_info; + + for (i = 0; i < numa_num; i++) { + for (j = 0; j < SCHED_MODE_BUTT; j++) { + sched_info[i].ctx_region[j] = + calloc(1, sizeof(struct sched_ctx_region) * type_num); + if (!sched_info[i].ctx_region[j]) + goto err_out; + } + } + + sched_ctx->poll_func = func; + sched_ctx->policy = sched_type; + sched_ctx->type_num = type_num; + sched_ctx->numa_num = numa_num; + memset(sched_ctx->numa_map, -1, sizeof(int) * NUMA_NUM_NODES); + + sched->sched_init = sched_table[sched_type].sched_init; + sched->pick_next_ctx = sched_table[sched_type].pick_next_ctx; + sched->poll_policy = sched_table[sched_type].poll_policy; + sched->sched_policy = sched_type; + sched->name = sched_table[sched_type].name; + + return sched; + +err_out: + wd_sched_rr_release(sched); + return NULL; +} diff --git a/uadk/wd_util.c b/uadk/wd_util.c new file mode 100644 index 0000000..bd82075 --- /dev/null +++ b/uadk/wd_util.c @@ -0,0 +1,1779 @@ +// SPDX-License-Identifier: Apache-2.0 +/* + * Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. + * Copyright 2020-2021 Linaro ltd. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include "wd_alg_common.h" +#include "wd_sched.h" +#include "wd_util.h" + +#define WD_ASYNC_DEF_POLL_NUM 1 +#define WD_ASYNC_DEF_QUEUE_DEPTH 1024 +#define WD_BALANCE_THRHD 1280 +#define WD_RECV_MAX_CNT_SLEEP 60000000 +#define WD_RECV_MAX_CNT_NOSLEEP 200000000 +#define PRIVILEGE_FLAG 600 +#define MIN(a, b) ((a) > (b) ? (b) : (a)) + +struct msg_pool { + /* message array allocated dynamically */ + void *msgs; + int *used; + __u32 msg_num; + __u32 msg_size; + int tail; +}; + +/* parse wd env begin */ + +/* define comp's combination of two operation type and two mode here */ +static const char *comp_ctx_type[2][2] = { + {"sync-comp:", "sync-decomp:"}, + {"async-comp:", "async-decomp:"} +}; + +/* define two ctx mode here for cipher and other alg */ +static const char *ctx_type[2][1] = { {"sync:"}, {"async:"} }; + +struct async_task { + __u32 idx; +}; + +struct async_task_queue { + struct async_task *head; + int depth; + /* the producer offset of task queue */ + int prod; + /* the consumer offset of task queue */ + int cons; + int cur_task; + int left_task; + int end; + sem_t empty_sem; + sem_t full_sem; + pthread_mutex_t lock; + pthread_t tid; + int (*alg_poll_ctx)(__u32, __u32, __u32 *); +}; + +static void clone_ctx_to_internal(struct wd_ctx *ctx, + struct wd_ctx_internal *ctx_in) +{ + ctx_in->ctx = ctx->ctx; + ctx_in->op_type = ctx->op_type; + ctx_in->ctx_mode = ctx->ctx_mode; +} + +static int get_shared_memory_id(__u32 numsize) +{ + int shm; + + shm = shmget(WD_IPC_KEY, sizeof(unsigned long) * numsize, + IPC_CREAT | PRIVILEGE_FLAG); + if (shm < 0) { + WD_ERR("failed to get shared memory id.\n"); + return -WD_EINVAL; + } + + return shm; +} + +static unsigned long *wd_shared_create(__u32 numsize) +{ + bool need_info = wd_need_info(); + void *ptr; + int shm; + + if (!need_info) + return NULL; + + if (numsize > WD_CTX_CNT_NUM) { + WD_ERR("invalid: input parameter is err!\n"); + return NULL; + } + + shm = get_shared_memory_id(numsize); + if (shm < 0) + return NULL; + + ptr = shmat(shm, NULL, 0); + if (ptr == (void *)-1) { + WD_ERR("failed to get shared memory addr.\n"); + return NULL; + } + + memset(ptr, 0, sizeof(unsigned long) * numsize); + + return ptr; +} + +static void wd_shared_delete(__u32 numsize) +{ + bool need_info = wd_need_info(); + int shm; + + if (!need_info) + return; + + if (numsize > WD_CTX_CNT_NUM) { + WD_ERR("invalid: input parameter is err!\n"); + return; + } + + shm = get_shared_memory_id(numsize); + if (shm < 0) + return; + + /* deleted shared memory */ + shmctl(shm, IPC_RMID, NULL); +} + +int wd_init_ctx_config(struct wd_ctx_config_internal *in, + struct wd_ctx_config *cfg) +{ + bool need_info = wd_need_info(); + struct wd_ctx_internal *ctxs; + int i, j, ret; + + if (!cfg->ctx_num) { + WD_ERR("invalid: ctx_num is 0!\n"); + return -WD_EINVAL; + } + + /* ctx could only be invoked once for one process. */ + if (in->ctx_num && in->pid == getpid()) { + WD_ERR("ctx have initialized.\n"); + return -WD_EEXIST; + } + + in->msg_cnt = wd_shared_create(WD_CTX_CNT_NUM); + if (!in->msg_cnt && need_info) + return -WD_EINVAL; + + ctxs = calloc(1, cfg->ctx_num * sizeof(struct wd_ctx_internal)); + if (!ctxs) { + WD_ERR("failed to alloc memory for internal ctxs!\n"); + wd_shared_delete(WD_CTX_CNT_NUM); + return -WD_ENOMEM; + } + + for (i = 0; i < cfg->ctx_num; i++) { + if (!cfg->ctxs[i].ctx) { + WD_ERR("invalid: ctx is NULL!\n"); + ret = -WD_EINVAL; + goto err_out; + } + + clone_ctx_to_internal(cfg->ctxs + i, ctxs + i); + ret = pthread_spin_init(&ctxs[i].lock, PTHREAD_PROCESS_SHARED); + if (ret) { + WD_ERR("failed to init ctxs lock!\n"); + goto err_out; + } + } + + in->ctxs = ctxs; + in->pid = getpid(); + in->priv = cfg->priv; + in->ctx_num = cfg->ctx_num; + + return 0; + +err_out: + for (j = 0; j < i; j++) + pthread_spin_destroy(&ctxs[j].lock); + + wd_shared_delete(WD_CTX_CNT_NUM); + free(ctxs); + return ret; +} + +int wd_init_sched(struct wd_sched *in, struct wd_sched *from) +{ + if (!from->name || !from->sched_init || + !from->pick_next_ctx || !from->poll_policy) { + WD_ERR("invalid: member of wd_sched is NULL!\n"); + return -WD_EINVAL; + } + + in->h_sched_ctx = from->h_sched_ctx; + in->name = strdup(from->name); + in->sched_init = from->sched_init; + in->pick_next_ctx = from->pick_next_ctx; + in->poll_policy = from->poll_policy; + + return 0; +} + +void wd_clear_sched(struct wd_sched *in) +{ + char *name = (char *)in->name; + + if (name) + free(name); + in->h_sched_ctx = 0; + in->name = NULL; + in->sched_init = NULL; + in->pick_next_ctx = NULL; + in->poll_policy = NULL; +} + +void wd_clear_ctx_config(struct wd_ctx_config_internal *in) +{ + int i; + + for (i = 0; i < in->ctx_num; i++) + pthread_spin_destroy(&in->ctxs[i].lock); + + in->priv = NULL; + in->ctx_num = 0; + in->pid = 0; + if (in->ctxs) { + free(in->ctxs); + in->ctxs = NULL; + } + + wd_shared_delete(WD_CTX_CNT_NUM); + in->msg_cnt = NULL; +} + +void wd_memset_zero(void *data, __u32 size) +{ + __u32 tmp = size; + char *s = data; + + if (!s) + return; + + while (tmp--) + *s++ = 0; +} + +static int init_msg_pool(struct msg_pool *pool, __u32 msg_num, __u32 msg_size) +{ + pool->msgs = calloc(1, msg_num * msg_size); + if (!pool->msgs) { + WD_ERR("failed to alloc memory for msgs arrary of msg pool!\n"); + return -WD_ENOMEM; + } + + pool->used = calloc(1, msg_num * sizeof(int)); + if (!pool->used) { + free(pool->msgs); + pool->msgs = NULL; + WD_ERR("failed to alloc memory for used arrary of msg pool!\n"); + return -WD_ENOMEM; + } + + pool->msg_size = msg_size; + pool->msg_num = msg_num; + pool->tail = 0; + + return 0; +} + +static void uninit_msg_pool(struct msg_pool *pool) +{ + free(pool->msgs); + free(pool->used); + pool->msgs = NULL; + pool->used = NULL; + memset(pool, 0, sizeof(*pool)); +} + +int wd_init_async_request_pool(struct wd_async_msg_pool *pool, __u32 pool_num, + __u32 msg_num, __u32 msg_size) +{ + int i, j, ret; + + pool->pool_num = pool_num; + + pool->pools = calloc(1, pool->pool_num * sizeof(struct msg_pool)); + if (!pool->pools) { + WD_ERR("failed to alloc memory for async msg pools!\n"); + return -WD_ENOMEM; + } + + for (i = 0; i < pool->pool_num; i++) { + ret = init_msg_pool(&pool->pools[i], msg_num, msg_size); + if (ret < 0) + goto err; + } + + return 0; +err: + for (j = 0; j < i; j++) + uninit_msg_pool(&pool->pools[j]); + free(pool->pools); + pool->pools = NULL; + return ret; +} + +void wd_uninit_async_request_pool(struct wd_async_msg_pool *pool) +{ + int i; + + for (i = 0; i < pool->pool_num; i++) + uninit_msg_pool(&pool->pools[i]); + + free(pool->pools); + pool->pools = NULL; + pool->pool_num = 0; +} + +/* fix me: this is old wd_get_req_from_pool */ +void *wd_find_msg_in_pool(struct wd_async_msg_pool *pool, + int ctx_idx, __u32 tag) +{ + struct msg_pool *p = &pool->pools[ctx_idx]; + __u32 msg_num = p->msg_num; + + /* tag value start from 1 */ + if (tag == 0 || tag > msg_num) { + WD_ERR("invalid: message cache tag is %u!\n", tag); + return NULL; + } + + return (void *)((uintptr_t)p->msgs + p->msg_size * (tag - 1)); +} + +int wd_get_msg_from_pool(struct wd_async_msg_pool *pool, + int ctx_idx, void **msg) +{ + struct msg_pool *p = &pool->pools[ctx_idx]; + __u32 msg_num = p->msg_num; + __u32 msg_size = p->msg_size; + int cnt = 0; + __u32 idx = p->tail; + + while (__atomic_test_and_set(&p->used[idx], __ATOMIC_ACQUIRE)) { + idx = (idx + 1) % msg_num; + cnt++; + if (cnt == msg_num) + return -WD_EBUSY; + } + + p->tail = (idx + 1) % msg_num; + *msg = (void *)((uintptr_t)p->msgs + msg_size * idx); + + return idx + 1; +} + +void wd_put_msg_to_pool(struct wd_async_msg_pool *pool, int ctx_idx, __u32 tag) +{ + struct msg_pool *p = &pool->pools[ctx_idx]; + __u32 msg_num = p->msg_num; + + /* tag value start from 1 */ + if (!tag || tag > msg_num) { + WD_ERR("invalid: message cache idx is %u!\n", tag); + return; + } + + __atomic_clear(&p->used[tag - 1], __ATOMIC_RELEASE); +} + +int wd_check_datalist(struct wd_datalist *head, __u32 size) +{ + struct wd_datalist *tmp = head; + __u32 list_size = 0; + + while (tmp) { + if (tmp->data) + list_size += tmp->len; + + tmp = tmp->next; + } + + return list_size >= size ? 0 : -WD_EINVAL; +} + +void dump_env_info(struct wd_env_config *config) +{ + struct wd_env_config_per_numa *config_numa; + struct wd_ctx_range **ctx_table; + int i, j, k; + + FOREACH_NUMA(i, config, config_numa) { + if (!config_numa->ctx_table) + continue; + + ctx_table = config_numa->ctx_table; + WD_ERR("-> %s: %d: sync num: %lu\n", __func__, i, + config_numa->sync_ctx_num); + WD_ERR("-> %s: %d: async num: %lu\n", __func__, i, + config_numa->async_ctx_num); + for (j = 0; j < CTX_MODE_MAX; j++) + for (k = 0; k < config_numa->op_type_num; k++) { + WD_ERR("-> %d: [%d][%d].begin: %u\n", + i, j, k, ctx_table[j][k].begin); + WD_ERR("-> %d: [%d][%d].end: %u\n", + i, j, k, ctx_table[j][k].end); + WD_ERR("-> %d: [%d][%d].size: %u\n", + i, j, k, ctx_table[j][k].size); + } + } +} + +static void *wd_get_config_numa(struct wd_env_config *config, int node) +{ + struct wd_env_config_per_numa *config_numa; + int i; + + FOREACH_NUMA(i, config, config_numa) + if (config_numa->node == node) + break; + + if (i == config->numa_num) { + WD_ERR("invalid: missing numa node is %d!\n", node); + return NULL; + } + + return config_numa; +} + +static void wd_free_numa(struct wd_env_config *config) +{ + struct wd_env_config_per_numa *config_numa; + int i; + + FOREACH_NUMA(i, config, config_numa) + free(config_numa->dev); + + free(config->config_per_numa); + config->config_per_numa = NULL; + config->numa_num = 0; +} + +/** + * @numa_dev_num: number of devices of the same type (like sec2) on each numa. + * @numa_num: number of numa node that has this type of device. + */ +static __u16 wd_get_dev_numa(struct uacce_dev_list *head, + int *numa_dev_num, __u16 size) +{ + struct uacce_dev_list *list = head; + __u16 numa_num = 0; + + while (list) { + if (list->dev->numa_id < 0) { + list->dev->numa_id = 0; + } else if (list->dev->numa_id >= size) { + WD_ERR("invalid: numa id is %d!\n", list->dev->numa_id); + return 0; + } + + if (!numa_dev_num[list->dev->numa_id]) + numa_num++; + + numa_dev_num[list->dev->numa_id]++; + list = list->next; + } + + return numa_num; +} + +static void wd_set_numa_dev(struct uacce_dev_list *head, + struct wd_env_config *config) +{ + struct uacce_dev_list *list = head; + struct wd_env_config_per_numa *config_numa; + struct uacce_dev *dev; + + while (list) { + config_numa = wd_get_config_numa(config, list->dev->numa_id); + if (!config_numa) + break; + + dev = config_numa->dev + config_numa->dev_num; + memcpy(dev, list->dev, sizeof(*list->dev)); + config_numa->dev_num++; + list = list->next; + } +} + +static int wd_set_config_numa(struct wd_env_config *config, + const int *numa_dev_num, int max_node) +{ + struct wd_env_config_per_numa *config_numa; + int i; + + config->config_per_numa = calloc(config->numa_num, sizeof(*config_numa)); + if (!config->config_per_numa) + return -WD_ENOMEM; + + config_numa = config->config_per_numa; + for (i = 0; i < max_node; i++) { + if (!numa_dev_num[i]) + continue; + + config_numa->node = i; + config_numa->dev = calloc(numa_dev_num[i], + sizeof(struct uacce_dev)); + if (!config_numa->dev) { + /* free config_per_numa and all uacce dev */ + wd_free_numa(config); + return -WD_ENOMEM; + } + + config_numa->dev_num = 0; + config_numa++; + } + + return 0; +} + +static int wd_alloc_numa(struct wd_env_config *config, + const struct wd_alg_ops *ops) +{ + struct uacce_dev_list *head; + int *numa_dev_num; + int ret, max_node; + + max_node = numa_max_node() + 1; + if (max_node <= 0) + return -WD_EINVAL; + + numa_dev_num = calloc(max_node, sizeof(int)); + if (!numa_dev_num) + return -WD_ENOMEM; + + /* get uacce_dev */ + head = wd_get_accel_list(ops->alg_name); + if (!head) { + WD_ERR("invalid: no device to support %s\n", ops->alg_name); + ret = -WD_ENODEV; + goto free_numa_dev_num; + } + + /* get numa num and device num of each numa from uacce_dev list */ + config->numa_num = wd_get_dev_numa(head, numa_dev_num, max_node); + if (config->numa_num == 0 || config->numa_num > max_node) { + WD_ERR("invalid: numa number is %u!\n", config->numa_num); + ret = -WD_ENODEV; + goto free_list; + } + + /* alloc and init config_per_numa and all uacce dev */ + ret = wd_set_config_numa(config, numa_dev_num, max_node); + if (ret) { + WD_ERR("failed to set numa config, ret = %d!\n", ret); + goto free_list; + } + + /* set device and device num for config numa from uacce_dev list */ + wd_set_numa_dev(head, config); + wd_free_list_accels(head); + free(numa_dev_num); + + return 0; + +free_list: + config->numa_num = 0; + wd_free_list_accels(head); +free_numa_dev_num: + free(numa_dev_num); + return ret; +} + +static int is_number(const char *str) +{ + size_t len; + int i; + + if (!str) + return 0; + + len = strlen(str); + if (len == 0) + return 0; + + if (len != 1 && str[0] == '0') + return 0; + + for (i = 0; i < len; i++) + if (!(isdigit(str[i]))) + return 0; + + return 1; +} + +static int str_to_bool(const char *s, bool *target) +{ + int tmp; + + if (!is_number(s)) + return -WD_EINVAL; + + tmp = strtol(s, NULL, 10); + if (tmp != 0 && tmp != 1) + return -WD_EINVAL; + + *target = tmp; + + return 0; +} + +int wd_parse_async_poll_en(struct wd_env_config *config, const char *s) +{ + int ret; + + ret = str_to_bool(s, &config->enable_internal_poll); + if (ret) + WD_ERR("failed to parse async poll enable flag(%s)!\n", s); + + return ret; +} + +static int parse_num_on_numa(const char *s, int *num, int *node) +{ + char *sep, *start, *left; + + if (!strlen(s)) { + WD_ERR("invalid: input string length is zero!\n"); + return -WD_EINVAL; + } + + start = strdup(s); + if (!start) + return -WD_ENOMEM; + + left = start; + sep = strsep(&left, "@"); + if (!sep) + goto out; + + if (is_number(sep) && is_number(left)) { + *num = strtol(sep, NULL, 10); + *node = strtol(left, NULL, 10); + free(start); + return 0; + } + +out: + WD_ERR("invalid: input env format is %s!\n", s); + free(start); + return -WD_EINVAL; +} + +static int wd_alloc_ctx_table_per_numa(struct wd_env_config_per_numa *config) +{ + struct wd_ctx_range **ctx_table; + int i, j, ret; + + if (config->ctx_table) + return 0; + + ctx_table = calloc(1, sizeof(struct wd_ctx_range *) * CTX_MODE_MAX); + if (!ctx_table) + return -WD_ENOMEM; + + for (i = 0; i < CTX_MODE_MAX; i++) { + ctx_table[i] = calloc(1, + sizeof(struct wd_ctx_range) * + config->op_type_num); + if (!ctx_table[i]) { + ret = -WD_ENOMEM; + goto free_mem; + } + } + + config->ctx_table = ctx_table; + + return 0; + +free_mem: + for (j = 0; j < i; j++) + free(ctx_table[j]); + + free(ctx_table); + return ret; +} + +static void wd_free_ctx_table_per_numa(struct wd_env_config_per_numa *config) +{ + int i; + + if (!config->ctx_table) + return; + + for (i = 0; i < CTX_MODE_MAX; i++) + free(config->ctx_table[i]); + + free(config->ctx_table); + config->ctx_table = NULL; +} + +static void wd_free_ctx_table(struct wd_env_config *config) +{ + struct wd_env_config_per_numa *config_numa; + int i; + + FOREACH_NUMA(i, config, config_numa) + wd_free_ctx_table_per_numa(config_numa); +} + +static int get_and_fill_ctx_num(struct wd_env_config_per_numa *config_numa, + const char *p, int ctx_num) +{ + struct wd_ctx_range **ctx_table = config_numa->ctx_table; + const char *type; + int i, j; + + /** + * There're two types of environment variables, mode:num@node and + * mode-type:num@node, parse ctx num with comp_ctx_type and ctx_type. + */ + + for (i = 0; i < CTX_MODE_MAX; i++) + for (j = 0; j < config_numa->op_type_num; j++) { + if (config_numa->op_type_num == 1) + type = ctx_type[i][j]; + else + type = comp_ctx_type[i][j]; + + if (!strncmp(p, type, strlen(type))) { + ctx_table[i][j].size = ctx_num; + return 0; + } + } + + return -WD_EINVAL; +} + +static int wd_parse_section(struct wd_env_config *config, char *section) +{ + struct wd_env_config_per_numa *config_numa; + int ctx_num, node, ret; + char *ctx_section; + + ctx_section = index(section, ':'); + if (!ctx_section) { + WD_ERR("invalid: ctx section got wrong format: %s!\n", section); + return -WD_EINVAL; + } + + ctx_section++; + + ret = parse_num_on_numa(ctx_section, &ctx_num, &node); + if (ret) + return ret; + + config_numa = wd_get_config_numa(config, node); + if (!config_numa) + return -WD_EINVAL; + + config_numa->op_type_num = config->op_type_num; + ret = wd_alloc_ctx_table_per_numa(config_numa); + if (ret) + return ret; + + ret = get_and_fill_ctx_num(config_numa, section, ctx_num); + if (ret) { + WD_ERR("invalid: ctx section got wrong ctx type: %s!\n", + section); + wd_free_ctx_table_per_numa(config_numa); + return ret; + } + + return 0; +} + +static int get_start_ctx_index(struct wd_env_config *config, + struct wd_env_config_per_numa *config_numa) +{ + struct wd_env_config_per_numa *config_cur = config->config_per_numa; + int start = 0; + + for (; config_cur < config_numa; config_cur++) + start += config_cur->sync_ctx_num + config_cur->async_ctx_num; + + return start; +} + +static void set_ctx_index(struct wd_env_config_per_numa *config_numa, + __u8 mode, int *start) +{ + struct wd_ctx_range **ctx_table = config_numa->ctx_table; + int size, i, sum = 0; + + for (i = 0; i < config_numa->op_type_num; i++) + sum += ctx_table[mode][i].size; + + if (mode) + config_numa->async_ctx_num = sum; + else + config_numa->sync_ctx_num = sum; + + if (!sum) + return; + + for (i = 0; i < config_numa->op_type_num; i++) { + size = ctx_table[mode][i].size; + if (!size) + continue; + ctx_table[mode][i].begin = *start; + ctx_table[mode][i].end = *start + size - 1; + *start += size; + } +} + +static void wd_fill_ctx_table(struct wd_env_config *config) +{ + struct wd_env_config_per_numa *config_numa; + int start, i, j; + + FOREACH_NUMA(i, config, config_numa) { + if (!config_numa->ctx_table) + continue; + + start = get_start_ctx_index(config, config_numa); + for (j = 0; j < CTX_MODE_MAX; j++) + set_ctx_index(config_numa, j, &start); + } +} + +static int parse_ctx_num(struct wd_env_config *config, const char *s) +{ + char *left, *section, *start; + int ret; + + start = strdup(s); + if (!start) + return -WD_ENOMEM; + + left = start; + + while ((section = strsep(&left, ","))) { + ret = wd_parse_section(config, section); + if (ret) + goto err_free_ctx_table; + } + + wd_fill_ctx_table(config); + free(start); + + return 0; + +err_free_ctx_table: + wd_free_ctx_table(config); + free(start); + return ret; +} + +int wd_parse_ctx_num(struct wd_env_config *config, const char *s) +{ + return parse_ctx_num(config, s); +} + +int wd_parse_async_poll_num(struct wd_env_config *config, const char *s) +{ + struct wd_env_config_per_numa *config_numa; + char *left, *section, *start; + int node, poll_num, ret; + + if (!config->enable_internal_poll) { + WD_ERR("internal poll not enabled, skip parse poll number!\n"); + return 0; + } + + start = strdup(s); + if (!start) + return -ENOMEM; + + left = start; + while ((section = strsep(&left, ","))) { + ret = parse_num_on_numa(section, &poll_num, &node); + if (ret) + goto out; + config_numa = wd_get_config_numa(config, node); + if (!config_numa) { + ret = -WD_EINVAL; + goto out; + } + config_numa->async_poll_num = poll_num; + } + + free(start); + return 0; +out: + free(start); + return ret; +} + +static int wd_parse_env(struct wd_env_config *config) +{ + const struct wd_config_variable *var; + const char *var_s; + int ret, i; + + for (i = 0; i < config->table_size; i++) { + var = config->table + i; + + var_s = secure_getenv(var->name); + if (!var_s || !strlen(var_s)) { + var_s = var->def_val; + WD_ERR("no %s environment variable! Use default: %s\n", + var->name, var->def_val); + } + + ret = var->parse_fn(config, var_s); + if (ret) { + WD_ERR("failed to parse %s environment variable!\n", + var->name); + return -WD_EINVAL; + } + } + + return 0; +} + +static int wd_parse_ctx_attr(struct wd_env_config *env_config, + struct wd_ctx_attr *attr) +{ + struct wd_env_config_per_numa *config_numa; + int ret; + + config_numa = wd_get_config_numa(env_config, attr->node); + if (!config_numa) + return -WD_EINVAL; + + config_numa->op_type_num = env_config->op_type_num; + ret = wd_alloc_ctx_table_per_numa(config_numa); + if (ret) + return ret; + + config_numa->ctx_table[attr->mode][attr->type].size = attr->num; + wd_fill_ctx_table(env_config); + + /* Use default sched and disable internal poll */ + env_config->sched = NULL; + env_config->enable_internal_poll = 0; + config_numa->async_poll_num = 0; + + return 0; +} + +static int wd_init_env_config(struct wd_env_config *config, + struct wd_ctx_attr *attr, + const struct wd_alg_ops *ops, + const struct wd_config_variable *table, + __u32 table_size) +{ + config->op_type_num = ops->op_type_num; + config->table_size = table_size; + config->table = table; + + return attr ? wd_parse_ctx_attr(config, attr) : wd_parse_env(config); +} + +static void wd_uninit_env_config(struct wd_env_config *config) +{ + wd_free_ctx_table(config); + + config->op_type_num = 0; + config->table_size = 0; + config->table = NULL; +} + +static __u8 get_ctx_mode(struct wd_env_config_per_numa *config, int idx) +{ + struct wd_ctx_range **ctx_table = config->ctx_table; + int i; + + for (i = 0; i < config->op_type_num; i++) { + if ((idx >= ctx_table[CTX_MODE_SYNC][i].begin) && + (idx <= ctx_table[CTX_MODE_SYNC][i].end) && + ctx_table[CTX_MODE_SYNC][i].size) + return CTX_MODE_SYNC; + } + return CTX_MODE_ASYNC; +} + +static int get_op_type(struct wd_env_config_per_numa *config, + int idx, __u8 ctx_mode) +{ + struct wd_ctx_range **ctx_table = config->ctx_table; + int i; + + if (config->op_type_num == 1) + return 0; + + for (i = 0; i < config->op_type_num; i++) { + if ((idx >= ctx_table[ctx_mode][i].begin) && + (idx <= ctx_table[ctx_mode][i].end) && + ctx_table[ctx_mode][i].size) + return i; + } + + WD_ERR("failed to get op type!\n"); + return -WD_EINVAL; +} + +static handle_t request_ctx_on_numa(struct wd_env_config_per_numa *config) +{ + struct uacce_dev *dev; + handle_t h_ctx; + int i, ctx_num; + + for (i = 0; i < config->dev_num; i++) { + dev = config->dev + i; + ctx_num = wd_get_avail_ctx(dev); + if (ctx_num <= 0) + continue; + + h_ctx = wd_request_ctx(dev); + if (h_ctx) + return h_ctx; + } + + return 0; +} + +static int wd_get_wd_ctx(struct wd_env_config_per_numa *config, + struct wd_ctx_config *ctx_config, int start) +{ + int ctx_num = config->sync_ctx_num + config->async_ctx_num; + handle_t h_ctx; + int i, j, ret; + + if (!ctx_num) + return 0; + + for (i = start; i < start + ctx_num; i++) { + h_ctx = request_ctx_on_numa(config); + if (!h_ctx) { + ret = -WD_EBUSY; + WD_ERR("failed to request more ctxs!\n"); + goto free_ctx; + } + + ctx_config->ctxs[i].ctx = h_ctx; + ctx_config->ctxs[i].ctx_mode = get_ctx_mode(config, i); + ret = get_op_type(config, i, ctx_config->ctxs[i].ctx_mode); + if (ret < 0) + goto free_ctx; + + ctx_config->ctxs[i].op_type = ret; + } + + return 0; + +free_ctx: + for (j = start; j < i; j++) + wd_release_ctx(ctx_config->ctxs[j].ctx); + return ret; +} + +static void wd_put_wd_ctx(struct wd_ctx_config *ctx_config, int ctx_num) +{ + __u32 i; + + for (i = 0; i < ctx_num; i++) + wd_release_ctx(ctx_config->ctxs[i].ctx); +} + +static int wd_alloc_ctx(struct wd_env_config *config) +{ + struct wd_env_config_per_numa *config_numa; + struct wd_ctx_config *ctx_config; + int ctx_num = 0, start = 0, ret = 0; + int i; + + config->ctx_config = calloc(1, sizeof(*ctx_config)); + if (!config->ctx_config) + return -WD_ENOMEM; + + ctx_config = config->ctx_config; + + FOREACH_NUMA(i, config, config_numa) + ctx_num += config_numa->sync_ctx_num + config_numa->async_ctx_num; + + ctx_config->ctxs = calloc(ctx_num, sizeof(struct wd_ctx)); + if (!ctx_config->ctxs) { + ret = -WD_ENOMEM; + goto err_free_ctx_config; + } + ctx_config->ctx_num = ctx_num; + + FOREACH_NUMA(i, config, config_numa) { + ret = wd_get_wd_ctx(config_numa, ctx_config, start); + if (ret) + goto err_free_ctxs; + + start += config_numa->sync_ctx_num + config_numa->async_ctx_num; + } + + return 0; + +err_free_ctxs: + wd_put_wd_ctx(ctx_config, start); + free(ctx_config->ctxs); +err_free_ctx_config: + free(ctx_config); + return ret; +} + +static void wd_free_ctx(struct wd_env_config *config) +{ + struct wd_ctx_config *ctx_config; + + if (!config->ctx_config) + return; + + ctx_config = config->ctx_config; + wd_put_wd_ctx(ctx_config, ctx_config->ctx_num); + free(ctx_config->ctxs); + free(ctx_config); + config->ctx_config = NULL; +} + +static int wd_sched_fill_table(struct wd_env_config_per_numa *config_numa, + struct wd_sched *sched, __u8 mode, int type_num) +{ + struct wd_ctx_range **ctx_table; + struct sched_params param; + int i, ret, ctx_num; + + if (mode) + ctx_num = config_numa->async_ctx_num; + else + ctx_num = config_numa->sync_ctx_num; + + ctx_table = config_numa->ctx_table; + param.numa_id = config_numa->node; + param.mode = mode; + for (i = 0; i < type_num && ctx_num; i++) { + if (!ctx_table[mode][i].size) + continue; + + param.type = i; + param.begin = ctx_table[mode][i].begin; + param.end = ctx_table[mode][i].end; + ret = wd_sched_rr_instance(sched, ¶m); + if (ret) + return ret; + } + + return 0; +} + +static void wd_uninit_sched_config(struct wd_env_config *config) +{ + if (!config->sched || !config->internal_sched) + return; + + wd_sched_rr_release(config->sched); + config->sched = NULL; +} + +static int wd_init_sched_config(struct wd_env_config *config, + void *alg_poll_ctx) +{ + struct wd_env_config_per_numa *config_numa; + int i, j, ret, max_node, type_num; + void *func = NULL; + + type_num = config->op_type_num; + max_node = numa_max_node() + 1; + if (max_node <= 0) + return -WD_EINVAL; + + if (!config->enable_internal_poll) + func = alg_poll_ctx; + + config->internal_sched = false; + if (!config->sched) { + WD_ERR("no sched is specified, alloc a default sched!\n"); + config->sched = wd_sched_rr_alloc(SCHED_POLICY_RR, type_num, + max_node, func); + if (!config->sched) + return -WD_ENOMEM; + + config->internal_sched = true; + } + + config->sched->name = "SCHED_RR"; + + FOREACH_NUMA(i, config, config_numa) { + for (j = 0; j < CTX_MODE_MAX; j++) { + ret = wd_sched_fill_table(config_numa, + config->sched, j, + type_num); + if (ret) + goto err_release_sched; + } + } + + return 0; + +err_release_sched: + wd_uninit_sched_config(config); + + return ret; +} + +static struct async_task_queue *find_async_queue(struct wd_env_config *config, + __u32 idx) +{ + struct wd_env_config_per_numa *config_numa; + struct wd_ctx_range **ctx_table; + struct async_task_queue *head; + unsigned long offset = 0; + int num = 0; + int i; + + FOREACH_NUMA(i, config, config_numa) { + num += config_numa->sync_ctx_num + config_numa->async_ctx_num; + if (idx < num) + break; + } + + if (i == config->numa_num) { + WD_ERR("failed to find a proper numa node!\n"); + return NULL; + } + + if (!config_numa->async_poll_num) { + WD_ERR("invalid: async_poll_num of numa is zero!\n"); + return NULL; + } + + ctx_table = config_numa->ctx_table; + for (i = 0; i < config_numa->op_type_num; i++) { + if (idx <= ctx_table[CTX_MODE_ASYNC][i].end && + idx >= ctx_table[CTX_MODE_ASYNC][i].begin) { + offset = (idx - ctx_table[CTX_MODE_ASYNC][i].begin) % + config_numa->async_poll_num; + break; + } + } + + if (i == config_numa->op_type_num) { + WD_ERR("failed to find async queue for ctx: idx %u!\n", idx); + return NULL; + } + + head = (struct async_task_queue *)config_numa->async_task_queue_array; + + return head + offset; +} + +/* fix me: all return value here, and no config input */ +int wd_add_task_to_async_queue(struct wd_env_config *config, __u32 idx) +{ + struct async_task_queue *task_queue; + struct async_task *task; + int curr_prod, ret; + + if (!config->enable_internal_poll) + return 0; + + task_queue = find_async_queue(config, idx); + if (!task_queue) + return -WD_EINVAL; + + ret = sem_wait(&task_queue->empty_sem); + if (ret) { + WD_ERR("failed to wait empty_sem!\n"); + return ret; + } + + pthread_mutex_lock(&task_queue->lock); + + /* get an available async task and fill ctx idx */ + curr_prod = task_queue->prod; + task = task_queue->head + curr_prod; + task->idx = idx; + + /* update global information of task queue */ + task_queue->prod = (curr_prod + 1) % task_queue->depth; + task_queue->cur_task++; + task_queue->left_task--; + + pthread_mutex_unlock(&task_queue->lock); + + ret = sem_post(&task_queue->full_sem); + if (ret) { + WD_ERR("failed to post full_sem!\n"); + goto err_out; + } + + return 0; + +err_out: + pthread_mutex_lock(&task_queue->lock); + task_queue->left_task++; + task_queue->cur_task--; + task_queue->prod = curr_prod; + pthread_mutex_unlock(&task_queue->lock); + + return ret; +} + +static void *async_poll_process_func(void *args) +{ + struct async_task_queue *task_queue = args; + struct async_task *head, *task; + __u32 count; + int cons, ret; + + while (1) { + if (sem_wait(&task_queue->full_sem)) { + if (errno == EINTR) { + continue; + } + } + if (__atomic_load_n(&task_queue->end, __ATOMIC_ACQUIRE)) { + __atomic_store_n(&task_queue->end, 0, __ATOMIC_RELEASE); + goto out; + } + + pthread_mutex_lock(&task_queue->lock); + + /* async sending message isn't submitted yet */ + if (task_queue->cons == task_queue->prod) { + pthread_mutex_unlock(&task_queue->lock); + sem_post(&task_queue->full_sem); + continue; + } + + cons = task_queue->cons; + head = task_queue->head; + task = head + cons; + + task_queue->cons = (cons + 1) % task_queue->depth; + task_queue->cur_task--; + task_queue->left_task++; + + pthread_mutex_unlock(&task_queue->lock); + + ret = task_queue->alg_poll_ctx(task->idx, 1, &count); + if (ret < 0) { + pthread_mutex_lock(&task_queue->lock); + task_queue->cons = cons; + task_queue->cur_task++; + task_queue->left_task--; + pthread_mutex_unlock(&task_queue->lock); + if (ret == -WD_EAGAIN) { + sem_post(&task_queue->full_sem); + continue; + } else + goto out; + } + + if (sem_post(&task_queue->empty_sem)) + goto out; + } +out: + pthread_exit(NULL); + return NULL; +} + +static int wd_init_one_task_queue(struct async_task_queue *task_queue, + void *alg_poll_ctx) + +{ + struct async_task *head; + pthread_t thread_id; + pthread_attr_t attr; + int depth, ret; + + task_queue->depth = depth = WD_ASYNC_DEF_QUEUE_DEPTH; + + head = calloc(task_queue->depth, sizeof(*head)); + if (!head) + return -WD_ENOMEM; + + task_queue->head = head; + task_queue->left_task = depth; + task_queue->alg_poll_ctx = alg_poll_ctx; + + if (sem_init(&task_queue->empty_sem, 0, depth)) { + WD_ERR("failed to init empty_sem!\n"); + goto err_free_head; + } + + if (sem_init(&task_queue->full_sem, 0, 0)) { + WD_ERR("failed to init full_sem!\n"); + goto err_uninit_empty_sem; + } + + if (pthread_mutex_init(&task_queue->lock, NULL)) { + WD_ERR("failed to init task queue's mutex lock!\n"); + goto err_uninit_full_sem; + } + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + task_queue->tid = 0; + if (pthread_create(&thread_id, &attr, async_poll_process_func, + task_queue)) { + WD_ERR("failed to create poll thread!\n"); + goto err_destory_mutex; + } + + task_queue->tid = thread_id; + pthread_attr_destroy(&attr); + + return 0; + +err_destory_mutex: + pthread_attr_destroy(&attr); + pthread_mutex_destroy(&task_queue->lock); +err_uninit_full_sem: + sem_destroy(&task_queue->full_sem); +err_uninit_empty_sem: + sem_destroy(&task_queue->empty_sem); +err_free_head: + free(head); + ret = -errno; + return ret; +} + +static void wd_uninit_one_task_queue(struct async_task_queue *task_queue) +{ + /* + * If there's no async task, async_poll_process_func() is sleeping + * on task_queue->full_sem. It'll cause that threads could not + * be end and memory leak. + */ + sem_post(&task_queue->full_sem); + __atomic_store_n(&task_queue->end, 1, __ATOMIC_RELEASE); + while (__atomic_load_n(&task_queue->end, __ATOMIC_ACQUIRE)) + sched_yield(); + + pthread_mutex_destroy(&task_queue->lock); + sem_destroy(&task_queue->full_sem); + sem_destroy(&task_queue->empty_sem); + free(task_queue->head); + task_queue->head = NULL; +} + +static int wd_init_async_polling_thread_per_numa(struct wd_env_config *config, + struct wd_env_config_per_numa *config_numa, + void *alg_poll_ctx) +{ + struct async_task_queue *task_queue, *queue_head; + int i, j, ret; + double num; + + if (!config_numa->async_ctx_num) + return 0; + + if (!config_numa->async_poll_num) { + WD_ERR("invalid async poll num (%lu) is set.\n", + config_numa->async_poll_num); + WD_ERR("change to default value: %d\n", WD_ASYNC_DEF_POLL_NUM); + config_numa->async_poll_num = WD_ASYNC_DEF_POLL_NUM; + } + + num = MIN(config_numa->async_poll_num, config_numa->async_ctx_num); + + /* make max task queues as the number of async ctxs */ + queue_head = calloc(config_numa->async_ctx_num, sizeof(*queue_head)); + if (!queue_head) + return -WD_ENOMEM; + + task_queue = queue_head; + for (i = 0; i < num; task_queue++, i++) { + ret = wd_init_one_task_queue(task_queue, alg_poll_ctx); + if (ret) { + for (j = 0; j < i; task_queue++, j++) + wd_uninit_one_task_queue(task_queue); + free(queue_head); + return ret; + } + } + + config_numa->async_task_queue_array = (void *)queue_head; + + return 0; +} + +static void wd_uninit_async_polling_thread_per_numa(struct wd_env_config *cfg, + struct wd_env_config_per_numa *config_numa) +{ + struct async_task_queue *task_queue, *head; + double num; + int i; + + if (!config_numa || !config_numa->async_task_queue_array) + return; + + head = config_numa->async_task_queue_array; + task_queue = head; + num = MIN(config_numa->async_poll_num, config_numa->async_ctx_num); + + for (i = 0; i < num; task_queue++, i++) + wd_uninit_one_task_queue(task_queue); + free(head); + config_numa->async_task_queue_array = NULL; +} + +static int wd_init_async_polling_thread(struct wd_env_config *config, + void *alg_poll_ctx) +{ + struct wd_env_config_per_numa *config_numa; + int i, ret; + + if (!config->enable_internal_poll) + return 0; + + FOREACH_NUMA(i, config, config_numa) { + ret = wd_init_async_polling_thread_per_numa(config, config_numa, + alg_poll_ctx); + if (ret) + goto out; + } + + return 0; + +out: + FOREACH_NUMA(i, config, config_numa) + wd_uninit_async_polling_thread_per_numa(config, config_numa); + + return ret; +} + +static void wd_uninit_async_polling_thread(struct wd_env_config *config) +{ + struct wd_env_config_per_numa *config_numa; + int i; + + if (!config->enable_internal_poll) + return; + + FOREACH_NUMA(i, config, config_numa) + wd_uninit_async_polling_thread_per_numa(config, config_numa); +} + +static int wd_init_resource(struct wd_env_config *config, + const struct wd_alg_ops *ops) +{ + int ret; + + ret = wd_alloc_ctx(config); + if (ret) + return ret; + + ret = wd_init_sched_config(config, ops->alg_poll_ctx); + if (ret) + goto err_uninit_ctx; + + ret = ops->alg_init(config->ctx_config, config->sched); + if (ret) + goto err_uninit_sched; + + ret = wd_init_async_polling_thread(config, ops->alg_poll_ctx); + if (ret) + goto err_uninit_alg; + + return 0; + +err_uninit_alg: + ops->alg_uninit(); +err_uninit_sched: + wd_uninit_sched_config(config); +err_uninit_ctx: + wd_free_ctx(config); + return ret; +} + +static void wd_uninit_resource(struct wd_env_config *config, + const struct wd_alg_ops *ops) +{ + wd_uninit_async_polling_thread(config); + ops->alg_uninit(); + wd_uninit_sched_config(config); + wd_free_ctx(config); +} + +int wd_alg_env_init(struct wd_env_config *env_config, + const struct wd_config_variable *table, + const struct wd_alg_ops *ops, + __u32 table_size, + struct wd_ctx_attr *ctx_attr) +{ + int ret; + + ret = wd_alloc_numa(env_config, ops); + if (ret) + return ret; + + ret = wd_init_env_config(env_config, ctx_attr, ops, table, table_size); + if (ret) + goto free_numa; + + ret = wd_init_resource(env_config, ops); + if (ret) + goto uninit_env_config; + + return 0; + +uninit_env_config: + wd_uninit_env_config(env_config); +free_numa: + wd_free_numa(env_config); + return ret; +} + +void wd_alg_env_uninit(struct wd_env_config *env_config, + const struct wd_alg_ops *ops) +{ + wd_uninit_resource(env_config, ops); + wd_uninit_env_config(env_config); + wd_free_numa(env_config); +} + +int wd_alg_get_env_param(struct wd_env_config *env_config, + struct wd_ctx_attr attr, + __u32 *num, __u8 *is_enable) +{ + struct wd_env_config_per_numa *config_numa; + + if (!num || !is_enable) { + WD_ERR("invalid: input pointer num or is_enable is NULL!\n"); + return -WD_EINVAL; + } + + *is_enable = env_config->enable_internal_poll; + + config_numa = wd_get_config_numa(env_config, attr.node); + if (!config_numa) + return -WD_EINVAL; + + *num = (config_numa->ctx_table) ? + config_numa->ctx_table[attr.mode][attr.type].size : 0; + + return 0; +} + +int wd_set_ctx_attr(struct wd_ctx_attr *ctx_attr, + __u32 node, __u32 type, __u8 mode, __u32 num) +{ + if (mode >= CTX_MODE_MAX) { + WD_ERR("invalid: ctx mode is %u!\n", mode); + return -WD_EINVAL; + } + + ctx_attr->node = node; + ctx_attr->mode = mode; + ctx_attr->num = num; + /* If type is CTX_TYPE_INVALID, we need update it to 0. */ + ctx_attr->type = (type == CTX_TYPE_INVALID) ? 0 : type; + + return 0; +} + +int wd_check_ctx(struct wd_ctx_config_internal *config, __u8 mode, __u32 idx) +{ + struct wd_ctx_internal *ctx; + + if (unlikely(idx >= config->ctx_num)) { + WD_ERR("failed to pick a proper ctx: idx %u!\n", idx); + return -WD_EINVAL; + } + + ctx = config->ctxs + idx; + if (ctx->ctx_mode != mode) { + WD_ERR("invalid: ctx(%u) mode is %hhu!\n", idx, ctx->ctx_mode); + return -WD_EINVAL; + } + + return 0; +} + +int wd_set_epoll_en(const char *var_name, bool *epoll_en) +{ + const char *s; + int ret; + + s = secure_getenv(var_name); + if (!s || !strlen(s)) { + *epoll_en = 0; + return 0; + } + + ret = str_to_bool(s, epoll_en); + if (ret) { + WD_ERR("failed to parse %s!\n", var_name); + return ret; + } + + if (*epoll_en) + WD_ERR("epoll wait is enabled!\n"); + + return 0; +} + +int wd_handle_msg_sync(struct wd_msg_handle *msg_handle, handle_t ctx, + void *msg, __u64 *balance, bool epoll_en) +{ + __u64 timeout = WD_RECV_MAX_CNT_NOSLEEP; + __u64 rx_cnt = 0; + int ret; + + if (balance) + timeout = WD_RECV_MAX_CNT_SLEEP; + + ret = msg_handle->send(ctx, msg); + if (unlikely(ret < 0)) { + WD_ERR("failed to send msg to hw, ret = %d!\n", ret); + return ret; + } + + do { + if (epoll_en) { + ret = wd_ctx_wait(ctx, POLL_TIME); + if (ret < 0) + WD_ERR("wd ctx wait timeout(%d)!\n", ret); + } + + ret = msg_handle->recv(ctx, msg); + if (ret == -WD_EAGAIN) { + if (unlikely(rx_cnt++ >= timeout)) { + WD_ERR("failed to recv msg: timeout!\n"); + return -WD_ETIMEDOUT; + } + + if (balance && *balance > WD_BALANCE_THRHD) + usleep(1); + } else if (unlikely(ret < 0)) { + WD_ERR("failed to recv msg: error = %d!\n", ret); + return ret; + } + } while (ret < 0); + + if (balance) + *balance = rx_cnt; + + return ret; +} + +int wd_init_param_check(struct wd_ctx_config *config, struct wd_sched *sched) +{ + if (!config || !config->ctxs || !config->ctxs[0].ctx) { + WD_ERR("invalid: config or config->ctxs is NULL!\n"); + return -WD_EINVAL; + } + + if (!sched) { + WD_ERR("invalid: sched is NULL!\n"); + return -WD_EINVAL; + } + + if (!wd_is_sva(config->ctxs[0].ctx)) { + WD_ERR("invalid: the mode is non sva, please check system!\n"); + return -WD_EINVAL; + } + + return 0; +} -- Gitee