From 47d038d38c0d355a9d3d17ed1c86c64e301dcee6 Mon Sep 17 00:00:00 2001 From: wuliaokanke Date: Sat, 3 Dec 2022 17:03:02 +0800 Subject: [PATCH 1/4] kae2 init --- README.md | 268 +----------------------------------------------------- 1 file changed, 1 insertion(+), 267 deletions(-) diff --git a/README.md b/README.md index 4411751..cf02b10 100644 --- a/README.md +++ b/README.md @@ -1,267 +1 @@ -# Kunpeng Accelerator Engine - -- [Introduction](#introduction) -- [License](#license) -- [Requirements](#requirements) -- [Installation Instructions](#installation-instructions) - - [Building OpenSSL](#building-openssl) - - [Cloning and Building Kunpeng Accelerator Engine](#cloning-and-building-kunpeng-acceleration-engine) - - [Testing Kunpeng Accelerator Engine](#testing-kunpeng-accelerator-engine) -- [Examples](#examples) -- [Troubleshooting](#troubleshooting) -- [Loading Engines by Setting the OpenSSL Configuration File](#loading-engines-by-setting-the-openssl-configuration-file) -- [Contribution Guidelines](#contribution-Guidelines) -- [Vulnerability Management](#Vulnerability-Management) -- [Quality Requirements](#Quality-Requirements) -- [Secure Design](#Secure-Design) -- [ReleaseNote](#ReleaseNote) -- [More Information](#more-information) -- [Copyright](#copyright) - -## Introduction - -Kunpeng Accelerator Engine is to build performance competitiveness of common software libraries on the Kunpeng platform. - -Kunpeng Accelerator Engine is a new technology within Hisilicon Kunpeng 920 processors which - -provides a hardware-enabled foundation for security, authentication, and compression. It significantly increases the performance across cloud, networking, big data, and storage applications and platforms. - -Kunpeng Accelerator Engine includes symmetric encryption, asymmetric encryption, digital signatures, and RSA for accelerating SSL/TLS application, which makes processors more efficient and reduces hardware costs. By accelerating SSL/TLS with Kunpeng Accelerator Engine, you can: - -- Support higher-performance secured tunnels and a greater number of authenticated clients -- Have higher-performance encrypted traffic throughout a secured network -- Accelerate compute-intense symmetric and asymmetric cryptography -- Have greater platform application efficiency -- Have higher-performance compression and decompression -- Maximize CPU utilization - -So far, the algorithms supported by Kunpeng Accelerator Engine are: - -- Asymmetric encryption algorithm: RSA Support Key Sizes 1024/2048/3072/4096 -- Digest algorithm: SM3/MD5 -- Block cipher algorithm: SM4 Support CTR/XTS/CBC/ECB/OFB -- Block cipher algorithm: AES Support CTR/XTS/CBC/ECB -- Key exchange algorithm: DH Support 768bit/1024bit/1536bit/2048bit/3072bit/4096bit - -## License - -It is licensed under the [APACHE LICENSE, VERSION 2.0](https://www.apache.org/licenses/LICENSE-2.0 ). For more information, see the LICENSE file. - -## Requirements - -* CPU: Kunpeng 920 -* Operating System: - * CentOS 7.6 4.14.0-115.el7a.0.1.aarch64 version - * SuSE 15.1 4.12.14-195-default arch64 version - * NeoKylin 7.6 4.14.0-115.5.1.el7a.06.aarch64 version - * EulerOS 2.8 4.19.36-vhulk1907.1.0.h410.eulerosv2r8.aarch64 version - * BCLinux-R7-U6-Server-aarch64 version - * Kylin 4.0.2 (juniper) 4.15.0-70-generic version - * Kylin release 4.0.2 (SP2) 4.19.36-vhulk1907.1.0.h403.ky4.aarch64 version - * UniKylin Linux release 3(Core) 4.18.0-80.ky3.kb21.hw.aarch64 version - * Ubuntu 18.04.1 LTS 4.15.0-29-generic version -* OpenSSL 1.1.1a or later OpenSSL - -## Installation Instructions - -### Building OpenSSL - -Clone OpenSSL from Github at the following location: - - git clone https://github.com/openssl/openssl.git - -You are advised to check out and build the OpenSSL 1.1.1a git tag specified in the release notes. -Versions of OpenSSL before OpenSSL 1.1.0 are not supported. - -Note: You are not advised to install the accelerated version of OpenSSL as your default system library. Otherwise, acceleration may be used unexpectedly by other applications on the system, resulting in undesired/unsupported behavior. The `--prefix` can be used with the `./config` command to specify the location that `make install` will copy files to. Please see the OpenSSL INSTALL file for full details on usage of the `--prefix` option. - -By default, we usually install OpenSSL as follows: - - ./config -Wl,-rpath=/usr/local/lib - make - make install -The `-Wl,-rpath` option can specify the openssl shared libraries where the binaries will link to. - -### Cloning and Building Kunpeng Accelerator Engine - -Clone the Github repository containing the Kunpeng Accelerator Engine: - - git clone https://github.com/kunpengcompute/KAE - -Download the release version of Kunpeng Accelerator Engine Driver from: - - - -Firstly, build and install the accelerator driver. -Note: To build the Kunpeng Accelerator Engine Driver, install the `kernel-devel` package first. - -``` -tar -zxf Kunpeng_KAE_driver.tar.gz -cd kae_driver -make -make install -modprobe uacce -modprobe hisi_qm -modprobe hisi_sec2 -modprobe hisi_hpre -modprobe hisi_zip -modprobe hisi_rde -``` -Secondly, install the accelerator library: - -``` -cd warpdrive -sh autogen.sh -./configure -make -make install -``` - -Then, install the Kunpeng Accelerator Engine: - -``` -cd KAE -./configure -make -make install - -``` - -Note1: The `--openssl_path` can be used with the `./configure` command to specify the location that `make install` will copy files to. The default installation path for the accelerator engine is `/usr/local/lib/openssl-1.1`. You are advised to install the Kunpeng Accelerator Engine as a default OpenSSL engine. -Export the environment variables `OPENSSL_ENGINES` as follows : - -``` -export OPENSSL_ENGINES=/usr/local/lib/engines-1.1 -``` -Note2: by default, KAE supports algorithms supported by all specifications. If you do not need to compile an algorithm, you can configure macros. The following configuration macros are supported: KAE_NO_DIGEST_METH, KAE_NO_DH_METH, KAE_NO_CIPHER_METH, and KAE_NO_RSA_METH.The file KAE/Makefile need to be modified. -If the KAE does not compile the RSA algorithm, the -D KAE_NO_RSA_METH configuration needs to be added to the CFLAGS configuration. For example:CFLAGS := -Wall -Werror -fstack-protector-all -fPIC -D_GNU_SOURCE -shared -fgnu89-inline -D KAE_NO_RSA_METH - -For more install guid and user guid, get information at: - - -### Testing Kunpeng Accelerator Engine - -Run the following command to check when the Kunpeng Accelerator Engine is loaded correctly: - -``` -cd /usr/local/bin/ -./openssl genrsa -out test.key -engine kae 2048 -./openssl rsa -in test.key -pubout -out test_pub.key -engine kae -echo asdsdf3246wdgg1024 > rsa_test -./openssl rsautl -encrypt -in rsa_test -inkey test_pub.key -pubin -out rsa_test.en -engine kae -./openssl rsautl -decrypt -in rsa_test.en -inkey test.key -out rsa_test.de -engine kae -``` - -``` -dd if=/dev/urandom of=sm4_test bs=M count=1 -./openssl enc -sm4-cbc -a -in sm4_test -out sm4_test.en -pass pass:123456 -engine kae -./openssl enc -sm4-cbc -a -in sm4_test -out sm4_test.en -pass pass:123456 -p -engine kae -./openssl enc -sm4-cbc -d -a -in sm4_test.en -out sm4_test.de -pass pass:123456 -engine kae - -dd if=/dev/urandom of=sm3_test bs=M count=1 -./openssl sm3 -out sm3_out -engine kae sm3_test -``` - -## Examples - -Here is an example to show you how to use the Kunpeng Accelerator Engine. - -``` -#include -#include - -/* OpenSSL headers */ -#include -#include -#include - -int main(int argc, char **argv) -{ - /* Initializing OpenSSL */ - ERR_load_BIO_strings(); - OpenSSL_add_all_algorithms(); - - /* You can use ENGINE_by_id Function to get the handle of the Kunpeng Accelerator Engine */ - ENGINE *e = ENGINE_by_id("kae"); - ENGINE_init(e); - - /* Set the default RSA algorithms computed by KAE engine, more usage methods about ENGINE_set_default, please refer to OpenSSL official website */ - ENGINE_set_default_RSA(e); - - /*The user code To Do */ - ... - - ENGINE_free(e); -} - -``` - -## Troubleshooting - -The most likely failure point is that the Kunpeng Accelerator Engine is not loaded successfully. If this occurs: - - 1. Check whether the accelerator driver has been loaded successfully by running the `lsmod` command. - - `uacce.ko, hisi_qm.ko, sgl.ko, hisi_sec2.ko, hisi_hpre.ko, hisi_zip.ko` should be in the list. - - 2. Check whether the paths have been set correctly so that the `libkae.so` engine file can be copied to the correct location. - - 3. Check whether the installation path has been correctly added to the environment variable `OPENSSL_ENGINES` and exported to the shell by running the `export` command. - -## Loading Engines by Setting the OpenSSL Configuration File - -By setting up the OpenSSL configuration file, you can also initialize the Kunpeng Accelerator Engine for your OpenSSL application. For further details on using the `openssl.cnf` file, see the OpenSSL online documentation at: - - - -Here is an example to show you how to set up the `openssl.cnf` file to load engines. Add the following statements to the global section (assuming that the path is the one that KAE installed): - - openssl_conf = openssl_engine_init - - [ openssl_engine_init ] - engines = engine_section - - [ engine_section ] - kae = kae_section - - [ kae_section ] - engine_id = kae - dynamic_path = /usr/local/lib/engines-1.1/kae.so - -Export the environment variableas `OPENSSL_CONF` as follows : - -``` -export OPENSSL_CONF=/home/app/openssl.cnf -``` - -By loading the openssl configuration file, the user application does not need to modify any code, except for loading KAE through the following API during initialization. - -``` -OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL); -``` -## Contribution Guidelines - -If you want to contribute to KAE, please use GitHub [issues](https://github.com/kunpengcompute/KAE/issues/new) for tracking requests and bugs. - -## Vulnerability Management -Please refer to https://github.com/kunpengcompute/Kunpeng#security - -## Quality Requirements -Please refer to [Secure Coding Specifications](https://github.com/kunpengcompute/Kunpeng/blob/master/security/SecureCoding.md). - -## Secure Design -Please refer to [Secure Design](https://github.com/kunpengcompute/Kunpeng/blob/master/security/SecureDesign.md). - -## ReleaseNote -The latest version 1.3.11 is recommended. -Please refer to https://github.com/kunpengcompute/KAE/blob/master/ReleaseNote - -## More Information - -For further assistance and more QAs, contact Huawei Support at: - - - -## Copyright - -Copyright © 2018 Huawei Corporation. All rights reserved. +kae2 -- Gitee From 8fdc7b15c7f586d3ccae7b51a557fe9e63ab3f6f Mon Sep 17 00:00:00 2001 From: wuliaokanke Date: Sat, 3 Dec 2022 17:09:21 +0800 Subject: [PATCH 2/4] del kae1 --- LICENSE | 201 --------- Makefile | 110 ----- README.md | 1 - ReleaseNote | 9 - alg/ciphers/sec_ciphers.c | 759 -------------------------------- alg/ciphers/sec_ciphers.h | 103 ----- alg/ciphers/sec_ciphers_soft.c | 334 -------------- alg/ciphers/sec_ciphers_soft.h | 53 --- alg/ciphers/sec_ciphers_utils.c | 217 --------- alg/ciphers/sec_ciphers_utils.h | 60 --- alg/ciphers/sec_ciphers_wd.c | 304 ------------- alg/ciphers/sec_ciphers_wd.h | 48 -- alg/dh/hpre_dh.c | 314 ------------- alg/dh/hpre_dh.h | 34 -- alg/dh/hpre_dh_soft.c | 120 ----- alg/dh/hpre_dh_soft.h | 50 --- alg/dh/hpre_dh_util.h | 33 -- alg/dh/hpre_dh_wd.c | 429 ------------------ alg/dh/hpre_dh_wd.h | 88 ---- alg/digests/sec_digests.c | 586 ------------------------ alg/digests/sec_digests.h | 83 ---- alg/digests/sec_digests_soft.c | 118 ----- alg/digests/sec_digests_soft.h | 43 -- alg/digests/sec_digests_wd.c | 259 ----------- alg/digests/sec_digests_wd.h | 40 -- alg/pkey/hpre_rsa.c | 717 ------------------------------ alg/pkey/hpre_rsa.h | 73 --- alg/pkey/hpre_rsa_soft.c | 69 --- alg/pkey/hpre_rsa_soft.h | 29 -- alg/pkey/hpre_rsa_utils.c | 562 ----------------------- alg/pkey/hpre_rsa_utils.h | 45 -- alg/pkey/hpre_wd.c | 464 ------------------- alg/pkey/hpre_wd.h | 91 ---- async/async_callback.c | 65 --- async/async_callback.h | 38 -- async/async_event.c | 194 -------- async/async_event.h | 42 -- async/async_poll.c | 154 ------- async/async_poll.h | 28 -- async/async_task_queue.c | 192 -------- async/async_task_queue.h | 72 --- configure | 92 ---- engine_kae.c | 392 ----------------- engine_kae.h | 35 -- utils/engine_check.c | 147 ------- utils/engine_check.h | 42 -- utils/engine_config.c | 110 ----- utils/engine_config.h | 29 -- utils/engine_fork.c | 75 ---- utils/engine_fork.h | 26 -- utils/engine_log.c | 256 ----------- utils/engine_log.h | 108 ----- utils/engine_opensslerr.c | 121 ----- utils/engine_opensslerr.h | 106 ----- utils/engine_types.h | 31 -- utils/engine_utils.c | 104 ----- utils/engine_utils.h | 132 ------ wdmngr/wd_alg_queue.c | 74 ---- wdmngr/wd_alg_queue.h | 31 -- wdmngr/wd_queue_memory.c | 569 ------------------------ wdmngr/wd_queue_memory.h | 110 ----- 61 files changed, 9821 deletions(-) delete mode 100644 LICENSE delete mode 100644 Makefile delete mode 100644 README.md delete mode 100644 ReleaseNote delete mode 100644 alg/ciphers/sec_ciphers.c delete mode 100644 alg/ciphers/sec_ciphers.h delete mode 100644 alg/ciphers/sec_ciphers_soft.c delete mode 100644 alg/ciphers/sec_ciphers_soft.h delete mode 100644 alg/ciphers/sec_ciphers_utils.c delete mode 100644 alg/ciphers/sec_ciphers_utils.h delete mode 100644 alg/ciphers/sec_ciphers_wd.c delete mode 100644 alg/ciphers/sec_ciphers_wd.h delete mode 100644 alg/dh/hpre_dh.c delete mode 100644 alg/dh/hpre_dh.h delete mode 100644 alg/dh/hpre_dh_soft.c delete mode 100644 alg/dh/hpre_dh_soft.h delete mode 100644 alg/dh/hpre_dh_util.h delete mode 100644 alg/dh/hpre_dh_wd.c delete mode 100644 alg/dh/hpre_dh_wd.h delete mode 100644 alg/digests/sec_digests.c delete mode 100644 alg/digests/sec_digests.h delete mode 100644 alg/digests/sec_digests_soft.c delete mode 100644 alg/digests/sec_digests_soft.h delete mode 100644 alg/digests/sec_digests_wd.c delete mode 100644 alg/digests/sec_digests_wd.h delete mode 100644 alg/pkey/hpre_rsa.c delete mode 100644 alg/pkey/hpre_rsa.h delete mode 100644 alg/pkey/hpre_rsa_soft.c delete mode 100644 alg/pkey/hpre_rsa_soft.h delete mode 100644 alg/pkey/hpre_rsa_utils.c delete mode 100644 alg/pkey/hpre_rsa_utils.h delete mode 100644 alg/pkey/hpre_wd.c delete mode 100644 alg/pkey/hpre_wd.h delete mode 100644 async/async_callback.c delete mode 100644 async/async_callback.h delete mode 100644 async/async_event.c delete mode 100644 async/async_event.h delete mode 100644 async/async_poll.c delete mode 100644 async/async_poll.h delete mode 100644 async/async_task_queue.c delete mode 100644 async/async_task_queue.h delete mode 100755 configure delete mode 100644 engine_kae.c delete mode 100644 engine_kae.h delete mode 100644 utils/engine_check.c delete mode 100644 utils/engine_check.h delete mode 100644 utils/engine_config.c delete mode 100644 utils/engine_config.h delete mode 100644 utils/engine_fork.c delete mode 100644 utils/engine_fork.h delete mode 100644 utils/engine_log.c delete mode 100644 utils/engine_log.h delete mode 100644 utils/engine_opensslerr.c delete mode 100644 utils/engine_opensslerr.h delete mode 100644 utils/engine_types.h delete mode 100644 utils/engine_utils.c delete mode 100644 utils/engine_utils.h delete mode 100644 wdmngr/wd_alg_queue.c delete mode 100644 wdmngr/wd_alg_queue.h delete mode 100644 wdmngr/wd_queue_memory.c delete mode 100644 wdmngr/wd_queue_memory.h diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 360db8c..0000000 --- a/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - 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/Makefile b/Makefile deleted file mode 100644 index 8f8b26b..0000000 --- a/Makefile +++ /dev/null @@ -1,110 +0,0 @@ -# -# Author: wudinggui -# Date: 2019/7/4 - -# Description: -# compile for accelerator -# -# Usage: -# $ make compile and link the program. -# $ make rebuild rebuild the program. The same as make clean && make all. -# $ make clean clean the objective, dependent and executable files. -# $ make install copy to the system directory. -# $ make uninstall clean the executable file from the system directory. -#============================================================================== -WORK_PATH := . -ENGINE_INSTALL_PATH := $(OPENSSL_WORK_PATH)/lib/engines-1.1 - -CC=gcc - -LIBNAME := libkae.so -VERSION = 1.3.11 -TARGET = ${LIBNAME}.${VERSION} -SOFTLINK = kae.so - -ifndef SILENCE - SILENCE = @ -endif - -# Src -SRCDIRS := ${WORK_PATH}/ -SRCDIRS += ${WORK_PATH}/alg/pkey -SRCDIRS += ${WORK_PATH}/alg/dh -SRCDIRS += ${WORK_PATH}/alg/ciphers -SRCDIRS += ${WORK_PATH}/alg/digests -SRCDIRS += ${WORK_PATH}/async -SRCDIRS += ${WORK_PATH}/wdmngr -SRCDIRS += ${WORK_PATH}/utils - -SRCEXTS := .c # C program - -# Include -INCDIR += -I $(WORK_PATH)/ -INCDIR += -I $(WORK_PATH)/alg/pkey -INCDIR += -I $(WORK_PATH)/alg/dh -INCDIR += -I $(WORK_PATH)/alg/ciphers -INCDIR += -I $(WORK_PATH)/alg/digests -INCDIR += -I $(WORK_PATH)/async -INCDIR += -I $(WORK_PATH)/wdmngr -INCDIR += -I $(WORK_PATH)/utils -INCDIR += -I $(OPENSSL_WORK_PATH)/include - -# Include Libs. -LIBDIR := -L$(OPENSSL_WORK_PATH)/lib -LIBDIR += -L/usr/lib64 -LIBS := -lcrypto -lwd -pthread -LIBS += -lc_nonshared - -# The flags -CFLAGS := -Wall -Werror -fstack-protector-all -fPIC -D_GNU_SOURCE -shared -fgnu89-inline -LDFLAGS := $(LIBDIR) -LDFLAGS += $(LIBS) -LDFLAGS += -Wl,-z,relro,-z,now,-z,noexecstack #safe link option - -# The command used to delete file. -RM = rm -f -LN = ln -sf - -SOURCES = $(foreach d,$(SRCDIRS),$(wildcard $(addprefix $(d)/*,$(SRCEXTS)))) - -OBJS = $(foreach x,$(SRCEXTS), \ - $(patsubst %$(x), %.o, $(filter %$(x),$(SOURCES)))) - -.PHONY : all objs clean cleanall rebuild - -all : $(TARGET) - -# Rules for creating the dependency files (.d). -%.d : %.c - $(CC) -MM -MD $(CFLAGS) $< - -# Rules for producing the objects. -objs : $(OBJS) -%.o : %.c - @echo compiling $(notdir $<) - $(SILENCE) $(CC) -c $(CFLAGS) $(INCDIR) $(LDFLAGS) -o $@ $< - -$(TARGET): $(OBJS) - @echo Linking $@ - $(SILENCE) $(CC) $(CFLAGS) $(INCDIR) -o ./$(TARGET) $(OBJS) $(LDFLAGS) - -@objcopy --only-keep-debug ./$(TARGET) $(TARGET).symbol - -@strip ./$(TARGET) -rebuild: clean all - -clean : - @-$(RM) *.d *.a *.so *.symbol $(TARGET) - @-$(RM) - @find ${WORK_PATH} -name '*.o' -exec $(RM) {} \; - @echo all clean - -install : - mkdir -p $(ENGINE_INSTALL_PATH) - install -m 755 $(TARGET) $(ENGINE_INSTALL_PATH) - $(LN) $(ENGINE_INSTALL_PATH)/$(TARGET) $(ENGINE_INSTALL_PATH)/$(SOFTLINK) - $(LN) $(ENGINE_INSTALL_PATH)/$(TARGET) $(ENGINE_INSTALL_PATH)/$(SOFTLINK).0 -uninstall : - $(RM) $(ENGINE_INSTALL_PATH)/$(SOFTLINK) - $(RM) $(ENGINE_INSTALL_PATH)/$(SOFTLINK).0 - $(RM) $(ENGINE_INSTALL_PATH)/$(TARGET) - $(RM) /var/log/kae.log - $(RM) /var/log/kae.log.old diff --git a/README.md b/README.md deleted file mode 100644 index cf02b10..0000000 --- a/README.md +++ /dev/null @@ -1 +0,0 @@ -kae2 diff --git a/ReleaseNote b/ReleaseNote deleted file mode 100644 index 3ca5527..0000000 --- a/ReleaseNote +++ /dev/null @@ -1,9 +0,0 @@ -ReleaseNote -The latest version is 1.3.11. -1.3.11 Updated the content: - 1.update kae version to 1.3.11 - 2.bugfix for libkae:fix libkae support custom location installation - 3.bugfix for kaezip:resolve multi-thread contention lock,causing crashes - 4.bugfix for kaezip:ceph cluster object storage, When KAEzip is used to compress data larger than 4 MB in the ceph cluster object storage, an error is returned and the minor - bug is fixed, see the FAQ link:https://support.huaweicloud.com/kunpengaccel_faq/kunpengaccel_10_0021.html - diff --git a/alg/ciphers/sec_ciphers.c b/alg/ciphers/sec_ciphers.c deleted file mode 100644 index bb623b8..0000000 --- a/alg/ciphers/sec_ciphers.c +++ /dev/null @@ -1,759 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the implemenation for KAE engine ciphers - * - * 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. - */ - -/***************************************************************************** - -* @file sec_ciphers.c -* -* This file provides the implemenation for ciphers -* -*****************************************************************************/ -#include "sec_ciphers.h" -#include "sec_ciphers_soft.h" -#include "sec_ciphers_utils.h" -#include "sec_ciphers_wd.h" - -#include "engine_check.h" -#include "engine_types.h" -#include "engine_utils.h" -#include "async_callback.h" -#include "async_event.h" -#include "async_task_queue.h" - -#define INPUT_CACHE_SIZE (256 * 1024) - -struct cipher_info { - int nid; - int blocksize; - int keylen; - int ivlen; - int flags; - int is_enabled; - EVP_CIPHER *cipher; -}; -typedef struct cipher_info cipher_info_t; - -static cipher_info_t g_sec_ciphers_info[] = { - {NID_aes_128_ecb, 16, 16, 0, EVP_CIPH_ECB_MODE, 1, NULL}, - {NID_aes_192_ecb, 16, 24, 0, EVP_CIPH_ECB_MODE, 1, NULL}, - {NID_aes_256_ecb, 16, 32, 0, EVP_CIPH_ECB_MODE, 1, NULL}, - {NID_aes_128_cbc, 16, 16, 16, EVP_CIPH_CBC_MODE, 1, NULL}, - {NID_aes_192_cbc, 16, 24, 16, EVP_CIPH_CBC_MODE, 1, NULL}, - {NID_aes_256_cbc, 16, 32, 16, EVP_CIPH_CBC_MODE, 1, NULL}, - {NID_aes_128_ctr, 1, 16, 16, EVP_CIPH_CTR_MODE, 1, NULL}, - {NID_aes_192_ctr, 1, 24, 16, EVP_CIPH_CTR_MODE, 1, NULL}, - {NID_aes_256_ctr, 1, 32, 16, EVP_CIPH_CTR_MODE, 1, NULL}, - {NID_aes_128_xts, 1, 32, 16, EVP_CIPH_XTS_MODE | EVP_CIPH_CUSTOM_IV, 1, NULL}, - {NID_aes_256_xts, 1, 64, 16, EVP_CIPH_XTS_MODE | EVP_CIPH_CUSTOM_IV, 1, NULL}, - - {NID_sm4_ctr, 1, 16, 16, EVP_CIPH_CTR_MODE, 1, NULL}, - {NID_sm4_cbc, 16, 16, 16, EVP_CIPH_CBC_MODE | EVP_CIPH_FLAG_DEFAULT_ASN1, 1, NULL}, - {NID_sm4_ofb128, 1, 16, 16, EVP_CIPH_OFB_MODE, 1, NULL}, - {NID_sm4_ecb, 16, 16, 0, EVP_CIPH_CTR_MODE, 1, NULL}, -}; - -#define CIPHERS_COUNT (BLOCKSIZES_OF(g_sec_ciphers_info)) - -static int g_known_cipher_nids[CIPHERS_COUNT] = { - NID_aes_128_ecb, - NID_aes_192_ecb, - NID_aes_256_ecb, - NID_aes_128_cbc, - NID_aes_192_cbc, - NID_aes_256_cbc, - NID_aes_128_ctr, - NID_aes_192_ctr, - NID_aes_256_ctr, - NID_aes_128_xts, - NID_aes_256_xts, - - NID_sm4_ctr, - NID_sm4_cbc, - NID_sm4_ofb128, - NID_sm4_ecb, -}; - -#define SEC_CIPHERS_RETURN_FAIL_IF(cond, mesg, ret)\ - if (unlikely(cond)) {\ - US_ERR(mesg);\ - return (ret);\ - }\ - -#define SEC_CIPHERS_GOTO_FAIL_IF(cond, mesg, tag)\ - if (unlikely(cond)) {\ - US_ERR(mesg);\ - goto tag;\ - }\ - -static int sec_ciphers_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int encrypt); -static int sec_ciphers_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl); -static int sec_ciphers_cleanup(EVP_CIPHER_CTX *ctx); -static int sec_ciphers_priv_ctx_cleanup(EVP_CIPHER_CTX *ctx); -static int sec_ciphers_is_check_valid(EVP_CIPHER_CTX *ctx, cipher_priv_ctx_t *priv_ctx); -static int sec_ciphers_async_do_crypto(cipher_engine_ctx_t *e_cipher_ctx, op_done_t *op_done); - -void sec_ciphers_set_enabled(int nid, int enabled) -{ - unsigned int i = 0; - for (i = 0; i < CIPHERS_COUNT; i++) { - if (g_sec_ciphers_info[i].nid == nid) { - g_sec_ciphers_info[i].is_enabled = enabled; - } - } -} - -static int sec_ciphers_sync_do_crypto(EVP_CIPHER_CTX *ctx, cipher_engine_ctx_t *e_cipher_ctx, - cipher_priv_ctx_t *priv_ctx); - -static int sec_ciphers_init_priv_ctx(cipher_priv_ctx_t *priv_ctx, EVP_CIPHER_CTX *ctx, - const unsigned char *key, const unsigned char *iv) -{ - int nid = 0; - int ret = KAE_FAIL; - - SEC_CIPHERS_RETURN_FAIL_IF(ctx == NULL || priv_ctx == NULL, "null ctx or priv ctx", KAE_FAIL); - - // init encrypt of private ctx - priv_ctx->encrypt = EVP_CIPHER_CTX_encrypting(ctx); - // init offset of private ctx - priv_ctx->offset = 0; - // init key of private ctx - if (priv_ctx->key == NULL) { - priv_ctx->key = (uint8_t *)kae_malloc(EVP_CIPHER_CTX_key_length(ctx)); - SEC_CIPHERS_GOTO_FAIL_IF(priv_ctx->key == NULL, "malloc key failed", ERR); - } - - kae_memcpy(priv_ctx->key, key, EVP_CIPHER_CTX_key_length(ctx)); - priv_ctx->key_len = EVP_CIPHER_CTX_key_length(ctx); - - // init iv of private ctx - if (priv_ctx->iv == NULL) { - priv_ctx->iv = (uint8_t *)kae_malloc(EVP_CIPHER_CTX_iv_length(ctx)); - SEC_CIPHERS_GOTO_FAIL_IF(priv_ctx->iv == NULL, "malloc iv failed.", ERR); - } - if (iv != NULL) { - kae_memcpy(priv_ctx->iv, iv, EVP_CIPHER_CTX_iv_length(ctx)); - } else { - kae_memcpy(priv_ctx->iv, EVP_CIPHER_CTX_iv_noconst(ctx), EVP_CIPHER_CTX_iv_length(ctx)); - } - priv_ctx->iv_len = EVP_CIPHER_CTX_iv_length(ctx); - - if (priv_ctx->next_iv == NULL) { - priv_ctx->next_iv = (uint8_t *)kae_malloc(priv_ctx->iv_len); - SEC_CIPHERS_GOTO_FAIL_IF(priv_ctx->next_iv == NULL, "malloc next iv failed.", ERR); - } - - // init cipher mode and alg of private ctx - nid = EVP_CIPHER_CTX_nid(ctx); - priv_ctx->c_mode = sec_ciphers_get_cipher_mode(nid); - priv_ctx->c_alg = sec_ciphers_get_cipher_alg(nid); - SEC_CIPHERS_GOTO_FAIL_IF(priv_ctx->c_mode == NO_C_MODE || priv_ctx->c_alg == NO_C_ALG, - "unsupport the cipher nid", ERR); - - if (priv_ctx->ecb_encryto == NULL && priv_ctx->c_mode == XTS) { - // set XTS PARAM - priv_ctx->ecb_encryto = (xts_ecb_data *)kae_malloc(sizeof(xts_ecb_data)); - SEC_CIPHERS_GOTO_FAIL_IF(priv_ctx->ecb_encryto == NULL, "malloc ecb ctx", ERR); - - priv_ctx->ecb_encryto->ecb_ctx = EVP_CIPHER_CTX_new(); - priv_ctx->ecb_encryto->key2_len = priv_ctx->key_len >> 1; - priv_ctx->ecb_encryto->key2 = (uint8_t *)kae_malloc(priv_ctx->key_len >> 1); - priv_ctx->ecb_encryto->encryto_iv = (uint8_t *)kae_malloc(priv_ctx->iv_len); - priv_ctx->ecb_encryto->iv_out = (uint8_t *)kae_malloc(priv_ctx->iv_len); - if (priv_ctx->ecb_encryto->ecb_ctx == NULL - || priv_ctx->ecb_encryto->key2 == NULL - || priv_ctx->ecb_encryto->encryto_iv == NULL - || priv_ctx->ecb_encryto->iv_out == NULL) { - if (priv_ctx->ecb_encryto->ecb_ctx != NULL) { - EVP_CIPHER_CTX_free(priv_ctx->ecb_encryto->ecb_ctx); - priv_ctx->ecb_encryto->ecb_ctx = NULL; - } - - kae_free(priv_ctx->ecb_encryto->key2); - kae_free(priv_ctx->ecb_encryto->encryto_iv); - kae_free(priv_ctx->ecb_encryto->iv_out); - kae_free(priv_ctx->ecb_encryto); - goto ERR; - } - - if (priv_ctx->ecb_encryto->key2_len == 32) { // 256-xts key2len is 32 - priv_ctx->ecb_encryto->cipher_type = EVP_aes_256_ecb(); - } else { - priv_ctx->ecb_encryto->cipher_type = EVP_aes_128_ecb(); - } - priv_ctx->ecb_encryto->countNum = 0; - kae_memcpy(priv_ctx->ecb_encryto->key2, - priv_ctx->key + priv_ctx->ecb_encryto->key2_len, - priv_ctx->ecb_encryto->key2_len); - } - -#ifndef OPENSSL_ENABLE_KAE_SMALL_PACKKET_CIPHER_OFFLOADS - ret = sec_ciphers_sw_impl_init(ctx, key, iv, priv_ctx->encrypt); - SEC_CIPHERS_GOTO_FAIL_IF(ret != KAE_SUCCESS, "kae sw iml init failed", ERR); - - priv_ctx->switch_threshold = - (size_t)sec_ciphers_sw_get_threshold(EVP_CIPHER_CTX_nid(ctx)); -#endif - - return KAE_SUCCESS; - -ERR: - US_ERR("sec_ciphers_sec_state_init failed. ctx=%p", ctx); - (void)sec_ciphers_priv_ctx_cleanup(ctx); - return KAE_FAIL; -} - -static int sec_ciphers_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, - const unsigned char *iv, int encrypt) -{ - cipher_priv_ctx_t *priv_ctx = NULL; - if (unlikely((ctx == NULL) || (key == NULL))) { - US_ERR("ctx or key is NULL."); - return OPENSSL_FAIL; - } - - if (encrypt != EVP_CIPHER_CTX_encrypting(ctx)) { - US_ERR("encrypt different, ctx=%p", ctx); - return OPENSSL_FAIL; - } - - priv_ctx = (cipher_priv_ctx_t *)EVP_CIPHER_CTX_get_cipher_data(ctx); - if (unlikely(priv_ctx == NULL)) { - US_ERR("sec private ctx is NULL"); - return OPENSSL_FAIL; - } - - if (KAE_SUCCESS != sec_ciphers_init_priv_ctx(priv_ctx, ctx, key, iv)) { - US_ERR("init failed. ctx=%p", ctx); - goto ERR; - } - US_DEBUG("init success, ctx=%p", ctx); -#ifdef KAE_DEBUG_KEY_ENABLE - dump_data("key", priv_ctx->key, priv_ctx->key_len); - dump_data("iv", priv_ctx->iv, priv_ctx->iv_len); -#endif - return OPENSSL_SUCCESS; -ERR: - sec_ciphers_cleanup(ctx); - return OPENSSL_SUCCESS; -} - -static void sec_ciphers_update_priv_ctx(cipher_priv_ctx_t *priv_ctx) -{ - uint32_t do_cipher_len = priv_ctx->do_cipher_len; - uint32_t increase_counter = 0; - - if (do_cipher_len == 0) { - return; - } - - priv_ctx->in += priv_ctx->do_cipher_len; - priv_ctx->out += priv_ctx->do_cipher_len; - priv_ctx->left_len -= priv_ctx->do_cipher_len; - - switch (priv_ctx->c_mode) { - case ECB: - break; - case CBC: - if (priv_ctx->encrypt == OPENSSL_ENCRYPTION) { - kae_memcpy(priv_ctx->iv, priv_ctx->out - 16, 16); // hardware need 16-byte alignment - } else { - kae_memcpy(priv_ctx->iv, priv_ctx->next_iv, 16); // hardware need 16-byte alignment - } - break; - case CTR: - increase_counter = (do_cipher_len + priv_ctx->offset) >> 4; // right shift 4 - sec_ciphers_ctr_iv_inc(priv_ctx->iv, increase_counter); - priv_ctx->offset = (priv_ctx->offset + (do_cipher_len & 0xf)) % 16; // hardware need 16-byte alignment - break; - case XTS: - if (priv_ctx->c_alg == AES) { - priv_ctx->ecb_encryto->countNum = (priv_ctx->do_cipher_len + priv_ctx->offset) >> 4; // right shift 4 - sec_ciphers_xts_iv_inc(priv_ctx); - priv_ctx->offset = (priv_ctx->offset + (do_cipher_len & 0xf)) % 16; // hardware need 16-byte alignment - } - break; - case OFB: - kae_memcpy(priv_ctx->iv, (uint8_t*)priv_ctx->e_cipher_ctx->op_data.iv, - priv_ctx->e_cipher_ctx->op_data.iv_bytes); - break; - default: - US_WARN("mode=%d don't support.", priv_ctx->c_mode); - break; - } - - US_DEBUG("update priv_ctx success."); - return; -} - -static int sec_ciphers_before_dociphers_cb(cipher_priv_ctx_t *priv_ctx) -{ - // store IV for next cbc decryption operation - if (priv_ctx->encrypt == OPENSSL_DECRYPTION && priv_ctx->c_mode == CBC) { - kae_memcpy(priv_ctx->next_iv, priv_ctx->in + priv_ctx->do_cipher_len - priv_ctx->iv_len, priv_ctx->iv_len); - } - - if (priv_ctx->c_mode == XTS && priv_ctx->c_alg == AES) { - sec_ciphers_ecb_encryt(priv_ctx->ecb_encryto, - priv_ctx->ecb_encryto->encryto_iv, - priv_ctx->iv, priv_ctx->iv_len); - } - - return KAE_SUCCESS; -} - -static int sec_ciphers_after_dociphers_cb(EVP_CIPHER_CTX *ctx) -{ - // sync priv ctx to next cipher, in case next cipher may be soft cipher - return sec_ciphers_sw_hw_ctx_sync(ctx, SEC_CIHPER_SYNC_H2S); -} - -/* - * |<--16*n bytes--> |<----16*n bytes------->|<--16*n bytes--->| - * |-----------------|<--offset----->|<----->|-----------------| - * |<--first cipher----------------->|<---next cipher--------->| - * - * - * to make 16*n align to next cipher data copy to hardware addr should start at - * hardware_addr+offset and get out put at hardware_addr+offset - * - * |<----16*n bytes------>|<--16*n bytes--->| - * |<--offset----->|------------------------+ - * hardware_addr |<---next cipher-------->| - * - */ -static int sec_ciphers_do_crypto(EVP_CIPHER_CTX *ctx, cipher_priv_ctx_t *priv_ctx) -{ - int ret = KAE_FAIL; - - // add async parm - int job_ret; - op_done_t op_done; - - SEC_CIPHERS_RETURN_FAIL_IF(priv_ctx == NULL, "priv_ctx is NULL.", KAE_FAIL); - cipher_engine_ctx_t *e_cipher_ctx = priv_ctx->e_cipher_ctx; - SEC_CIPHERS_RETURN_FAIL_IF(e_cipher_ctx == NULL, "e_cipher_ctx is NULL", KAE_FAIL); - - SEC_CIPHERS_RETURN_FAIL_IF(priv_ctx->inl <= 0, "in length less than or equal to zero.", KAE_FAIL); - // packageSize>input_cache_size - if (priv_ctx->left_len > INPUT_CACHE_SIZE - priv_ctx->offset) { - ret = sec_ciphers_sync_do_crypto(ctx, e_cipher_ctx, priv_ctx); - if (ret != 0) { - US_ERR("sec sync crypto fail"); - return ret; - } - return KAE_SUCCESS; - } - - // async - async_init_op_done(&op_done); - - if (op_done.job != NULL && kae_is_async_enabled()) { - if (async_setup_async_event_notification(0) == 0) { - US_ERR("sec async event notifying failed"); - async_cleanup_op_done(&op_done); - return KAE_FAIL; - } - } else { - US_DEBUG("NO ASYNC Job or async disable, back to SYNC!"); - async_cleanup_op_done(&op_done); - return sec_ciphers_sync_do_crypto(ctx, e_cipher_ctx, priv_ctx); - } - - if (sec_ciphers_async_do_crypto(e_cipher_ctx, &op_done) == KAE_FAIL) - goto err; - - do { - job_ret = async_pause_job(op_done.job, ASYNC_STATUS_OK); - if ((job_ret == 0)) { - US_DEBUG("- pthread_yidle -"); - kae_pthread_yield(); - } - } while (!op_done.flag || ASYNC_CHK_JOB_RESUMED_UNEXPECTEDLY(job_ret)); - - if (op_done.verifyRst < 0) { - US_ERR("verify result failed with %d", op_done.verifyRst); - async_cleanup_op_done(&op_done); - return KAE_FAIL; - } - - async_cleanup_op_done(&op_done); - - US_DEBUG(" Cipher Async Job Finish! priv_ctx = %p\n", priv_ctx); - - // after cipher cycle should update: in, out, iv, key, length. - sec_ciphers_update_priv_ctx(priv_ctx); - (void)sec_ciphers_after_dociphers_cb(ctx); - - return KAE_SUCCESS; -err: - US_ERR("async job err"); - (void)async_clear_async_event_notification(); - async_cleanup_op_done(&op_done); - return KAE_FAIL; -} - -static int sec_ciphers_sync_do_crypto(EVP_CIPHER_CTX *ctx, cipher_engine_ctx_t *e_cipher_ctx, - cipher_priv_ctx_t *priv_ctx) -{ - int ret = KAE_FAIL; - int leftlen = priv_ctx->left_len; - - while (leftlen != 0) { - priv_ctx->do_cipher_len = wd_ciphers_get_do_cipher_len(priv_ctx->offset, leftlen); - - (void)sec_ciphers_before_dociphers_cb(e_cipher_ctx->priv_ctx); - - wd_ciphers_set_input_data(e_cipher_ctx); - - ret = wd_ciphers_do_crypto_impl(e_cipher_ctx); - if (ret != KAE_SUCCESS) { - return ret; - } - - wd_ciphers_get_output_data(e_cipher_ctx); - - // after cipher cycle should update: in, out, iv, key, length. - sec_ciphers_update_priv_ctx(priv_ctx); - - (void)sec_ciphers_after_dociphers_cb(ctx); - - leftlen -= priv_ctx->do_cipher_len; - } - - US_DEBUG("sec state update success."); - - return KAE_SUCCESS; -} - -static int sec_ciphers_async_do_crypto(cipher_engine_ctx_t *e_cipher_ctx, op_done_t *op_done) -{ - int ret = 0; - int cnt = 0; - cipher_priv_ctx_t *priv_ctx = e_cipher_ctx->priv_ctx; - enum task_type type = ASYNC_TASK_CIPHER; - void *tag = e_cipher_ctx; - - priv_ctx->do_cipher_len = wd_ciphers_get_do_cipher_len(priv_ctx->offset, priv_ctx->left_len); - - (void)sec_ciphers_before_dociphers_cb(e_cipher_ctx->priv_ctx); - - wd_ciphers_set_input_data(e_cipher_ctx); - - do { - if (cnt > MAX_SEND_TRY_CNTS) { - break; - } - - ret = wcrypto_do_cipher(e_cipher_ctx->wd_ctx, &e_cipher_ctx->op_data, tag); - if (ret == -WD_EBUSY) { - if ((async_wake_job(op_done->job, ASYNC_STATUS_EAGAIN) == 0 || - async_pause_job(op_done->job, ASYNC_STATUS_EAGAIN) == 0)) { - US_ERR("sec wake job or sec pause job fail!\n"); - ret = 0; - break; - } - cnt++; - } - } while (ret == -WD_EBUSY); - - if (ret != WD_SUCCESS) { - US_ERR("sec async wcryto do cipher failed"); - return KAE_FAIL; - } - - if (async_add_poll_task(e_cipher_ctx, op_done, type) == 0) { - US_ERR("sec add task failed "); - return KAE_FAIL; - } - - return KAE_SUCCESS; -} - -static int sec_ciphers_is_check_valid(EVP_CIPHER_CTX *ctx, cipher_priv_ctx_t *priv_ctx) -{ - if (priv_ctx->switch_threshold > (size_t)priv_ctx->inl) { - US_WARN_LIMIT("small packet cipher offload, switch to soft cipher, inl %d", (int)priv_ctx->inl); - return KAE_FAIL; - } - - if (sec_ciphers_is_iv_may_overflow(ctx, priv_ctx)) { - US_WARN("sec do cipher, the iv will overflow"); - return KAE_FAIL; - } - - return KAE_SUCCESS; -} - -static int sec_ciphers_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl) -{ - int ret = KAE_FAIL; - int num = 0; - - cipher_priv_ctx_t *priv_ctx = NULL; - - SEC_CIPHERS_RETURN_FAIL_IF(ctx == NULL, "ctx is NULL", OPENSSL_FAIL); - SEC_CIPHERS_RETURN_FAIL_IF(in == NULL, "in is NULL", OPENSSL_FAIL); - SEC_CIPHERS_RETURN_FAIL_IF(out == NULL, "out is NULL", OPENSSL_FAIL); - priv_ctx = (cipher_priv_ctx_t *)EVP_CIPHER_CTX_get_cipher_data(ctx); - SEC_CIPHERS_RETURN_FAIL_IF(priv_ctx == NULL, "ctx cipher data is NULL.", OPENSSL_FAIL); - priv_ctx->inl = inl; - priv_ctx->in = in; - priv_ctx->out = out; - priv_ctx->left_len = inl; - - num = EVP_CIPHER_CTX_num(ctx); - - ret = sec_ciphers_is_check_valid(ctx, priv_ctx); - if (ret != KAE_SUCCESS) { - US_WARN_LIMIT("sec cipher check invalid, switch to soft cipher"); - goto do_soft_cipher; - } - - if (priv_ctx->e_cipher_ctx == NULL) { - priv_ctx->e_cipher_ctx = wd_ciphers_get_engine_ctx(priv_ctx); - if (priv_ctx->e_cipher_ctx == NULL) { - US_WARN("failed to get engine ctx, switch to soft cipher"); - goto do_soft_cipher; - } - } - - ret = sec_ciphers_do_crypto(ctx, priv_ctx); - if (ret != KAE_SUCCESS) { - US_WARN("sec cipher do ciphers failed, switch to soft cipher"); - goto do_soft_cipher; - } - - US_DEBUG("do cipher success. ctx=%p, ctx->num=%d, inl=%d", ctx, num, (int)inl); - - return OPENSSL_SUCCESS; - -do_soft_cipher: - if (priv_ctx->e_cipher_ctx != NULL) { - wd_ciphers_put_engine_ctx(priv_ctx->e_cipher_ctx); - priv_ctx->e_cipher_ctx = NULL; - } - - if (sec_ciphers_software_encrypt(ctx, priv_ctx) != KAE_SUCCESS) { - US_WARN("sec cipher do soft ciphers failed"); - return OPENSSL_FAIL; - } - - return OPENSSL_SUCCESS; -} - -static int sec_ciphers_priv_ctx_cleanup(EVP_CIPHER_CTX *ctx) -{ - cipher_priv_ctx_t *priv_ctx = NULL; - priv_ctx = (cipher_priv_ctx_t *)EVP_CIPHER_CTX_get_cipher_data(ctx); - if (unlikely(priv_ctx == NULL)) { - US_WARN("ctx cipher data is NULL."); - return KAE_FAIL; - } - - kae_free(priv_ctx->iv); - kae_free(priv_ctx->key); - kae_free(priv_ctx->next_iv); - if (priv_ctx->ecb_encryto) { - if (priv_ctx->ecb_encryto->ecb_ctx != NULL) { - EVP_CIPHER_CTX_free(priv_ctx->ecb_encryto->ecb_ctx); - priv_ctx->ecb_encryto->ecb_ctx = NULL; - } - - kae_free(priv_ctx->ecb_encryto->key2); - kae_free(priv_ctx->ecb_encryto->encryto_iv); - kae_free(priv_ctx->ecb_encryto->iv_out); - kae_free(priv_ctx->ecb_encryto); - } - - (void)wd_ciphers_put_engine_ctx(priv_ctx->e_cipher_ctx); - priv_ctx->e_cipher_ctx = NULL; - - return KAE_SUCCESS; -} - -static int sec_ciphers_cleanup(EVP_CIPHER_CTX *ctx) -{ - if (unlikely(ctx == NULL)) { - US_WARN("ctx is NULL"); - return OPENSSL_FAIL; - } - - int ret = sec_ciphers_sw_impl_cleanup(ctx); - if (ret != KAE_SUCCESS) { - US_ERR("Cipher soft impl cleanup failed. ctx=%p", ctx); - } - - ret = sec_ciphers_priv_ctx_cleanup(ctx); - if (ret != KAE_SUCCESS) { - return OPENSSL_FAIL; - } - - US_DEBUG("Cleanup success, ctx=%p", ctx); - - return OPENSSL_SUCCESS; -} - -static EVP_CIPHER *sec_ciphers_set_cipher_method(cipher_info_t cipherinfo) -{ - int ret = 1; - - EVP_CIPHER *cipher = EVP_CIPHER_meth_new(cipherinfo.nid, cipherinfo.blocksize, cipherinfo.keylen); - if (cipher == NULL) { - return NULL; - } - ret &= EVP_CIPHER_meth_set_iv_length(cipher, cipherinfo.ivlen); - ret &= EVP_CIPHER_meth_set_flags(cipher, cipherinfo.flags); - ret &= EVP_CIPHER_meth_set_init(cipher, sec_ciphers_init); - ret &= EVP_CIPHER_meth_set_do_cipher(cipher, sec_ciphers_do_cipher); - ret &= EVP_CIPHER_meth_set_set_asn1_params(cipher, EVP_CIPHER_set_asn1_iv); - ret &= EVP_CIPHER_meth_set_get_asn1_params(cipher, EVP_CIPHER_get_asn1_iv); - ret &= EVP_CIPHER_meth_set_cleanup(cipher, sec_ciphers_cleanup); - ret &= EVP_CIPHER_meth_set_impl_ctx_size(cipher, sizeof(cipher_priv_ctx_t)); - if (ret == 0) { - US_WARN("Failed to set cipher methods for nid %d\n", cipherinfo.nid); - return NULL; - } else { - return cipher; - } -} - -void sec_create_ciphers(void) -{ - unsigned int i = 0; - - for (i = 0; i < CIPHERS_COUNT; i++) { - if (g_sec_ciphers_info[i].cipher == NULL) { - g_sec_ciphers_info[i].cipher = sec_ciphers_set_cipher_method(g_sec_ciphers_info[i]); - } - } -} - -static EVP_CIPHER *get_ciphers_default_method(int nid) -{ - EVP_CIPHER *cipher = NULL; - switch (nid) { - case NID_sm4_ctr: - cipher = (EVP_CIPHER *)EVP_sm4_ctr(); - break; - case NID_sm4_cbc: - cipher = (EVP_CIPHER *)EVP_sm4_cbc(); - break; - case NID_sm4_ofb128: - cipher = (EVP_CIPHER *)EVP_sm4_ofb(); - break; - case NID_sm4_ecb: - cipher = (EVP_CIPHER *)EVP_sm4_ecb(); - break; - default: - US_WARN("nid = %d not support.", nid); - break; - } - return cipher; -} - -int sec_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher, const int **nids, int nid) -{ - UNUSED(e); - unsigned int i = 0; - - if (unlikely((nids == NULL) && ((cipher == NULL) || (nid < 0)))) { - US_WARN("Invalid input param."); - if (cipher != NULL) { - *cipher = NULL; - } - return OPENSSL_FAIL; - } - - /* No specific cipher => return a list of supported nids ... */ - if (cipher == NULL) { - if (nids != NULL) { - *nids = g_known_cipher_nids; - } - return BLOCKSIZES_OF(g_sec_ciphers_info); - } - - for (i = 0; i < CIPHERS_COUNT; i++) { - if (g_sec_ciphers_info[i].nid == nid) { - if (g_sec_ciphers_info[i].cipher == NULL) { - sec_create_ciphers(); - } - /*SM4 is disabled*/ - *cipher = g_sec_ciphers_info[i].is_enabled ? g_sec_ciphers_info[i].cipher : get_ciphers_default_method(nid); - return OPENSSL_SUCCESS; - } - } - - US_WARN("nid = %d not support.", nid); - *cipher = NULL; - - return OPENSSL_FAIL; -} - -void sec_ciphers_free_ciphers(void) -{ - unsigned int i = 0; - - for (i = 0; i < CIPHERS_COUNT; i++) { - if (g_sec_ciphers_info[i].cipher != NULL) { - EVP_CIPHER_meth_free(g_sec_ciphers_info[i].cipher); - g_sec_ciphers_info[i].cipher = NULL; - } - } -} - -void sec_ciphers_cb(const void *msg, void *tag) -{ - if (!msg || !tag) { - US_ERR("sec cb params err!\n"); - return; - } - struct wcrypto_cipher_msg *message = (struct wcrypto_cipher_msg *)msg; - cipher_engine_ctx_t *eng_ctx = (cipher_engine_ctx_t *)tag; - kae_memcpy(eng_ctx->priv_ctx->out, message->out, message->out_bytes); -} - -// async poll thread create -int sec_cipher_engine_ctx_poll(void *engnine_ctx) -{ - int ret = 0; - struct cipher_engine_ctx *eng_ctx = (struct cipher_engine_ctx *)engnine_ctx; - struct wd_queue *q = eng_ctx->q_node->kae_wd_queue; - -POLL_AGAIN: - ret = wcrypto_cipher_poll(q, 1); - if (!ret) { - goto POLL_AGAIN; - } else if (ret < 0) { - US_ERR("cipher poll failed\n"); - return ret; - } - return ret; -} - -int cipher_module_init(void) -{ - wd_ciphers_init_qnode_pool(); - - sec_create_ciphers(); - - // reg async interface here - async_register_poll_fn(ASYNC_TASK_CIPHER, sec_cipher_engine_ctx_poll); - - return 1; -} diff --git a/alg/ciphers/sec_ciphers.h b/alg/ciphers/sec_ciphers.h deleted file mode 100644 index ed3ec41..0000000 --- a/alg/ciphers/sec_ciphers.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the the interface for KAE engine dealing with wrapdrive - * - * 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. - */ - -/***************************************************************************** - * @file sec_cipher.h - * - * This file provides the interface for SEC engine dealing with wrapdrive - * - *****************************************************************************/ - -#ifndef SEC_CIPHERS_H -#define SEC_CIPHERS_H -#include -#include "wd_cipher.h" -#include "wd_queue_memory.h" - -#define MAX_SEND_TRY_CNTS 50 - -enum openssl_cipher_enc_t { - OPENSSL_DECRYPTION = 0, - OPENSSL_ENCRYPTION = 1 -}; - -enum sec_cipher_priv_ctx_syncto { - SEC_CIHPER_SYNC_S2W = 1, // software priv ctx sync to hareware priv ctx - SEC_CIHPER_SYNC_H2S, // hareware priv ctx sync to software priv ctx -}; -typedef enum sec_cipher_priv_ctx_syncto sec_cipher_priv_ctx_syncto_t; - -typedef struct xts_ecb_data_strcut { - EVP_CIPHER_CTX *ecb_ctx; - const EVP_CIPHER* cipher_type; - uint8_t* key2; - uint8_t key2_len; - uint8_t* iv_out; - uint8_t* encryto_iv; - uint32_t countNum; -} xts_ecb_data; - -typedef struct cipher_engine_ctx cipher_engine_ctx_t; -/* - * | 16bytes * n length | offset | | - * | <---------first buf -----------><---next buf -->| - * the next buf send to warpdriv should start at hardaddr + first offset - */ -struct cipher_priv_ctx { - int32_t encrypt; // encrypt or decryto DECRYPTION = 0, ENCRYPTION = 1 - uint32_t inl; // input length - uint32_t left_len; // left length for warpdrive to do - uint32_t offset; // prev buf offset, that indicate the next buf should start at hardware_addr+offset - uint8_t* key; // key - uint32_t key_len; // key length - uint8_t* iv; // iv - uint32_t iv_len; // iv length - uint8_t* next_iv; // store IV for next cbc operation in decryption - const uint8_t* in; - uint8_t* out; - uint32_t c_mode; - uint32_t c_alg; - uint32_t do_cipher_len; // do one cycle cipher length - - size_t switch_threshold; // crypt small packet offload threshold - void* sw_ctx_data; // Pointer for context data that will be used by Small packet offload feature. - xts_ecb_data* ecb_encryto; - cipher_engine_ctx_t* e_cipher_ctx; -}; - -typedef struct cipher_priv_ctx cipher_priv_ctx_t; - -struct cipher_engine_ctx { - KAE_QUEUE_DATA_NODE_S* q_node; - struct wcrypto_cipher_op_data op_data; - struct wcrypto_cipher_ctx_setup setup; - void* wd_ctx; // one ctx or a list of ctx - - cipher_priv_ctx_t* priv_ctx; -}; - -void sec_ciphers_set_enabled(int nid, int enabled); -int sec_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher, const int **nids, int nid); -void sec_ciphers_free_ciphers(void); -int sec_cipher_engine_ctx_poll(void* engnine_ctx); - -int cipher_module_init(void); -void sec_ciphers_cb(const void* msg, void* tag); - -#endif - diff --git a/alg/ciphers/sec_ciphers_soft.c b/alg/ciphers/sec_ciphers_soft.c deleted file mode 100644 index 0f68edb..0000000 --- a/alg/ciphers/sec_ciphers_soft.c +++ /dev/null @@ -1,334 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the implemenation for switch to soft ciphers - * - * 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. - */ - -/***************************************************************************** - * @file sec_ciphers_soft.c - * - * This file provides the implemenation for switch to soft ciphers - * - *****************************************************************************/ -#include "engine_types.h" -#include "sec_ciphers_soft.h" -#include "sec_ciphers.h" -#include "sec_ciphers_utils.h" - -#define CRYPTO_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT 192 - -static cipher_threshold_table_t g_sec_ciphers_pkt_threshold_table[] = { - { NID_aes_128_ecb, CRYPTO_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT }, - { NID_aes_192_ecb, CRYPTO_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT }, - { NID_aes_256_ecb, CRYPTO_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT }, - { NID_aes_128_cbc, CRYPTO_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT }, - { NID_aes_192_cbc, CRYPTO_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT }, - { NID_aes_256_cbc, CRYPTO_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT }, - { NID_aes_128_ctr, CRYPTO_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT }, - { NID_aes_192_ctr, CRYPTO_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT }, - { NID_aes_256_ctr, CRYPTO_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT }, - { NID_aes_128_xts, CRYPTO_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT }, - { NID_aes_256_xts, CRYPTO_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT }, - - { NID_sm4_cbc, CRYPTO_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT }, - { NID_sm4_ctr, CRYPTO_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT }, - { NID_sm4_ofb128, CRYPTO_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT }, - { NID_sm4_ecb, CRYPTO_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT }, -}; -static int g_sec_ciphers_pkt_threshold_table_size = BLOCKSIZES_OF(g_sec_ciphers_pkt_threshold_table); - -static sw_cipher_t g_sec_ciphers_sw_cipher_table[] = { - - { NID_aes_128_ecb, EVP_aes_128_ecb }, - { NID_aes_192_ecb, EVP_aes_192_ecb }, - { NID_aes_256_ecb, EVP_aes_256_ecb }, - { NID_aes_128_cbc, EVP_aes_128_cbc }, - { NID_aes_192_cbc, EVP_aes_192_cbc }, - { NID_aes_256_cbc, EVP_aes_256_cbc }, - { NID_aes_128_ctr, EVP_aes_128_ctr }, - { NID_aes_192_ctr, EVP_aes_192_ctr }, - { NID_aes_256_ctr, EVP_aes_256_ctr }, - { NID_aes_128_xts, EVP_aes_128_xts }, - { NID_aes_256_xts, EVP_aes_256_xts }, - - { NID_sm4_cbc, EVP_sm4_cbc }, - { NID_sm4_ctr, EVP_sm4_ctr }, - { NID_sm4_ofb128, EVP_sm4_ofb }, - { NID_sm4_ecb, EVP_sm4_ecb }, -}; -static int g_sec_ciphers_sw_cipher_table_size = BLOCKSIZES_OF(g_sec_ciphers_sw_cipher_table); - -static int sec_ciphers_sw_impl_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl); - -int sec_ciphers_sw_get_threshold(int nid) -{ - int i = 0; - - do { - if (g_sec_ciphers_pkt_threshold_table[i].nid == nid) { - return g_sec_ciphers_pkt_threshold_table[i].threshold; - } - } while (++i < g_sec_ciphers_pkt_threshold_table_size); - - US_ERR("nid %d not found in threshold table", nid); - - return KAE_FAIL; -} - -const EVP_CIPHER *sec_ciphers_get_cipher_sw_impl(int nid) -{ - int i = 0; - - for (i = 0; i < g_sec_ciphers_sw_cipher_table_size; i++) { - if (nid == g_sec_ciphers_sw_cipher_table[i].nid) { - return (g_sec_ciphers_sw_cipher_table[i].get_cipher)(); - } - } - US_WARN("Invalid nid %d\n", nid); - - return (EVP_CIPHER *)NULL; -} - -int sec_ciphers_sw_impl_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, - const unsigned char *iv, int enc) -{ - int ret = KAE_FAIL; - unsigned int sw_size = 0; - - cipher_priv_ctx_t* priv_ctx = NULL; - const EVP_CIPHER *sw_cipher = NULL; - - /* allowed iv to be empty. */ - if (unlikely(key == NULL)) { - US_ERR("kae sw init parameter is NULL. key=%p", key); - return KAE_FAIL; - } - if (unlikely(ctx == NULL)) { - US_ERR("kae sw init parameter is NULL. ctx=%p", ctx); - return KAE_FAIL; - } - - priv_ctx = (cipher_priv_ctx_t *)EVP_CIPHER_CTX_get_cipher_data(ctx); - if (unlikely(priv_ctx == NULL)) { - US_ERR("state is NULL"); - return KAE_FAIL; - } - - sw_cipher = sec_ciphers_get_cipher_sw_impl(EVP_CIPHER_CTX_nid(ctx)); - if (unlikely(sw_cipher == NULL)) { - int nid = EVP_CIPHER_CTX_nid(ctx); - US_ERR("get openssl software cipher failed. nid = %d", nid); - return KAE_FAIL; - } - - sw_size = EVP_CIPHER_impl_ctx_size(sw_cipher); - if (unlikely(sw_size == 0)) { - US_ERR("get EVP cipher ctx size failed, sw_size=%d", sw_size); - return KAE_FAIL; - } - - if (priv_ctx->sw_ctx_data == NULL) { - priv_ctx->sw_ctx_data = kae_malloc(sw_size); - if (priv_ctx->sw_ctx_data == NULL) { - US_ERR("Unable to allocate memory [%u bytes] for sw_ctx_data", sw_size); - return KAE_FAIL; - } - } - kae_memset(priv_ctx->sw_ctx_data, 0, sw_size); - - if (iv == NULL) { - iv = EVP_CIPHER_CTX_iv_noconst(ctx); - } - - /* real implementation: Openssl soft arithmetic key initialization function */ - EVP_CIPHER_CTX_set_cipher_data(ctx, priv_ctx->sw_ctx_data); - ret = EVP_CIPHER_meth_get_init(sw_cipher)(ctx, key, iv, enc); - EVP_CIPHER_CTX_set_cipher_data(ctx, priv_ctx); - if (ret != OPENSSL_SUCCESS) { - US_ERR("OPENSSL init key failed. ctx=%p", ctx); - kae_free(priv_ctx->sw_ctx_data); - return KAE_FAIL; - } - US_DEBUG("kae sw init impl success. ctx=%p", ctx); - - return KAE_SUCCESS; -} - -int sec_ciphers_sw_impl_cleanup(EVP_CIPHER_CTX *ctx) -{ - cipher_priv_ctx_t* priv_ctx = NULL; - - if (unlikely(ctx == NULL)) { - US_WARN("ctx is NULL"); - return KAE_FAIL; - } - -#ifdef KAE_DEBUG_KEY_ENABLE - dump_data("iv", EVP_CIPHER_CTX_iv_noconst(ctx), EVP_CIPHER_CTX_iv_length(ctx)); -#endif - - priv_ctx = (cipher_priv_ctx_t *)EVP_CIPHER_CTX_get_cipher_data(ctx); - if (unlikely(priv_ctx == NULL)) { - US_WARN("ctx cipher private data is NULL."); - return KAE_FAIL; - } - - kae_free(priv_ctx->sw_ctx_data); - - US_DEBUG("kae sw cleanup impl success, ctx=%p", ctx); - - return KAE_SUCCESS; -} - -static int sec_ciphers_sw_impl_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, - const unsigned char *in, size_t inl) -{ - if (unlikely((ctx == NULL) || (out == NULL) || (in == NULL))) { - US_ERR("kae sw cipher parameter is null.ctx=%p, in=%p, out=%p, inl=%d", ctx, out, in, (int)inl); - return KAE_FAIL; - } - - cipher_priv_ctx_t* priv_ctx = (cipher_priv_ctx_t *)EVP_CIPHER_CTX_get_cipher_data(ctx); - if (unlikely(priv_ctx == NULL)) { - US_ERR("state is NULL"); - return KAE_FAIL; - } - - const EVP_CIPHER* sw_cipher = sec_ciphers_get_cipher_sw_impl(EVP_CIPHER_CTX_nid(ctx)); - if (unlikely(sw_cipher == NULL)) { - US_ERR("get OpenSSL cipher failed. ctx=%p", ctx); - return KAE_FAIL; - } - - EVP_CIPHER_CTX_set_cipher_data(ctx, priv_ctx->sw_ctx_data); - int ret = EVP_CIPHER_meth_get_do_cipher(sw_cipher)(ctx, out, in, inl); - if (unlikely(ret == OPENSSL_FAIL)) { - EVP_CIPHER_CTX_set_cipher_data(ctx, priv_ctx); - US_ERR("OpenSSL do cipher failed. ctx=%p", ctx); - return KAE_FAIL; - } - - EVP_CIPHER_CTX_set_cipher_data(ctx, priv_ctx); - - US_DEBUG("kae sw impl do cipher success, ctx=%p", ctx); - - return KAE_SUCCESS; -} - -int sec_ciphers_software_encrypt(EVP_CIPHER_CTX *ctx, cipher_priv_ctx_t* priv_ctx) -{ - int ret = sec_ciphers_sw_impl_do_cipher(ctx, priv_ctx->out, priv_ctx->in, priv_ctx->left_len); - if (ret != KAE_SUCCESS) { - US_ERR("kae software do cipher or small packet cipher offload failed."); - return KAE_FAIL; - } - - // after openssl software do cipher, sync priv data to next priv data for hareware to contiune to do cipher */ - ret = sec_ciphers_sw_hw_ctx_sync(ctx, SEC_CIHPER_SYNC_S2W); - if (unlikely(ret != KAE_SUCCESS)) { - US_ERR("kae sw hw state sync failed."); - return KAE_FAIL; - } - - US_DEBUG("Cipher success, ctx=%p", ctx); - return KAE_SUCCESS; -} - -int sec_ciphers_sw_hw_ctx_sync(EVP_CIPHER_CTX *ctx, sec_cipher_priv_ctx_syncto_t direction) -{ - cipher_priv_ctx_t* priv_ctx = NULL; - unsigned int num = 0; - unsigned int offset = 0; - - US_DEBUG("sw hw state sync start. ctx=%p", ctx); - - priv_ctx = (cipher_priv_ctx_t *)EVP_CIPHER_CTX_get_cipher_data(ctx); - if (unlikely(priv_ctx == NULL)) { - US_ERR("cipher priv ctx data is NULL."); - return KAE_FAIL; - } - - if (direction == SEC_CIHPER_SYNC_S2W) { - kae_memcpy(priv_ctx->iv, EVP_CIPHER_CTX_iv_noconst(ctx), EVP_CIPHER_CTX_iv_length(ctx)); - num = EVP_CIPHER_CTX_num(ctx); - if (num) { - sec_ciphers_ctr_iv_sub(priv_ctx->iv); - } - priv_ctx->offset = num; - priv_ctx->left_len = 0; - } else { - if (priv_ctx->do_cipher_len != 0) { - offset = priv_ctx->offset; - kae_memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), priv_ctx->iv, EVP_CIPHER_CTX_iv_length(ctx)); - EVP_CIPHER_CTX_set_num(ctx, offset); - } - } - - US_DEBUG("state sync success, direct=%d[1:SW_TO_HW, 2:HW_TO_SW], offset=%d", direction, num); - - return KAE_SUCCESS; -} - - -int sec_ciphers_ecb_encryt(xts_ecb_data* ecb_encryto, uint8_t* buf_out, uint8_t* buf_in, int buf_len) -{ - int out_len1, tmplen; - /* Encrypt */ - if (!EVP_EncryptInit_ex(ecb_encryto->ecb_ctx, ecb_encryto->cipher_type, NULL, ecb_encryto->key2, NULL)) { - US_ERR("EVP_EncryptInit failed.\n"); - return KAE_FAIL; - } - EVP_CIPHER_CTX_set_padding(ecb_encryto->ecb_ctx, 0); - - if (!EVP_EncryptUpdate(ecb_encryto->ecb_ctx, buf_out, &out_len1, buf_in, buf_len)) { - US_ERR("EVP_EncryptUpdate failed.\n"); - return KAE_FAIL; - } - - if (!EVP_EncryptFinal_ex(ecb_encryto->ecb_ctx, buf_out + out_len1, &tmplen)) { - /* Error */ - return KAE_FAIL; - } - out_len1 += tmplen; - - return KAE_SUCCESS; -} - -int sec_ciphers_ecb_decrypt(xts_ecb_data* ecb_encryto, uint8_t* buf_out, uint8_t* buf_in, int buf_len) -{ - int out_len1, tmplen; - - /* decrypt */ - if (!EVP_DecryptInit_ex(ecb_encryto->ecb_ctx, ecb_encryto->cipher_type, NULL, ecb_encryto->key2, NULL)) { - US_ERR("EVP_EncryptInit failed.\n"); - return KAE_FAIL; - } - - EVP_CIPHER_CTX_set_padding(ecb_encryto->ecb_ctx, 0); - - if (!EVP_DecryptUpdate(ecb_encryto->ecb_ctx, buf_out, &out_len1, buf_in, buf_len)) { - US_ERR("EVP_EncryptUpdate failed.\n"); - return KAE_FAIL; - } - - if (!EVP_DecryptFinal_ex(ecb_encryto->ecb_ctx, buf_out + out_len1, &tmplen)) { - /* Error */ - return KAE_FAIL; - } - out_len1 += tmplen; - - return KAE_SUCCESS; -} - diff --git a/alg/ciphers/sec_ciphers_soft.h b/alg/ciphers/sec_ciphers_soft.h deleted file mode 100644 index ccf93fb..0000000 --- a/alg/ciphers/sec_ciphers_soft.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the cipher interface for soft ciphers - * - * 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. - */ - -/***************************************************************************** -* @file sec_ciphers_soft.h -* -* This file provides the cipher interface for soft ciphers -* -*****************************************************************************/ - -#ifndef SEC_CIPHERS_SOFT_H -#define SEC_CIPHERS_SOFT_H - -#include "sec_ciphers.h" -#include "engine_kae.h" - -typedef struct cipher_threshold_table_s { - int nid; - int threshold; -} cipher_threshold_table_t; - -typedef struct sw_cipher_s { - int nid; - const EVP_CIPHER *(*get_cipher)(void); -} sw_cipher_t; - -const EVP_CIPHER *sec_ciphers_get_cipher_sw_impl(int nid); -int sec_ciphers_sw_get_threshold(int nid); -int sec_ciphers_sw_impl_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc); -int sec_ciphers_sw_impl_cleanup(EVP_CIPHER_CTX *ctx); -int sec_ciphers_software_encrypt(EVP_CIPHER_CTX *ctx, cipher_priv_ctx_t* priv_ctx); -int sec_ciphers_sw_hw_ctx_sync(EVP_CIPHER_CTX *ctx, sec_cipher_priv_ctx_syncto_t direction); -int sec_ciphers_ecb_encryt(xts_ecb_data* ecb_encryto, uint8_t* buf_out, uint8_t* buf_in, int buf_len); -int sec_ciphers_ecb_decrypt(xts_ecb_data* ecb_encryto, uint8_t* buf_out, uint8_t* buf_in, int buf_len); - - -#endif - diff --git a/alg/ciphers/sec_ciphers_utils.c b/alg/ciphers/sec_ciphers_utils.c deleted file mode 100644 index 69de5ec..0000000 --- a/alg/ciphers/sec_ciphers_utils.c +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the implemenation for KAE engine utils dealing with wrapdrive - * - * 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. - */ - -/***************************************************************************** -* @file sec_ciphers_utils.c -* -* This file provides the interface for SEC engine dealing with wrapdrive -* -*****************************************************************************/ - - -#include "sec_ciphers_utils.h" -#include "engine_types.h" -#include "sec_ciphers_soft.h" - -int sec_ciphers_get_cipher_mode(int nid) -{ - uint32_t c_mode = NO_C_MODE; - - switch (nid) { - case NID_aes_128_ecb: - case NID_aes_192_ecb: - case NID_aes_256_ecb: - case NID_sm4_ecb: - c_mode = ECB; - break; - case NID_aes_128_cbc: - case NID_aes_192_cbc: - case NID_aes_256_cbc: - case NID_sm4_cbc: - c_mode = CBC; - break; - case NID_aes_128_ctr: - case NID_aes_192_ctr: - case NID_aes_256_ctr: - case NID_sm4_ctr: - c_mode = CTR; - break; - case NID_aes_128_xts: - case NID_aes_256_xts: - c_mode = XTS; - break; - case NID_sm4_ofb128: - c_mode = OFB; - break; - default: - US_WARN("nid=%d don't support by sec engine.", nid); - break; - } - - return c_mode; -} - -int sec_ciphers_get_cipher_alg(int nid) -{ - uint32_t c_alg = NO_C_ALG; - switch (nid) { - case NID_sm4_ctr: - case NID_sm4_cbc: - case NID_sm4_ofb128: - case NID_sm4_ecb: - c_alg = SM4; - break; - case NID_aes_128_ecb: - case NID_aes_192_ecb: - case NID_aes_256_ecb: - case NID_aes_128_cbc: - case NID_aes_192_cbc: - case NID_aes_256_cbc: - case NID_aes_128_ctr: - case NID_aes_192_ctr: - case NID_aes_256_ctr: - case NID_aes_128_xts: - case NID_aes_256_xts: - c_alg = AES; - break; - default: - US_WARN("nid=%d don't support by sec engine.", nid); - break; - } - - return c_alg; -} - -/* - * SEC ENGINE IV: {Flag, Random, Counter} - * | <--4--> <--8--> | <---4bytes ---> | - * | Flag, Random | counter | - */ -static unsigned int __iv_to_engine_counter(const uint8_t *iv) -{ - unsigned int counter = 0; - const unsigned int SEC_IV_COUNTER_POSTION = 12; - - counter |= iv[SEC_IV_COUNTER_POSTION]; - counter <<= 8; // left shift 8 - counter |= iv[(unsigned int)(SEC_IV_COUNTER_POSTION + 1)]; // count num 1 - counter <<= 8; // left shift 8 - counter |= iv[(unsigned int)(SEC_IV_COUNTER_POSTION + 2)]; // count num 2 - counter <<= 8; // left shift 8 - counter |= iv[(unsigned int)(SEC_IV_COUNTER_POSTION + 3)]; // count num 3 - - return counter; -} - -/* increment counter (128-bit int) by c */ -void sec_ciphers_ctr_iv_inc(uint8_t *counter, uint32_t c) -{ - uint32_t n = 16; - - do { - --n; - c += counter[n]; - counter[n] = (uint8_t)c; - c >>= 8; // right shift 8 - } while (n); -} - -void sec_ciphers_xts_iv_inc(cipher_priv_ctx_t* priv_ctx) -{ - uint32_t i = 0; - unsigned int carry; - unsigned int res; - - union { - uint64_t u[2]; // union length 2 - uint32_t d[4]; // union length 4 - uint8_t c[16]; // union length 16 - }tweak; - - kae_memcpy(tweak.c, priv_ctx->ecb_encryto->encryto_iv, 16); // encrypto iv length 16 - - for (i = 0; i < priv_ctx->ecb_encryto->countNum; i++) { - // cppcheck-suppress * - res = 0x87 & (((int)tweak.d[3]) >> 31); // algorithm para 31 - carry = (unsigned int)(tweak.u[0] >> 63); // algorithm para 63 - tweak.u[0] = (tweak.u[0] << 1) ^ res; - tweak.u[1] = (tweak.u[1] << 1) | carry; - } - - sec_ciphers_ecb_decrypt(priv_ctx->ecb_encryto, priv_ctx->ecb_encryto->iv_out, tweak.c, 16); // iv len 16 - - kae_memcpy(priv_ctx->iv, priv_ctx->ecb_encryto->iv_out, 16); // update iv len 16 -} - -void sec_ciphers_ctr_iv_sub(uint8_t *counter) -{ - unsigned int n = 16; - int c = 0; - - do { - --n; - c = counter[n] < 1 ? 1 : 0; - counter[n] = (unsigned char)(counter[n] + c * 256 - 1); // algorithm para 256 - if (c == 0) { - break; - } - } while (n); -} - -void sec_ciphers_update_iv(cipher_priv_ctx_t *tmp_docipher_ctx, int cipher_length) -{ - unsigned int inc_counter = 0; - - switch (tmp_docipher_ctx->c_mode) { - case CBC: - if (tmp_docipher_ctx->encrypt == OPENSSL_ENCRYPTION) { - kae_memcpy(tmp_docipher_ctx->iv, tmp_docipher_ctx->out + cipher_length - IV_SIZE, IV_SIZE); - } - break; - case CTR: - inc_counter = cipher_length >> 4; // right shift 4 - sec_ciphers_ctr_iv_inc(tmp_docipher_ctx->iv, inc_counter); - break; - case XTS: - // update iv here - break; - default: - break; - } - - return; -} - -int sec_ciphers_is_iv_may_overflow(EVP_CIPHER_CTX *ctx, cipher_priv_ctx_t *priv_ctx) -{ - unsigned int will_inc_counter = 0; - unsigned int current_counter = 0; - - if (sec_ciphers_get_cipher_mode(EVP_CIPHER_CTX_nid(ctx)) == CTR) { - // (input length + prev offset)/ 16 = will_inc_counter - will_inc_counter = (priv_ctx->inl + priv_ctx->offset) >> 4; // right shift 4 - current_counter = __iv_to_engine_counter(priv_ctx->iv); - if ((0xFFFFFFFFU - current_counter < will_inc_counter)) { - US_DEBUG("ciphers increase iv overflow 0xFFFFFFFF."); - return 1; - } - } - - return 0; -} - diff --git a/alg/ciphers/sec_ciphers_utils.h b/alg/ciphers/sec_ciphers_utils.h deleted file mode 100644 index 5241027..0000000 --- a/alg/ciphers/sec_ciphers_utils.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the cipher interface for KAE engine utils dealing - * - * 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. - */ - -/***************************************************************************** -* @file sec_ciphers_utils.h -* -* This file provides the implemenation for SEC engine utils dealing -* -*****************************************************************************/ - -#ifndef SEC_CIPHERS_CHECKER_H -#define SEC_CIPHERS_CHECKER_H - -#include "sec_ciphers.h" -#include "engine_kae.h" - -#define IV_SIZE 16 - -enum CIPHERS_MODE { - ECB, - CBC, - CTR, - XTS, - OFB, -}; - -enum CIPHERS_ALG { - SM4, - AES, - DES, - M_3DES, -}; - -int sec_ciphers_is_iv_may_overflow(EVP_CIPHER_CTX *ctx, cipher_priv_ctx_t *priv_ctx); -int sec_ciphers_get_cipher_mode(int nid); -int sec_ciphers_get_cipher_alg(int nid); - -void sec_ciphers_ctr_iv_inc(uint8_t *counter, uint32_t c); -void sec_ciphers_ctr_iv_sub(uint8_t *counter); -void sec_ciphers_xts_iv_inc(cipher_priv_ctx_t* priv_ctx); - -void sec_ciphers_update_iv(cipher_priv_ctx_t *tmp_docipher_ctx, int cipher_length); - -#endif - diff --git a/alg/ciphers/sec_ciphers_wd.c b/alg/ciphers/sec_ciphers_wd.c deleted file mode 100644 index 27cf3e0..0000000 --- a/alg/ciphers/sec_ciphers_wd.c +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the implemenation for KAE ciphers using wd interface - * - * 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. - */ - -/***************************************************************************** - * @file sec_cipher_wd.c - * - * This file provides the implemenation for SEC ciphers using wd interface - * - *****************************************************************************/ -#include "sec_ciphers_wd.h" -#include "sec_ciphers_utils.h" -#include "wd_queue_memory.h" -#include "engine_utils.h" -#include "engine_types.h" - -#define OUTPUT_CACHE_SIZE (256*1024) -#define INPUT_CACHE_SIZE (256*1024) -#define MAX_KEY_SIZE 64 -#define MAX_IV_SIZE 16 - - -KAE_QUEUE_POOL_HEAD_S* g_sec_ciphers_qnode_pool = NULL; -static cipher_engine_ctx_t* wd_ciphers_new_engine_ctx(KAE_QUEUE_DATA_NODE_S* q_node, cipher_priv_ctx_t* priv_ctx); - -void wd_ciphers_free_engine_ctx(void* engine_ctx) -{ - cipher_engine_ctx_t* e_cipher_ctx = (cipher_engine_ctx_t *)engine_ctx; - if (e_cipher_ctx == NULL) { - return; - } - - if (e_cipher_ctx->op_data.in && e_cipher_ctx->setup.br.usr) { - e_cipher_ctx->setup.br.free(e_cipher_ctx->setup.br.usr, (void *)e_cipher_ctx->op_data.in); - e_cipher_ctx->op_data.in = NULL; - } - - if (e_cipher_ctx->op_data.out && e_cipher_ctx->setup.br.usr) { - e_cipher_ctx->setup.br.free(e_cipher_ctx->setup.br.usr, (void *)e_cipher_ctx->op_data.out); - e_cipher_ctx->op_data.out = NULL; - } - - if (e_cipher_ctx->op_data.iv && e_cipher_ctx->setup.br.usr) { - e_cipher_ctx->setup.br.free(e_cipher_ctx->setup.br.usr, (void *)e_cipher_ctx->op_data.iv); - e_cipher_ctx->op_data.iv = NULL; - } - - OPENSSL_free(e_cipher_ctx); - e_cipher_ctx = NULL; -} - -static cipher_engine_ctx_t* wd_ciphers_new_engine_ctx(KAE_QUEUE_DATA_NODE_S* q_node, cipher_priv_ctx_t* priv_ctx) -{ - cipher_engine_ctx_t *e_cipher_ctx = NULL; - - e_cipher_ctx = (cipher_engine_ctx_t *)OPENSSL_malloc(sizeof(cipher_engine_ctx_t)); - if (e_cipher_ctx == NULL) { - US_ERR("OPENSSL_malloc ctx failed"); - return NULL; - } - kae_memset(e_cipher_ctx, 0, sizeof(cipher_engine_ctx_t)); - - e_cipher_ctx->setup.br.alloc = kae_wd_alloc_blk; - e_cipher_ctx->setup.br.free = kae_wd_free_blk; - e_cipher_ctx->setup.br.iova_map = kae_dma_map; - e_cipher_ctx->setup.br.iova_unmap = kae_dma_unmap; - e_cipher_ctx->setup.br.usr = q_node->kae_queue_mem_pool; - - e_cipher_ctx->op_data.in = e_cipher_ctx->setup.br.alloc(e_cipher_ctx->setup.br.usr, INPUT_CACHE_SIZE); - if (e_cipher_ctx->op_data.in == NULL) { - US_ERR("alloc opdata in buf failed"); - goto err; - } - - e_cipher_ctx->op_data.out = e_cipher_ctx->setup.br.alloc(e_cipher_ctx->setup.br.usr, OUTPUT_CACHE_SIZE); - if (e_cipher_ctx->op_data.out == NULL) { - US_ERR("alloc opdata out buf failed"); - goto err; - } - - e_cipher_ctx->op_data.iv = e_cipher_ctx->setup.br.alloc(e_cipher_ctx->setup.br.usr, priv_ctx->iv_len); - if (e_cipher_ctx->op_data.iv == NULL) { - US_ERR("alloc opdata iv buf failed"); - goto err; - } - - e_cipher_ctx->priv_ctx = priv_ctx; // point to each other - e_cipher_ctx->q_node = q_node; // point to each other - q_node->engine_ctx = e_cipher_ctx; // point to each other - - return e_cipher_ctx; - -err: - (void)wd_ciphers_free_engine_ctx(e_cipher_ctx); - - return NULL; -} - -static int wd_ciphers_init_engine_ctx(cipher_engine_ctx_t *e_cipher_ctx) -{ - struct wd_queue *q = e_cipher_ctx->q_node->kae_wd_queue; - cipher_priv_ctx_t* priv_ctx = e_cipher_ctx->priv_ctx; - - if (e_cipher_ctx->wd_ctx != NULL) { - US_WARN("wd ctx is in used by other ciphers"); - - return KAE_FAIL; - } - - e_cipher_ctx->setup.alg = (enum wcrypto_cipher_alg)priv_ctx->c_alg; // for example: WD_CIPHER_SM4; - e_cipher_ctx->setup.mode = (enum wcrypto_cipher_mode)priv_ctx->c_mode; // for example: WD_CIPHER_CBC; - e_cipher_ctx->setup.cb = (wcrypto_cb)sec_ciphers_cb; - e_cipher_ctx->wd_ctx = wcrypto_create_cipher_ctx(q, &e_cipher_ctx->setup); - - if (e_cipher_ctx->wd_ctx == NULL) { - US_ERR("wd create sec cipher ctx fail!"); - return KAE_FAIL; - } - - wcrypto_set_cipher_key(e_cipher_ctx->wd_ctx, priv_ctx->key, priv_ctx->key_len); - - return KAE_SUCCESS; -} - -cipher_engine_ctx_t* wd_ciphers_get_engine_ctx(cipher_priv_ctx_t* priv_ctx) -{ - KAE_QUEUE_DATA_NODE_S *q_node = NULL; - cipher_engine_ctx_t *e_cipher_ctx = NULL; - - if (unlikely(priv_ctx == NULL)) { - US_ERR("sec cipher priv ctx NULL!"); - return NULL; - } - - q_node = kae_get_node_from_pool(g_sec_ciphers_qnode_pool); - if (q_node == NULL) { - US_ERR_LIMIT("failed to get hardware queue"); - return NULL; - } - - e_cipher_ctx = (cipher_engine_ctx_t *)q_node->engine_ctx; - if (e_cipher_ctx == NULL) { - e_cipher_ctx = wd_ciphers_new_engine_ctx(q_node, priv_ctx); - if (e_cipher_ctx == NULL) { - US_WARN("sec new engine ctx fail!"); - (void)kae_put_node_to_pool(g_sec_ciphers_qnode_pool, q_node); - return NULL; - } - } - - e_cipher_ctx->priv_ctx = priv_ctx; - - if (wd_ciphers_init_engine_ctx(e_cipher_ctx) == KAE_FAIL) { - US_WARN("init engine ctx fail!"); - wd_ciphers_put_engine_ctx(e_cipher_ctx); - return NULL; - } - - return e_cipher_ctx; -} - -void wd_ciphers_put_engine_ctx(cipher_engine_ctx_t* e_cipher_ctx) -{ - if (unlikely(e_cipher_ctx == NULL)) { - US_WARN("sec cipher engine ctx NULL!"); - return; - } - - if (e_cipher_ctx->wd_ctx != NULL) { - wcrypto_del_cipher_ctx(e_cipher_ctx->wd_ctx); - e_cipher_ctx->wd_ctx = NULL; - } - - if (e_cipher_ctx->priv_ctx && e_cipher_ctx->priv_ctx->ecb_encryto) { - if (e_cipher_ctx->priv_ctx->ecb_encryto->ecb_ctx != NULL) { - EVP_CIPHER_CTX_free(e_cipher_ctx->priv_ctx->ecb_encryto->ecb_ctx); - e_cipher_ctx->priv_ctx->ecb_encryto->ecb_ctx = NULL; - } - - kae_free(e_cipher_ctx->priv_ctx->ecb_encryto->key2); - kae_free(e_cipher_ctx->priv_ctx->ecb_encryto->encryto_iv); - kae_free(e_cipher_ctx->priv_ctx->ecb_encryto->iv_out); - kae_free(e_cipher_ctx->priv_ctx->ecb_encryto); - } - - if (e_cipher_ctx->q_node != NULL) { - (void)kae_put_node_to_pool(g_sec_ciphers_qnode_pool, e_cipher_ctx->q_node); - } - - e_cipher_ctx = NULL; - - return; -} - -int wd_ciphers_do_crypto_impl(cipher_engine_ctx_t *e_cipher_ctx) -{ - int ret = -WD_EINVAL; - int trycount = 0; - - if (unlikely(e_cipher_ctx == NULL)) { - US_ERR("do cipher ctx NULL!"); - return KAE_FAIL; - } - -again: - ret = wcrypto_do_cipher(e_cipher_ctx->wd_ctx, &e_cipher_ctx->op_data, NULL); - if (ret != WD_SUCCESS) { - if (ret == -WD_EBUSY && trycount <= 5) { // try 5 times - US_WARN("do cipher busy, retry again!"); - trycount++; - goto again; - } else { - US_ERR("do cipher failed!"); - return KAE_FAIL; - } - } - - return KAE_SUCCESS; -} - -inline void wd_ciphers_set_input_data(cipher_engine_ctx_t *e_cipher_ctx) -{ - // fill engine ctx opdata - cipher_priv_ctx_t* priv_ctx = e_cipher_ctx->priv_ctx; - - kae_memcpy(((uint8_t *)e_cipher_ctx->op_data.in + priv_ctx->offset), priv_ctx->in, priv_ctx->do_cipher_len); - - if (priv_ctx->encrypt == OPENSSL_ENCRYPTION) { - e_cipher_ctx->op_data.op_type = WCRYPTO_CIPHER_ENCRYPTION; - } else { - e_cipher_ctx->op_data.op_type = WCRYPTO_CIPHER_DECRYPTION; - } - - e_cipher_ctx->op_data.in_bytes = priv_ctx->do_cipher_len + priv_ctx->offset; - - // the real out data start at opdata.out + offset - e_cipher_ctx->op_data.out_bytes = priv_ctx->offset + priv_ctx->do_cipher_len; - kae_memcpy(e_cipher_ctx->op_data.iv, priv_ctx->iv, priv_ctx->iv_len); - e_cipher_ctx->op_data.iv_bytes = priv_ctx->iv_len; -} - -inline void wd_ciphers_get_output_data(cipher_engine_ctx_t *e_cipher_ctx) -{ - cipher_priv_ctx_t* priv_ctx = e_cipher_ctx->priv_ctx; - - // the real out data start at opdata.out + offset - kae_memcpy(priv_ctx->out, (uint8_t*)e_cipher_ctx->op_data.out + priv_ctx->offset, - priv_ctx->do_cipher_len); -} - -inline uint32_t wd_ciphers_get_do_cipher_len(uint32_t offset, int leftlen) -{ - uint32_t do_cipher_len = 0; - int max_input_datalen = INPUT_CACHE_SIZE - offset; - /* - * Note: Small encrypted block can be encrypted once. - * or the last encrypted slice of a large encrypted block - */ - if (leftlen <= max_input_datalen) { - do_cipher_len = leftlen; - } else { - do_cipher_len = max_input_datalen; - } - - return do_cipher_len; -} - -KAE_QUEUE_POOL_HEAD_S* wd_ciphers_get_qnode_pool(void) -{ - return g_sec_ciphers_qnode_pool; -} - -int wd_ciphers_init_qnode_pool(void) -{ - kae_queue_pool_destroy(g_sec_ciphers_qnode_pool, wd_ciphers_free_engine_ctx); - - g_sec_ciphers_qnode_pool = kae_init_queue_pool(WCRYPTO_CIPHER); - if (g_sec_ciphers_qnode_pool == NULL) { - US_ERR("do cipher ctx NULL!"); - return KAE_FAIL; - } - - return KAE_SUCCESS; -} - -void wd_ciphers_uninit_qnode_pool(void) -{ - kae_queue_pool_destroy(g_sec_ciphers_qnode_pool, wd_ciphers_free_engine_ctx); - g_sec_ciphers_qnode_pool = NULL; -} diff --git a/alg/ciphers/sec_ciphers_wd.h b/alg/ciphers/sec_ciphers_wd.h deleted file mode 100644 index 55edd5f..0000000 --- a/alg/ciphers/sec_ciphers_wd.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the cipher interface for KAE ciphers using wd interface - * - * 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. - */ - -/***************************************************************************** - * @file sec_cipher_wd.h - * - * This file provides the interface for SEC ciphers using wd interface - * - *****************************************************************************/ - -#ifndef SEC_CIPHERS_WD_H -#define SEC_CIPHERS_WD_H - -#include "sec_ciphers.h" - -extern KAE_QUEUE_POOL_HEAD_S *g_sec_ciphers_qnode_pool; - -cipher_engine_ctx_t* wd_ciphers_get_engine_ctx(cipher_priv_ctx_t* priv_ctx); -void wd_ciphers_put_engine_ctx(cipher_engine_ctx_t* e_cipher_ctx); -int wd_ciphers_do_crypto_impl(cipher_engine_ctx_t *e_cipher_ctx); - -inline void wd_ciphers_set_input_data(cipher_engine_ctx_t *e_cipher_ctx); -inline void wd_ciphers_get_output_data(cipher_engine_ctx_t *e_cipher_ctx); -inline uint32_t wd_ciphers_get_do_cipher_len(uint32_t offset, int leftlen); - -int wd_ciphers_init_qnode_pool(void); -void wd_ciphers_uninit_qnode_pool(void); - -KAE_QUEUE_POOL_HEAD_S* wd_ciphers_get_qnode_pool(void); -void wd_ciphers_free_engine_ctx(void* engine_ctx); - -#endif - diff --git a/alg/dh/hpre_dh.c b/alg/dh/hpre_dh.c deleted file mode 100644 index 038a54f..0000000 --- a/alg/dh/hpre_dh.c +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the implemenation for KAE engine DH. - * - * 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 "hpre_dh.h" -#include "hpre_dh_wd.h" -#include "hpre_dh_soft.h" -#include "hpre_dh_util.h" -#include "engine_kae.h" -#include "engine_types.h" -#include "engine_opensslerr.h" -#include "async_task_queue.h" - -#define DH768BITS 768 -#define DH1024BITS 1024 -#define DH1536BITS 1536 -#define DH2048BITS 2048 -#define DH3072BITS 3072 -#define DH4096BITS 4096 - -#define GENERATOR_2 2 - -#ifndef OPENSSL_NO_DH -const int DHPKEYMETH_IDX = 1; -#else -const int DHPKEYMETH_IDX = -1; -#endif - -const char* g_hpre_dh_device = "hisi_hpre"; -static DH_METHOD* g_hpre_dh_method = NULL; -static EVP_PKEY_METHOD* g_hpre_dh_pkey_meth = NULL; - -static int hpre_dh_generate_key(DH* dh); - -static int hpre_dh_compute_key(unsigned char* key, const BIGNUM* pub_key, DH* dh); - -static int hpre_db_bn_mod_exp( - const DH* dh, BIGNUM* r, const BIGNUM* a, const BIGNUM* p, const BIGNUM* m, BN_CTX* ctx, BN_MONT_CTX* m_ctx); - -static int check_dh_bit_useful(const int bit); - -static int prepare_dh_data(const int bits, const BIGNUM* g, DH* dh, hpre_dh_engine_ctx_t** eng_ctx, BIGNUM** priv_key); - -static int hpre_dh_ctx_poll(void* engine_ctx); - -const DH_METHOD* hpre_get_dh_methods(void) -{ - int ret = 1; - if (g_hpre_dh_method != NULL) { - return g_hpre_dh_method; - } - - if (!kae_get_device(g_hpre_dh_device)) { - const DH_METHOD* default_soft_method = DH_OpenSSL(); - return default_soft_method; - } - - g_hpre_dh_method = DH_meth_new("HPRE DH method", 0); - if (g_hpre_dh_method == NULL) { - KAEerr(KAE_F_HPRE_GET_DH_METHODS, KAE_R_MALLOC_FAILURE); - US_ERR("Failed to allocate HPRE DH methods"); - return NULL; - } - - ret &= DH_meth_set_generate_key(g_hpre_dh_method, hpre_dh_generate_key); - ret &= DH_meth_set_compute_key(g_hpre_dh_method, hpre_dh_compute_key); - ret &= DH_meth_set_bn_mod_exp(g_hpre_dh_method, hpre_db_bn_mod_exp); - if (ret == 0) { - KAEerr(KAE_F_HPRE_GET_DH_METHODS, KAE_R_DH_SET_METHODS_FAILURE); - US_ERR("Failed to set HPRE DH methods"); - return NULL; - } - - return g_hpre_dh_method; -} - -int hpre_module_dh_init() -{ - wd_hpre_dh_init_qnode_pool(); - - (void)get_dh_pkey_meth(); - (void)hpre_get_dh_methods(); - - /* register async poll func */ - async_register_poll_fn(ASYNC_TASK_DH, hpre_dh_ctx_poll); - - return HPRE_DH_SUCCESS; -} - -void hpre_dh_destroy() -{ - if (g_hpre_dh_method != NULL) { - DH_meth_free(g_hpre_dh_method); - g_hpre_dh_method = NULL; - } -} - -EVP_PKEY_METHOD* get_dh_pkey_meth(void) -{ - const EVP_PKEY_METHOD* def_dh = EVP_PKEY_meth_get0(DHPKEYMETH_IDX); - if (g_hpre_dh_pkey_meth == NULL) { - g_hpre_dh_pkey_meth = EVP_PKEY_meth_new(EVP_PKEY_DH, 0); - if (g_hpre_dh_pkey_meth == NULL) { - US_ERR("failed to new pkey meth"); - return NULL; - } - EVP_PKEY_meth_copy(g_hpre_dh_pkey_meth, def_dh); - } - - return g_hpre_dh_pkey_meth; -} - -EVP_PKEY_METHOD *get_dsa_pkey_meth(void) -{ - return (EVP_PKEY_METHOD*)EVP_PKEY_meth_get0(DHPKEYMETH_IDX); -} - -static int hpre_dh_ctx_poll(void* engine_ctx) -{ - int ret; - hpre_dh_engine_ctx_t* eng_ctx = (hpre_dh_engine_ctx_t*)engine_ctx; - struct wd_queue* q = eng_ctx->qlist->kae_wd_queue; -poll_again: - ret = wcrypto_dh_poll(q, 1); - if (!ret) { - goto poll_again; - } else if (ret < 0) { - US_ERR("dh poll fail!\n"); - return ret; - } - return ret; -} - -static int hpre_dh_generate_key(DH* dh) -{ - int bits = DH_bits(dh); - const BIGNUM* p = NULL; - const BIGNUM* g = NULL; - const BIGNUM* q = NULL; - BIGNUM* pub_key = NULL; - BIGNUM* priv_key = NULL; - hpre_dh_engine_ctx_t* eng_ctx = NULL; - int ret = HPRE_DH_FAIL; - - if (dh == NULL) { - KAEerr(KAE_F_HPRE_DH_KEYGEN, KAE_R_DH_INVALID_PARAMETER); - US_ERR("DH_BUILTIN_KEYGEN KAE_R_DH_INVALID_PARAMETER"); - return HPRE_DH_FAIL; - } - - hpre_dh_soft_get_pg(dh, &p, &g, &q); - if (p == NULL || g == NULL) { - KAEerr(KAE_F_HPRE_DH_KEYGEN, KAE_R_DH_INVALID_PARAMETER); - US_ERR("invalid g or p."); - return HPRE_DH_FAIL; - } - // check whether it is dsa parameter. - CHECK_AND_GOTO(q != NULL, end_soft, "q is not null, then switch to soft!"); - - // check whether bits exceeds the limit. - if (bits > OPENSSL_DH_MAX_MODULUS_BITS) { - KAEerr(KAE_F_HPRE_DH_KEYGEN, KAE_R_DH_KEY_SIZE_TOO_LARGE); - US_ERR("DH_BUILTIN_KEYGEN DH_KEY_SIZE_TOO_LARGE"); - return HPRE_DH_FAIL; - } - - ret = prepare_dh_data(bits, g, dh, &eng_ctx, &priv_key); - CHECK_AND_GOTO(ret != HPRE_DH_SUCCESS, end_soft, "prepare dh data failed!"); - - // construct opdata - ret = hpre_dh_fill_genkey_opdata(g, p, priv_key, eng_ctx); - CHECK_AND_GOTO(ret != HPRE_DH_SUCCESS, end_soft, "fill opdata fail then switch to soft!"); - - // call wd api - ret = hpre_dh_genkey(eng_ctx); - CHECK_AND_GOTO(ret != HPRE_DH_SUCCESS, end_soft, "hpre generate dh key failed.switch to soft!"); - - // get public key from opdata - ret = hpre_dh_get_pubkey(eng_ctx, &pub_key); - CHECK_AND_GOTO(ret != HPRE_DH_SUCCESS, end_soft, "get pub key failed.switch to soft!"); - - // set public key and secret key to the DH. - hpre_dh_soft_set_pkeys(dh, pub_key, priv_key); - -end_soft: - if (pub_key != DH_get0_pub_key(dh)) { - BN_free(pub_key); - } - if (priv_key != DH_get0_priv_key(dh)) { - BN_free(priv_key); - } - hpre_dh_free_eng_ctx(eng_ctx); - - if (ret != HPRE_DH_SUCCESS) { - return hpre_dh_soft_generate_key(dh); - } else { - US_DEBUG("hpre dh generate key success!"); - return HPRE_DH_SUCCESS; - } -} - -static int hpre_dh_compute_key(unsigned char* key, const BIGNUM* pub_key, DH* dh) -{ - int bits = DH_bits(dh); - const BIGNUM* p = NULL; - const BIGNUM* g = NULL; - const BIGNUM* q = NULL; - BIGNUM* priv_key = NULL; - hpre_dh_engine_ctx_t* eng_ctx = NULL; - int ret = HPRE_DH_FAIL; - int ret_size = 0; - - if (dh == NULL || key == NULL || pub_key == NULL || DH_get0_priv_key(dh) == NULL) { - KAEerr(KAE_F_HPRE_DH_KEYCOMP, KAE_R_DH_INVALID_PARAMETER); - US_ERR("KAE_F_HPRE_DH_KEYCOMP KAE_R_DH_INVALID_PARAMETER"); - return HPRE_DH_FAIL; - } - - hpre_dh_soft_get_pg(dh, &p, &g, &q); - if (p == NULL || g == NULL) { - KAEerr(KAE_F_HPRE_DH_KEYCOMP, KAE_R_DH_INVALID_PARAMETER); - US_ERR("invalid g or p."); - return HPRE_DH_FAIL; - } - // check whether it is dsa parameter. - CHECK_AND_GOTO(q != NULL, end_soft, "q is not null, then switch to soft!"); - - // check whether bits exceeds the limit. - if (bits > OPENSSL_DH_MAX_MODULUS_BITS) { - KAEerr(KAE_F_HPRE_DH_KEYCOMP, KAE_R_DH_KEY_SIZE_TOO_LARGE); - US_ERR("DH_BUILTIN_KEYGEN DH_KEY_SIZE_TOO_LARGE"); - return HPRE_DH_FAIL; - } - - ret = prepare_dh_data(bits, g, dh, &eng_ctx, &priv_key); - CHECK_AND_GOTO(ret != HPRE_DH_SUCCESS, end_soft, "prepare dh data failed!"); - - // construct opdata - ret = hpre_dh_fill_compkey_opdata(g, p, priv_key, pub_key, eng_ctx); - CHECK_AND_GOTO(ret != HPRE_DH_SUCCESS, end_soft, "fill opdata fail then switch to soft!"); - - // call wd api to generate shared secret key. - ret = hpre_dh_compkey(eng_ctx); - CHECK_AND_GOTO(ret != HPRE_DH_SUCCESS, end_soft, "hpre compute dh key failed.switch to soft!"); - - ret_size = hpre_dh_get_output_chars(eng_ctx, key); - -end_soft: - - hpre_dh_free_eng_ctx(eng_ctx); - - if (ret != HPRE_DH_SUCCESS) { - return hpre_dh_soft_compute_key(key, pub_key, dh); - } else { - US_DEBUG("hpre dh compute key success!"); - return ret_size; - } -} - -static int hpre_db_bn_mod_exp( - const DH* dh, BIGNUM* r, const BIGNUM* a, const BIGNUM* p, const BIGNUM* m, BN_CTX* ctx, BN_MONT_CTX* m_ctx) -{ - return BN_mod_exp_mont(r, a, p, m, ctx, m_ctx); -} - -static int check_dh_bit_useful(const int bit) -{ - switch (bit) { - case DH768BITS: - case DH1024BITS: - case DH1536BITS: - case DH2048BITS: - case DH3072BITS: - case DH4096BITS: - return 1; - default: - break; - } - return 0; -} - -static int prepare_dh_data(const int bits, const BIGNUM* g, DH* dh, hpre_dh_engine_ctx_t** eng_ctx, BIGNUM** priv_key) -{ - int ret = HPRE_DH_FAIL; - bool is_g2 = BN_is_word(g, GENERATOR_2); - // check whether the bits is supported by hpre. - CHECK_AND_GOTO(!check_dh_bit_useful(bits), err, "op sizes not supported by hpre engine then back to soft!"); - - // get ctx - *eng_ctx = hpre_dh_get_eng_ctx(dh, bits, is_g2); - CHECK_AND_GOTO(*eng_ctx == NULL, err, "get eng ctx fail then switch to soft!"); - - // get private key - ret = hpre_dh_soft_try_get_priv_key(dh, priv_key); - CHECK_AND_GOTO(ret != OPENSSL_SUCCESS, err, "get priv key fail then switch to soft!"); - - return HPRE_DH_SUCCESS; -err: - return HPRE_DH_FAIL; -} \ No newline at end of file diff --git a/alg/dh/hpre_dh.h b/alg/dh/hpre_dh.h deleted file mode 100644 index 893fd39..0000000 --- a/alg/dh/hpre_dh.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the implemenation for KAE engine DH. - * - * 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_DH_H -#define HPRE_DH_H - -#include - -const DH_METHOD *hpre_get_dh_methods(void); - -int hpre_module_dh_init(); - -void hpre_dh_destroy(); - -EVP_PKEY_METHOD *get_dh_pkey_meth(void); - -EVP_PKEY_METHOD *get_dsa_pkey_meth(void); - -#endif \ No newline at end of file diff --git a/alg/dh/hpre_dh_soft.c b/alg/dh/hpre_dh_soft.c deleted file mode 100644 index 73aebb3..0000000 --- a/alg/dh/hpre_dh_soft.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the implemenation for switch to soft dh. - * - * 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 "hpre_dh_soft.h" -#include "engine_types.h" -#include "engine_log.h" - -static int generate_new_priv_key(const DH* dh, BIGNUM* new_priv_key); - -void hpre_dh_soft_get_pg(const DH* dh, const BIGNUM** p, const BIGNUM** g, const BIGNUM** q) -{ - DH_get0_pqg(dh, p, q, g); -} - -int hpre_dh_soft_try_get_priv_key(const DH* dh, BIGNUM** priv_key) -{ - int generate_new_key = 0; - BIGNUM* new_priv_key = NULL; - - // get the private key from dh. - *priv_key = (BIGNUM*)DH_get0_priv_key(dh); - if (*priv_key == NULL) { - new_priv_key = BN_secure_new(); - if (new_priv_key == NULL) { - goto err; - } - generate_new_key = 1; - } - - if (generate_new_key) { - // generate random private key,referencing function 'generate_key' in openssl - if (generate_new_priv_key(dh, new_priv_key) == OPENSSL_FAIL) { - goto err; - } else { - *priv_key = new_priv_key; - } - } - return OPENSSL_SUCCESS; - -err: - BN_free(new_priv_key); - return OPENSSL_FAIL; -} - -void hpre_dh_soft_set_pkeys(DH* dh, BIGNUM* pub_key, BIGNUM* priv_key) -{ - const BIGNUM* old_pub = DH_get0_pub_key(dh); - const BIGNUM* old_priv = DH_get0_priv_key(dh); - if (old_pub != pub_key && old_priv != priv_key) { - DH_set0_key(dh, pub_key, priv_key); - } else if (old_pub != pub_key) { - DH_set0_key(dh, pub_key, NULL); - } else if (old_priv != priv_key) { - DH_set0_key(dh, NULL, priv_key); - } -} - -int hpre_dh_soft_generate_key(DH* dh) -{ - int (*dh_soft_generate_key)(DH *dh); - - dh_soft_generate_key = DH_meth_get_generate_key(DH_OpenSSL()); - int ret = dh_soft_generate_key(dh); - if (ret < 0) { - US_ERR("dh soft key generate fail: %d", ret); - return OPENSSL_FAIL; - } - - return OPENSSL_SUCCESS; -} - -int hpre_dh_soft_compute_key(unsigned char* key, const BIGNUM* pub_key, DH* dh) -{ - int (*dh_soft_compute_key)(unsigned char *key, const BIGNUM *pub_key, DH *dh); - - dh_soft_compute_key = DH_meth_get_compute_key(DH_OpenSSL()); - int ret = dh_soft_compute_key(key, pub_key, dh); - if (ret < 0) { - US_ERR("dh soft key compute fail: %d", ret); - return OPENSSL_FAIL; - } - - return ret; -} - -static int generate_new_priv_key(const DH* dh, BIGNUM* new_priv_key) -{ - const BIGNUM* q = DH_get0_q(dh); - int l; - - if (q) { - do { - if (!BN_priv_rand_range(new_priv_key, q)) { - return OPENSSL_FAIL; - } - } while (BN_is_zero(new_priv_key) || BN_is_one(new_priv_key)); - } else { - l = DH_get_length(dh) ? DH_get_length(dh) : BN_num_bits(DH_get0_p(dh)) - 1; - if (!BN_priv_rand(new_priv_key, l, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY)) { - return OPENSSL_FAIL; - } - } - - return OPENSSL_SUCCESS; -} \ No newline at end of file diff --git a/alg/dh/hpre_dh_soft.h b/alg/dh/hpre_dh_soft.h deleted file mode 100644 index 69158ef..0000000 --- a/alg/dh/hpre_dh_soft.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the implemenation for switch to soft dh. - * - * 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_DH_SOFT_H -#define HPRE_DH_SOFT_H - -#include - -/* -* get p, g, q in dh. -*/ -void hpre_dh_soft_get_pg(const DH* dh, const BIGNUM** p, const BIGNUM** g, const BIGNUM** q); - -/* -* get private key in dh, if null, then generate a random one. -*/ -int hpre_dh_soft_try_get_priv_key(const DH* dh, BIGNUM** priv_key); - -/* -* put private key and public key in the dh. -*/ -void hpre_dh_soft_set_pkeys(DH* dh, BIGNUM* pub_key, BIGNUM* priv_key); - -/* -* call openssl API to generate public key . -*/ -int hpre_dh_soft_generate_key(DH* dh); - -/* -* call openssl API to generate secret key . -*/ -int hpre_dh_soft_compute_key(unsigned char* key, const BIGNUM* pub_key, DH* dh); - -#endif \ No newline at end of file diff --git a/alg/dh/hpre_dh_util.h b/alg/dh/hpre_dh_util.h deleted file mode 100644 index d1de78b..0000000 --- a/alg/dh/hpre_dh_util.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides common function for DH. - * - * 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_DH_UTILS_H -#define HPRE_DH_UTILS_H - -#define HPRE_DH_SUCCESS 1 -#define HPRE_DH_FAIL 0 - -#define CHECK_AND_GOTO(cond, goto_tag, log) \ - do { \ - if (cond) { \ - US_WARN(log); \ - goto goto_tag; \ - } \ - } while (0) - -#endif \ No newline at end of file diff --git a/alg/dh/hpre_dh_wd.c b/alg/dh/hpre_dh_wd.c deleted file mode 100644 index 75bb287..0000000 --- a/alg/dh/hpre_dh_wd.c +++ /dev/null @@ -1,429 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides wd api for DH. - * - * 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 "hpre_dh_wd.h" -#include "hpre_dh_util.h" -#include "engine_types.h" -#include "engine_log.h" -#include "async_callback.h" -#include "async_task_queue.h" -#include "async_event.h" -#include "utils/engine_check.h" -#include - -#define DH_GENERATOR_2 2 -#define DH_GENERATOR_5 5 -#define CHAR_BIT_SIZE 3 -#define DH_PARAMS_CNT 4 -#define MAX_SEND_TRY_CNTS 50 -#define WD_STATUS_BUSY (-EBUSY) - -KAE_QUEUE_POOL_HEAD_S* g_hpre_dh_qnode_pool = NULL; - -static hpre_dh_engine_ctx_t* hpre_dh_new_eng_ctx(DH* alg); - -static int hpre_dh_init_eng_ctx(hpre_dh_engine_ctx_t* eng_ctx, int bits, bool is_g2); - -static int hpre_dh_set_g(const BIGNUM* g, const int key_size, unsigned char* ag_bin, hpre_dh_engine_ctx_t* engine_ctx); - -static int hpre_dh_fill_g_p_priv_key( - const BIGNUM* g, const BIGNUM* p, const BIGNUM* priv_key, hpre_dh_engine_ctx_t* engine_ctx, unsigned char* ag_bin); - -static int hpre_dh_internal_do(void* ctx, struct wcrypto_dh_op_data* opdata); - -static int hpre_dh_fill_pub_key(const BIGNUM* pub_key, hpre_dh_engine_ctx_t* engine_ctx, unsigned char* ag_bin); - -static void hpre_dh_free_opdata(hpre_dh_engine_ctx_t* eng_ctx); - -static int hpre_internal_do_dh(hpre_dh_engine_ctx_t *eng_ctx, enum wcrypto_dh_op_type op_type); - -static int hpre_dh_async(hpre_dh_engine_ctx_t *eng_ctx, - struct wcrypto_dh_op_data *opdata, op_done_t *op_done); - -void wd_hpre_dh_uninit_qnode_pool(void) -{ - kae_queue_pool_destroy(g_hpre_dh_qnode_pool, NULL); - g_hpre_dh_qnode_pool = NULL; -} - -int wd_hpre_dh_init_qnode_pool(void) -{ - kae_queue_pool_destroy(g_hpre_dh_qnode_pool, NULL); - - g_hpre_dh_qnode_pool = kae_init_queue_pool(WCRYPTO_DH); - if (g_hpre_dh_qnode_pool == NULL) { - US_ERR("hpre dh qnode poll init fail!\n"); - return KAE_FAIL; - } - - return KAE_SUCCESS; -} - -KAE_QUEUE_POOL_HEAD_S* wd_hpre_dh_get_qnode_pool() -{ - return g_hpre_dh_qnode_pool; -} - -hpre_dh_engine_ctx_t* hpre_dh_get_eng_ctx(DH* dh, int bits, bool is_g2) -{ - hpre_dh_engine_ctx_t* eng_ctx = hpre_dh_new_eng_ctx(dh); - if (eng_ctx == NULL) { - US_WARN("new eng ctx fail then switch to soft!"); - return NULL; - } - - if (hpre_dh_init_eng_ctx(eng_ctx, bits, is_g2) == 0) { - hpre_dh_free_eng_ctx(eng_ctx); - US_WARN("init eng ctx fail then switch to soft!"); - return NULL; - } - return eng_ctx; -} - -int hpre_dh_fill_genkey_opdata( - const BIGNUM* g, const BIGNUM* p, const BIGNUM* priv_key, hpre_dh_engine_ctx_t* engine_ctx) -{ - unsigned char* ag_bin = NULL; - int key_size = engine_ctx->priv_ctx.key_size; - - // allocate data block - ag_bin = (unsigned char *)kae_wd_alloc_blk(engine_ctx->qlist->kae_queue_mem_pool, key_size); - if (!ag_bin) { - US_ERR("pool alloc ag_bin fail!"); - return -ENOMEM; - } - int ret = hpre_dh_fill_g_p_priv_key(g, p, priv_key, engine_ctx, ag_bin); - if (ret != HPRE_DH_SUCCESS) { - kae_wd_free_blk(engine_ctx->qlist->kae_queue_mem_pool, ag_bin); - return ret; - } - engine_ctx->priv_ctx.block_addr = ag_bin; - - return HPRE_DH_SUCCESS; -} - -int hpre_dh_fill_compkey_opdata( - const BIGNUM* g, const BIGNUM* p, const BIGNUM* priv_key, const BIGNUM* pub_key, hpre_dh_engine_ctx_t* engine_ctx) -{ - unsigned char* ag_bin = NULL; - int key_size = engine_ctx->priv_ctx.key_size; - - ag_bin = (unsigned char*)kae_wd_alloc_blk(engine_ctx->qlist->kae_queue_mem_pool, key_size); - if (!ag_bin) { - US_ERR("pool alloc ag_bin fail!"); - return -ENOMEM; - } - int ret = hpre_dh_fill_g_p_priv_key(g, p, priv_key, engine_ctx, ag_bin); - if (ret != HPRE_DH_SUCCESS) { - kae_wd_free_blk(engine_ctx->qlist->kae_queue_mem_pool, ag_bin); - return ret; - } - - ret = hpre_dh_fill_pub_key(pub_key, engine_ctx, ag_bin); - if (ret != HPRE_DH_SUCCESS) { - return ret; - } - engine_ctx->priv_ctx.block_addr = ag_bin; - - return HPRE_DH_SUCCESS; -} - -int hpre_dh_genkey(hpre_dh_engine_ctx_t* engine_ctx) -{ - return hpre_internal_do_dh(engine_ctx, WCRYPTO_DH_PHASE1); -} - -int hpre_dh_compkey(hpre_dh_engine_ctx_t* engine_ctx) -{ - return hpre_internal_do_dh(engine_ctx, WCRYPTO_DH_PHASE2); -} - -int hpre_dh_get_output_chars(hpre_dh_engine_ctx_t* engine_ctx, unsigned char* out) -{ - kae_memcpy(out, engine_ctx->opdata.pri, engine_ctx->opdata.pri_bytes); - return engine_ctx->opdata.pri_bytes; -} - -int hpre_dh_get_pubkey(hpre_dh_engine_ctx_t* engine_ctx, BIGNUM** pubkey) -{ - const unsigned char* pubkey_str = (const unsigned char*)engine_ctx->opdata.pri; - if (pubkey_str == NULL) { - return HPRE_DH_FAIL; - } - *pubkey = BN_bin2bn(pubkey_str, engine_ctx->opdata.pri_bytes, *pubkey); - if (*pubkey == NULL) { - return HPRE_DH_FAIL; - } - - return HPRE_DH_SUCCESS; -} - -void hpre_dh_free_eng_ctx(hpre_dh_engine_ctx_t* eng_ctx) -{ - US_DEBUG("hpre dh free engine ctx start!"); - if (eng_ctx == NULL) { - US_DEBUG("no eng_ctx to free"); - return; - } - - if (eng_ctx->qlist != NULL) { - if (eng_ctx->ctx != NULL) { - wcrypto_del_dh_ctx(eng_ctx->ctx); - } - kae_put_node_to_pool(g_hpre_dh_qnode_pool, eng_ctx->qlist); - } - - hpre_dh_free_opdata(eng_ctx); - - eng_ctx->priv_ctx.block_addr = NULL; - eng_ctx->priv_ctx.ssl_alg = NULL; - eng_ctx->qlist = NULL; - eng_ctx->ctx = NULL; - eng_ctx->opdata.pri = NULL; - eng_ctx->opdata.x_p = NULL; - eng_ctx->opdata.pv = NULL; - OPENSSL_free(eng_ctx); - eng_ctx = NULL; - - return; -} - -static int hpre_internal_do_dh(hpre_dh_engine_ctx_t *eng_ctx, enum wcrypto_dh_op_type op_type) -{ - int job_ret; - op_done_t op_done; - - async_init_op_done(&op_done); - - eng_ctx->opdata.op_type = op_type; - if (op_done.job != NULL && kae_is_async_enabled()) { - if (async_setup_async_event_notification(0) == 0) { - US_ERR("hpre async event notifying failed"); - async_cleanup_op_done(&op_done); - return HPRE_DH_FAIL; - } - } else { - US_DEBUG("hpre dh no async Job or async disable, back to sync!"); - async_cleanup_op_done(&op_done); - return hpre_dh_internal_do(eng_ctx->ctx, &eng_ctx->opdata); - } - - if (hpre_dh_async(eng_ctx, &eng_ctx->opdata, &op_done) == HPRE_DH_FAIL) - goto err; - - do { - job_ret = async_pause_job(op_done.job, ASYNC_STATUS_OK); - if (job_ret == 0) { - US_DEBUG("- pthread_yidle -"); - kae_pthread_yield(); - } - } - while (!op_done.flag || - ASYNC_CHK_JOB_RESUMED_UNEXPECTEDLY(job_ret)); - - if (op_done.verifyRst <= 0) { - US_ERR("hpre dh verify result failed with %d", op_done.verifyRst); - async_cleanup_op_done(&op_done); - return HPRE_DH_FAIL; - } - - async_cleanup_op_done(&op_done); - - US_DEBUG("hpre dh do async job success!"); - return HPRE_DH_SUCCESS; - -err: - US_ERR("hpre dh do async job err"); - (void)async_clear_async_event_notification(); - async_cleanup_op_done(&op_done); - return HPRE_DH_FAIL; -} - -static void hpre_dh_free_opdata(hpre_dh_engine_ctx_t* eng_ctx) -{ - if (eng_ctx->priv_ctx.block_addr != NULL) { - if (eng_ctx->qlist != NULL) { - eng_ctx->dh_setup.br.free(eng_ctx->qlist->kae_queue_mem_pool, eng_ctx->priv_ctx.block_addr); - } - } -} - -static hpre_dh_engine_ctx_t* hpre_dh_new_eng_ctx(DH* alg) -{ - hpre_dh_engine_ctx_t* eng_ctx = NULL; - eng_ctx = (hpre_dh_engine_ctx_t*)OPENSSL_malloc(sizeof(hpre_dh_engine_ctx_t)); - if (eng_ctx == NULL) { - US_ERR("hpre engine_ctx malloc fail"); - return NULL; - } - kae_memset(eng_ctx, 0, sizeof(hpre_dh_engine_ctx_t)); - - eng_ctx->priv_ctx.ssl_alg = alg; - eng_ctx->qlist = kae_get_node_from_pool(g_hpre_dh_qnode_pool); - if (eng_ctx->qlist == NULL) { - US_ERR_LIMIT("error. get hardware queue failed"); - OPENSSL_free(eng_ctx); - eng_ctx = NULL; - return NULL; - } - return eng_ctx; -} - -static void hpre_dh_cb(const void *message, void *tag) -{ - if (!message || !tag) { - US_ERR("hpre cb params err!\n"); - return; - } - struct wcrypto_dh_msg *msg = (struct wcrypto_dh_msg *)message; - hpre_dh_engine_ctx_t *eng_ctx = (hpre_dh_engine_ctx_t *)tag; - eng_ctx->opdata.pri = msg->out; - eng_ctx->opdata.pri_bytes = msg->out_bytes; - eng_ctx->opdata.status = msg->result; -} - -static int hpre_dh_init_eng_ctx(hpre_dh_engine_ctx_t* eng_ctx, int bits, bool is_g2) -{ - struct wd_queue* q = eng_ctx->qlist->kae_wd_queue; - struct wd_queue_mempool* pool = eng_ctx->qlist->kae_queue_mem_pool; - - // this is for ctx is in use.we dont need to re create ctx->ctx again - if (eng_ctx->ctx) { - return OPENSSL_SUCCESS; - } - if (eng_ctx->ctx == NULL) { - if (bits == 0) { - eng_ctx->priv_ctx.key_size = DH_size(eng_ctx->priv_ctx.ssl_alg); - } else { - eng_ctx->priv_ctx.key_size = bits >> CHAR_BIT_SIZE; - } - eng_ctx->priv_ctx.block_addr = NULL; - eng_ctx->dh_setup.key_bits = eng_ctx->priv_ctx.key_size << CHAR_BIT_SIZE; - eng_ctx->dh_setup.cb = hpre_dh_cb; - eng_ctx->dh_setup.br.alloc = kae_wd_alloc_blk; - eng_ctx->dh_setup.br.free = kae_wd_free_blk; - eng_ctx->dh_setup.br.usr = pool; - eng_ctx->dh_setup.is_g2 = is_g2; - eng_ctx->ctx = wcrypto_create_dh_ctx(q, &eng_ctx->dh_setup); - if (eng_ctx->ctx == NULL) { - US_ERR("create dh ctx fail!"); - return OPENSSL_FAIL; - } - } - - return OPENSSL_SUCCESS; -} - -static int hpre_dh_set_g(const BIGNUM* g, const int key_size, unsigned char* ag_bin, hpre_dh_engine_ctx_t* engine_ctx) -{ - struct wd_dtb g_dtb; - __u32 gbytes = BN_bn2bin(g, ag_bin); - g_dtb.data = (char*)ag_bin; - g_dtb.bsize = key_size; - g_dtb.dsize = gbytes; - int ret = wcrypto_set_dh_g(engine_ctx->ctx, &g_dtb); - if (ret) { - US_ERR("wcrypto_set_dh_g fail: %d", ret); - return HPRE_DH_FAIL; - } - return HPRE_DH_SUCCESS; -} - -static int hpre_dh_fill_g_p_priv_key( - const BIGNUM* g, const BIGNUM* p, const BIGNUM* priv_key, hpre_dh_engine_ctx_t* engine_ctx, unsigned char* ag_bin) -{ - unsigned char* apriv_key_bin = NULL; - unsigned char* ap_bin = NULL; - int key_size = engine_ctx->priv_ctx.key_size; - int ret = 0; - - apriv_key_bin = ag_bin + key_size; - ap_bin = apriv_key_bin + key_size; - memset(ag_bin, 0, key_size * DH_PARAMS_CNT); - - // construct data block of g - ret = hpre_dh_set_g(g, key_size, ag_bin, engine_ctx); - if (ret != HPRE_DH_SUCCESS) { - return HPRE_DH_FAIL; - } - - // construct data block of p and private key - engine_ctx->opdata.pbytes = BN_bn2bin(p, ap_bin); - engine_ctx->opdata.xbytes = BN_bn2bin(priv_key, apriv_key_bin); - - engine_ctx->opdata.x_p = apriv_key_bin; - engine_ctx->opdata.pri = ap_bin + key_size; - - return HPRE_DH_SUCCESS; -} - -static int hpre_dh_internal_do(void* ctx, struct wcrypto_dh_op_data* opdata) -{ - int ret = wcrypto_do_dh(ctx, opdata, NULL); - if (ret) { - US_ERR("wcrypto_do_dh fail: %d", ret); - return HPRE_DH_FAIL; - } else if (opdata->pri == NULL) { - US_ERR("output is empty"); - return HPRE_DH_FAIL; - } else { - return HPRE_DH_SUCCESS; - } -} - -static int hpre_dh_fill_pub_key(const BIGNUM* pub_key, hpre_dh_engine_ctx_t* engine_ctx, unsigned char* ag_bin) -{ - engine_ctx->opdata.pvbytes = BN_bn2bin(pub_key, ag_bin); - engine_ctx->opdata.pv = ag_bin; /* bob's public key here */ - return HPRE_DH_SUCCESS; -} - -static int hpre_dh_async(hpre_dh_engine_ctx_t *eng_ctx, - struct wcrypto_dh_op_data *opdata, op_done_t *op_done) -{ - int ret = 0; - int cnt = 0; - enum task_type type = ASYNC_TASK_DH; - void *tag = eng_ctx; - do { - if (cnt > MAX_SEND_TRY_CNTS) { - break; - } - ret = wcrypto_do_dh(eng_ctx->ctx, opdata, tag); - if (ret == WD_STATUS_BUSY) { - if ((async_wake_job(op_done->job, ASYNC_STATUS_EAGAIN) == 0 || - (async_pause_job(op_done->job, ASYNC_STATUS_EAGAIN) == 0))) { - US_ERR("hpre wake job or hpre pause job fail!"); - ret = 0; - break; - } - cnt++; - } - } while (ret == WD_STATUS_BUSY); - - if (ret != WD_SUCCESS) { - return HPRE_DH_FAIL; - } - - if (async_add_poll_task(eng_ctx, op_done, type) == 0) { - return HPRE_DH_FAIL; - } - - return HPRE_DH_SUCCESS; -} diff --git a/alg/dh/hpre_dh_wd.h b/alg/dh/hpre_dh_wd.h deleted file mode 100644 index 2df20c1..0000000 --- a/alg/dh/hpre_dh_wd.h +++ /dev/null @@ -1,88 +0,0 @@ - -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides wd api for DH. - * - * 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_DH_WD_H -#define HPRE_DH_WD_H - -#include -#include "wdmngr/wd_queue_memory.h" -#include "wd_dh.h" - -struct hpre_dh_priv_ctx { - DH* ssl_alg; - int key_size; - unsigned char* block_addr; -}; - -typedef struct hpre_dh_priv_ctx hpre_dh_priv_ctx_t; - -struct hpre_dh_engine_ctx { - void* ctx; - struct wcrypto_dh_op_data opdata; - struct wcrypto_dh_ctx_setup dh_setup; - struct KAE_QUEUE_DATA_NODE* qlist; - hpre_dh_priv_ctx_t priv_ctx; -}; - -typedef struct hpre_dh_engine_ctx hpre_dh_engine_ctx_t; - -extern KAE_QUEUE_POOL_HEAD_S *g_hpre_dh_qnode_pool; - -int wd_hpre_dh_init_qnode_pool(void); -void wd_hpre_dh_uninit_qnode_pool(void); - -KAE_QUEUE_POOL_HEAD_S* wd_hpre_dh_get_qnode_pool(); - -void hpre_dh_free_eng_ctx(hpre_dh_engine_ctx_t* eng_ctx); - -hpre_dh_engine_ctx_t* hpre_dh_get_eng_ctx(DH* dh, int bits, bool is_g2); - -/* -* fill opdata for generate_key. -*/ -int hpre_dh_fill_genkey_opdata(const BIGNUM* g, const BIGNUM* p, - const BIGNUM* priv_key, hpre_dh_engine_ctx_t* engine_ctx); - -/* -* fill opdata for compute_key. -*/ -int hpre_dh_fill_compkey_opdata(const BIGNUM* g, const BIGNUM* p, - const BIGNUM* priv_key, const BIGNUM* pub_key, hpre_dh_engine_ctx_t* engine_ctx); - -/* -* call wd API for generating public key. -*/ -int hpre_dh_genkey(hpre_dh_engine_ctx_t* engine_ctx); - -/* -* call wd API for generating secret key. -*/ -int hpre_dh_compkey(hpre_dh_engine_ctx_t* engine_ctx); - -/* -* get public key from engine ctx. -*/ -int hpre_dh_get_pubkey(hpre_dh_engine_ctx_t* engine_ctx, BIGNUM** pubkey); - -/* -* get secret key from engine ctx. -*/ -int hpre_dh_get_output_chars(hpre_dh_engine_ctx_t* engine_ctx, unsigned char* out); - -#endif diff --git a/alg/digests/sec_digests.c b/alg/digests/sec_digests.c deleted file mode 100644 index 0f4746d..0000000 --- a/alg/digests/sec_digests.c +++ /dev/null @@ -1,586 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the implemenation for KAE engine digests - * - * 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 "sec_digests.h" -#include "sec_digests_soft.h" -#include "sec_digests_wd.h" - -#include "engine_check.h" -#include "engine_utils.h" -#include "engine_types.h" -#include "engine_log.h" -#include "async_callback.h" -#include "async_event.h" -#include "async_task_queue.h" - -#define DIGEST_SM3_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT (512) -#define DIGEST_MD5_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT (8 * 1024) - -struct digest_info { - int nid; - int is_enabled; - EVP_MD *digest; -}; - -static struct digest_threshold_table g_digest_pkt_threshold_table[] = { - { NID_sm3, DIGEST_SM3_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT }, - { NID_md5, DIGEST_MD5_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT }, -}; - -static struct digest_info g_sec_digests_info[] = { - { NID_sm3, 1, NULL }, - { NID_md5, 1, NULL }, -}; - -#define DIGESTS_COUNT (BLOCKSIZES_OF(g_sec_digests_info)) -static int g_known_digest_nids[DIGESTS_COUNT] = { - NID_sm3, - NID_md5, -}; - -#define SEC_DIGESTS_RETURN_FAIL_IF(cond, mesg, ret) \ - if (unlikely(cond)) {\ - US_ERR(mesg); \ - return (ret); \ - }\ - -static int sec_digests_init(EVP_MD_CTX *ctx); -static int sec_digests_update(EVP_MD_CTX *ctx, const void *data, size_t data_len); -static int sec_digests_final(EVP_MD_CTX *ctx, unsigned char *digest); -static int sec_digests_cleanup(EVP_MD_CTX *ctx); -static int sec_digests_dowork(sec_digest_priv_t *md_ctx); -static int sec_digests_sync_dowork(sec_digest_priv_t *md_ctx); -static int sec_digests_async_dowork(sec_digest_priv_t *md_ctx, op_done_t *op_done); -static uint32_t sec_digests_sw_get_threshold(int nid); - -void sec_digests_set_enabled(int nid, int enabled) { - unsigned int i = 0; - for (i = 0; i < DIGESTS_COUNT; i++) { - if (g_sec_digests_info[i].nid == nid) { - g_sec_digests_info[i].is_enabled = enabled; - } - } -} -static uint32_t sec_digests_sw_get_threshold(int nid) -{ - int threshold_table_sz = BLOCKSIZES_OF(g_digest_pkt_threshold_table); - int i = 0; - do { - if (g_digest_pkt_threshold_table[i].nid == nid) { - return g_digest_pkt_threshold_table[i].threshold; - } - } while (++i < threshold_table_sz); - - US_ERR("nid %d not found in digest threshold table", nid); - return UINT_MAX; -} - -static void sec_digests_get_alg(sec_digest_priv_t *md_ctx) -{ - switch (md_ctx->e_nid) { - case NID_sm3: - md_ctx->d_alg = WCRYPTO_SM3; - md_ctx->out_len = SM3_LEN; - break; - case NID_md5: - md_ctx->d_alg = WCRYPTO_MD5; - md_ctx->out_len = MD5_HASH_LEN; - break; - default: - US_WARN("nid=%d don't support by sec engine.", md_ctx->e_nid); - break; - } -} - -int sec_digests_init(EVP_MD_CTX *ctx) -{ - sec_digest_priv_t *md_ctx = NULL; - if (unlikely(ctx == NULL)) { - return OPENSSL_FAIL; - } - - md_ctx = (sec_digest_priv_t *)EVP_MD_CTX_md_data(ctx); - if (unlikely(md_ctx == NULL)) { - return OPENSSL_FAIL; - } - memset((void *)md_ctx, 0, sizeof(sec_digest_priv_t)); - int nid = EVP_MD_nid(EVP_MD_CTX_md(ctx)); - md_ctx->e_nid = nid; - sec_digests_get_alg(md_ctx); - md_ctx->state = SEC_DIGEST_INIT; - - return OPENSSL_SUCCESS; -} - -static int sec_digests_update_inner(sec_digest_priv_t *md_ctx, size_t data_len, const void *data) -{ - int ret = OPENSSL_FAIL; - size_t left_len = data_len; - const unsigned char* tmpdata = (const unsigned char *)data; - while (md_ctx->last_update_bufflen + left_len > INPUT_CACHE_SIZE) { - int copy_to_bufflen = INPUT_CACHE_SIZE - md_ctx->last_update_bufflen; - kae_memcpy(md_ctx->last_update_buff + md_ctx->last_update_bufflen, tmpdata, copy_to_bufflen); - md_ctx->last_update_bufflen = INPUT_CACHE_SIZE; - left_len -= copy_to_bufflen; - tmpdata += copy_to_bufflen; - - if (md_ctx->state == SEC_DIGEST_INIT) { - md_ctx->state = SEC_DIGEST_FIRST_UPDATING; - } else if (md_ctx->state == SEC_DIGEST_FIRST_UPDATING) { - md_ctx->state = SEC_DIGEST_DOING; - } else { - (void)md_ctx->state; - } - - ret = sec_digests_sync_dowork(md_ctx); - if (ret != KAE_SUCCESS) { - US_WARN("do sec digest failed, switch to soft digest"); - goto do_soft_digest; - } - - md_ctx->last_update_bufflen = 0; - if (left_len <= INPUT_CACHE_SIZE) { - md_ctx->last_update_bufflen = left_len; - kae_memcpy(md_ctx->last_update_buff, tmpdata, md_ctx->last_update_bufflen); - break; - } - } - - return OPENSSL_SUCCESS; - -do_soft_digest: - if (md_ctx->state == SEC_DIGEST_FIRST_UPDATING - && md_ctx->last_update_buff - && md_ctx->last_update_bufflen != 0) { - md_ctx->switch_flag = 1; - sec_digests_soft_init(md_ctx->soft_ctx, md_ctx->e_nid); - ret = sec_digests_soft_update(md_ctx->soft_ctx, md_ctx->last_update_buff, - md_ctx->last_update_bufflen, md_ctx->e_nid); - ret &= sec_digests_soft_update(md_ctx->soft_ctx, tmpdata, left_len, md_ctx->e_nid); - - return ret; - } else { - US_ERR("do sec digest failed"); - return OPENSSL_FAIL; - } -} - -static int sec_digests_update(EVP_MD_CTX *ctx, const void *data, - size_t data_len) -{ - SEC_DIGESTS_RETURN_FAIL_IF(unlikely(!ctx || !data), "ctx is NULL.", OPENSSL_FAIL); - sec_digest_priv_t *md_ctx = (sec_digest_priv_t *)EVP_MD_CTX_md_data(ctx); - SEC_DIGESTS_RETURN_FAIL_IF(unlikely(md_ctx == NULL), "md_ctx is NULL.", OPENSSL_FAIL); - - if (md_ctx->soft_ctx == NULL) { - md_ctx->soft_ctx = EVP_MD_CTX_new(); - } - - if (md_ctx->switch_flag) { - return sec_digests_soft_update(md_ctx->soft_ctx, data, data_len, md_ctx->e_nid); - } - - if (md_ctx->e_digest_ctx == NULL) { - md_ctx->e_digest_ctx = wd_digests_get_engine_ctx(md_ctx); - if (md_ctx->e_digest_ctx == NULL) { - US_WARN("failed to get engine ctx"); - return OPENSSL_FAIL; - } - } - digest_engine_ctx_t *e_digest_ctx = md_ctx->e_digest_ctx; - if (md_ctx->last_update_buff == NULL) { - md_ctx->last_update_buff = e_digest_ctx->op_data.in; - } - - int nid = EVP_MD_nid(EVP_MD_CTX_md(ctx)); - md_ctx->e_nid = nid; - sec_digests_get_alg(md_ctx); - unsigned char digest[MAX_OUTLEN] = {0}; - md_ctx->out = digest; - - if (md_ctx->last_update_bufflen + data_len <= INPUT_CACHE_SIZE) { - kae_memcpy(md_ctx->last_update_buff + md_ctx->last_update_bufflen, data, data_len); - md_ctx->last_update_bufflen += data_len; - return OPENSSL_SUCCESS; - } - - return sec_digests_update_inner(md_ctx, data_len, data); -} - -static int sec_digests_final(EVP_MD_CTX *ctx, unsigned char *digest) -{ - int ret = KAE_FAIL; - - SEC_DIGESTS_RETURN_FAIL_IF(!ctx || !digest, "ctx is NULL.", OPENSSL_FAIL); - sec_digest_priv_t *md_ctx = (sec_digest_priv_t *)EVP_MD_CTX_md_data(ctx); - SEC_DIGESTS_RETURN_FAIL_IF(unlikely(md_ctx == NULL), "md_ctx is NULL.", OPENSSL_FAIL); - - if (md_ctx->switch_flag) { - ret = sec_digests_soft_final(md_ctx->soft_ctx, digest, md_ctx->e_nid); - goto end; - } - - if (md_ctx->last_update_bufflen == 0) { - US_WARN("no data input, swich to soft digest"); - goto do_soft_digest; - } - - if (md_ctx->last_update_buff && md_ctx->last_update_bufflen != 0) { - if (md_ctx->state == SEC_DIGEST_INIT - && md_ctx->last_update_bufflen < sec_digests_sw_get_threshold(md_ctx->e_nid)) { - US_WARN_LIMIT("small package offload, switch to soft digest"); - goto do_soft_digest; - } - - uint32_t tmp = md_ctx->state; - md_ctx->state = SEC_DIGEST_FINAL; - - md_ctx->out = digest; - ret = sec_digests_dowork(md_ctx); - if (ret != KAE_SUCCESS) { - US_WARN("do sec digest failed, switch to soft digest"); - md_ctx->state = tmp; - goto do_soft_digest; - } - ret = OPENSSL_SUCCESS; - } - - US_DEBUG("do digest success. ctx=%p", md_ctx); - -end: - sec_digests_soft_cleanup(md_ctx); - if (md_ctx->e_digest_ctx != NULL) { - (void)wd_digests_put_engine_ctx(md_ctx->e_digest_ctx); - md_ctx->e_digest_ctx = NULL; - } - - return ret; - -do_soft_digest: - if (md_ctx->state == SEC_DIGEST_INIT) { - sec_digests_soft_work(md_ctx, md_ctx->last_update_bufflen, digest); - ret = OPENSSL_SUCCESS; - } else { - US_ERR("do sec digest failed"); - ret = OPENSSL_FAIL; - } - - if (md_ctx->e_digest_ctx != NULL) { - (void)wd_digests_put_engine_ctx(md_ctx->e_digest_ctx); - md_ctx->e_digest_ctx = NULL; - } - - return ret; -} - -static void sec_digests_update_md_ctx(sec_digest_priv_t* md_ctx) -{ - if (md_ctx->do_digest_len == 0) { - return; - } - - md_ctx->in += md_ctx->do_digest_len; -} - -static int sec_digests_dowork(sec_digest_priv_t *md_ctx) -{ - int ret = KAE_FAIL; - - // add async parm - int job_ret; - op_done_t op_done; - - SEC_DIGESTS_RETURN_FAIL_IF(md_ctx->last_update_bufflen <= 0, "in length less than or equal to zero.", KAE_FAIL); - // packageSize>input_cache_size - if (md_ctx->last_update_bufflen > INPUT_CACHE_SIZE) { - ret = sec_digests_sync_dowork(md_ctx); - if (ret != 0) { - US_ERR("sec digest sync fail"); - return ret; - } - return KAE_SUCCESS; - } - - // async - async_init_op_done(&op_done); - - if (op_done.job != NULL && kae_is_async_enabled()) { - if (async_setup_async_event_notification(0) == 0) { - US_ERR("sec async event notifying failed"); - async_cleanup_op_done(&op_done); - return KAE_FAIL; - } - } else { - US_DEBUG("NO ASYNC Job or async disable, back to SYNC!"); - async_cleanup_op_done(&op_done); - return sec_digests_sync_dowork(md_ctx); - } - - if (sec_digests_async_dowork(md_ctx, &op_done) == KAE_FAIL) - goto err; - - do { - job_ret = async_pause_job(op_done.job, ASYNC_STATUS_OK); - if ((job_ret == 0)) { - US_DEBUG("- pthread_yidle -"); - kae_pthread_yield(); - } - } while (!op_done.flag || ASYNC_CHK_JOB_RESUMED_UNEXPECTEDLY(job_ret)); - - if (op_done.verifyRst < 0) { - US_ERR("verify result failed with %d", op_done.verifyRst); - async_cleanup_op_done(&op_done); - return KAE_FAIL; - } - - async_cleanup_op_done(&op_done); - - US_DEBUG(" Digest Async Job Finish! md_ctx = %p\n", md_ctx); - return KAE_SUCCESS; -err: - US_ERR("async job err"); - (void)async_clear_async_event_notification(); - async_cleanup_op_done(&op_done); - return KAE_FAIL; -} - -static int sec_digests_sync_dowork(sec_digest_priv_t *md_ctx) -{ - SEC_DIGESTS_RETURN_FAIL_IF(md_ctx == NULL, "md_ctx is NULL.", KAE_FAIL); - digest_engine_ctx_t *e_digest_ctx = md_ctx->e_digest_ctx; - md_ctx->in = md_ctx->last_update_buff; - uint32_t leftlen = md_ctx->last_update_bufflen; - while (leftlen != 0) { - md_ctx->do_digest_len = wd_digests_get_do_digest_len(e_digest_ctx, leftlen); - - wd_digests_set_input_data(e_digest_ctx); - - int ret = wd_digests_doimpl(e_digest_ctx); - if (ret != KAE_SUCCESS) { - return ret; - } - - wd_digests_get_output_data(e_digest_ctx); - sec_digests_update_md_ctx(md_ctx); - leftlen -= md_ctx->do_digest_len; - } - - US_DEBUG("sec do digest success."); - - return KAE_SUCCESS; -} - -static int sec_digests_async_dowork(sec_digest_priv_t *md_ctx, op_done_t *op_done) -{ - int ret = 0; - int cnt = 0; - enum task_type type = ASYNC_TASK_DIGEST; - - SEC_DIGESTS_RETURN_FAIL_IF(md_ctx == NULL, "md_ctx is NULL.", KAE_FAIL); - digest_engine_ctx_t *e_digest_ctx = md_ctx->e_digest_ctx; - SEC_DIGESTS_RETURN_FAIL_IF(e_digest_ctx == NULL, "e_digest_ctx is NULL", KAE_FAIL); - void *tag = e_digest_ctx; - - md_ctx->in = md_ctx->last_update_buff; - uint32_t leftlen = md_ctx->last_update_bufflen; - md_ctx->do_digest_len = wd_digests_get_do_digest_len(e_digest_ctx, leftlen); - - wd_digests_set_input_data(e_digest_ctx); - - do { - if (cnt > MAX_SEND_TRY_CNTS) { - break; - } - ret = wcrypto_do_digest(e_digest_ctx->wd_ctx, &e_digest_ctx->op_data, tag); - if (ret == -WD_EBUSY) { - if ((async_wake_job(op_done->job, ASYNC_STATUS_EAGAIN) == 0 || - async_pause_job(op_done->job, ASYNC_STATUS_EAGAIN) == 0)) { - US_ERR("sec wake job or sec pause job fail!\n"); - ret = 0; - break; - } - cnt++; - } - } while (ret == -WD_EBUSY); - - if (ret != WD_SUCCESS) { - US_ERR("sec async wcryto do cipher failed"); - return KAE_FAIL; - } - - if (async_add_poll_task(e_digest_ctx, op_done, type) == 0) { - US_ERR("sec add task failed "); - return KAE_FAIL; - } - - return KAE_SUCCESS; -} - -static int sec_digests_cleanup(EVP_MD_CTX *ctx) -{ - return OPENSSL_SUCCESS; -} - -/** - * desc:bind digest func as hardware function - * @return - */ -static EVP_MD *sec_set_digests_methods(struct digest_info digestinfo) -{ - const EVP_MD *default_digest = NULL; - if (digestinfo.digest == NULL) { - switch (digestinfo.nid) { - case NID_sm3: - default_digest = EVP_sm3(); - break; - case NID_md5: - default_digest = EVP_md5(); - break; - default: - return NULL; - } - } - digestinfo.digest = (EVP_MD *)EVP_MD_meth_dup(default_digest); - if (digestinfo.digest == NULL) { - US_ERR("dup digest failed!"); - return NULL; - } - - EVP_MD_meth_set_init(digestinfo.digest, sec_digests_init); - EVP_MD_meth_set_update(digestinfo.digest, sec_digests_update); - EVP_MD_meth_set_final(digestinfo.digest, sec_digests_final); - EVP_MD_meth_set_cleanup(digestinfo.digest, sec_digests_cleanup); - EVP_MD_meth_set_app_datasize(digestinfo.digest, sizeof(sec_digest_priv_t)); - return digestinfo.digest; -} - -static void sec_create_digests(void) -{ - unsigned int i = 0; - for (i = 0; i < DIGESTS_COUNT; i++) { - if (g_sec_digests_info[i].digest == NULL) { - g_sec_digests_info[i].digest = sec_set_digests_methods(g_sec_digests_info[i]); - } - } -} - -/****************************************************************************** -* function: -* sec_engine_digests(ENGINE *e, -* const EVP_digest **digest, -* const int **nids, -* int nid) -* -* @param e [IN] - OpenSSL engine pointer -* @param digest [IN] - digest structure pointer -* @param nids [IN] - digest function nids -* @param nid [IN] - digest operation id -* -* description: -* kae engine digest operations registrar -******************************************************************************/ -int sec_engine_digests(ENGINE *e, const EVP_MD **digest, const int **nids, int nid) -{ - UNUSED(e); - unsigned int i = 0; - - if ((nids == NULL) && ((digest == NULL) || (nid < 0))) { - US_ERR("sec_engine_digests invalid input param."); - if (digest != NULL) { - *digest = NULL; - } - return OPENSSL_FAIL; - } - - /* No specific digest => return a list of supported nids ... */ - /* No specific digest => return a list of supported nids ... */ - if (digest == NULL) { - if (nids != NULL) { - *nids = g_known_digest_nids;; - } - return BLOCKSIZES_OF(g_sec_digests_info); - } - - for (i = 0; i < DIGESTS_COUNT; i++) { - if (g_sec_digests_info[i].nid == nid) { - if (g_sec_digests_info[i].digest == NULL) { - sec_create_digests(); - } - /*SM3 is disabled*/ - *digest = g_sec_digests_info[i].is_enabled - ? g_sec_digests_info[i].digest : (EVP_MD *)EVP_MD_meth_dup(EVP_sm3()); - return OPENSSL_SUCCESS; - } - } - - US_WARN("nid = %d not support.", nid); - *digest = NULL; - - return OPENSSL_FAIL; -} - -void sec_digests_free_methods(void) -{ - unsigned int i = 0; - - for (i = 0; i < DIGESTS_COUNT; i++) { - if (g_sec_digests_info[i].digest != NULL) { - EVP_MD_meth_free(g_sec_digests_info[i].digest); - g_sec_digests_info[i].digest = NULL; - } - } -} - -void sec_digests_cb(const void *msg, void *tag) -{ - if (!msg || !tag) { - US_ERR("sec cb params err!\n"); - return; - } - struct wcrypto_digest_msg *message = (struct wcrypto_digest_msg *)msg; - digest_engine_ctx_t *e_digest_ctx = (digest_engine_ctx_t *)tag; - kae_memcpy(e_digest_ctx->md_ctx->out, message->out, message->out_bytes); -} - -// async poll thread create -int sec_digest_engine_ctx_poll(void *engnine_ctx) -{ - int ret = 0; - digest_engine_ctx_t *e_digest_ctx = (digest_engine_ctx_t *)engnine_ctx; - struct wd_queue *q = e_digest_ctx->q_node->kae_wd_queue; - -POLL_AGAIN: - ret = wcrypto_digest_poll(q, 1); - if (!ret) { - goto POLL_AGAIN; - } else if (ret < 0) { - US_ERR("digest poll failed\n"); - return ret; - } - return ret; -} - -int digest_module_init(void) -{ - wd_digests_init_qnode_pool(); - sec_create_digests(); - // reg async interface here - async_register_poll_fn(ASYNC_TASK_DIGEST, sec_digest_engine_ctx_poll); - - return 1; -} diff --git a/alg/digests/sec_digests.h b/alg/digests/sec_digests.h deleted file mode 100644 index f6788cd..0000000 --- a/alg/digests/sec_digests.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the digest interface for KAE engine - * - * 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 SEC_DIGESTS_H -#define SEC_DIGESTS_H - -#include -#include -#include "wd_digest.h" -#include "wd_queue_memory.h" -#include "engine_types.h" -#include "engine_utils.h" - -#define MAX_SEND_TRY_CNTS 50 - -#define MIN_DIGEST_LEN 512 -#define INPUT_CACHE_SIZE (512 * 1024) -#define SM3_LEN 32 -#define MAX_OUTLEN 64 -#define MD5_HASH_LEN 16 - -enum sec_digest_state { - SEC_DIGEST_INIT = 0, - SEC_DIGEST_FIRST_UPDATING, - SEC_DIGEST_DOING, - SEC_DIGEST_FINAL -}; - -typedef struct digest_engine_ctx digest_engine_ctx_t; -typedef struct sec_digest_priv sec_digest_priv_t; - -struct sec_digest_priv { - uint8_t* last_update_buff; - uint8_t* in; - uint8_t* out; - uint32_t d_mode; // haven't used - uint32_t d_alg; - uint32_t state; - uint32_t last_update_bufflen; - uint32_t do_digest_len; // do one cycle digest length - uint32_t out_len; // digest out length - uint32_t e_nid; // digest nid - digest_engine_ctx_t* e_digest_ctx; - EVP_MD_CTX* soft_ctx; - uint32_t switch_flag; -}; - -struct digest_engine_ctx { - KAE_QUEUE_DATA_NODE_S* q_node; - struct wcrypto_digest_op_data op_data; - struct wcrypto_digest_ctx_setup setup; - void* wd_ctx; // one ctx or a list of ctx - sec_digest_priv_t* md_ctx; -}; - -struct digest_threshold_table { - int nid; - int threshold; -}; -void sec_digests_set_enabled(int nid, int enabled); -int sec_engine_digests(ENGINE *e, const EVP_MD **digest, const int **nids, int nid); -void sec_digests_free_methods(void); -int sec_cipher_engine_ctx_poll(void* engnine_ctx); - -int digest_module_init(void); -void sec_digests_cb(const void* msg, void* tag); -#endif - diff --git a/alg/digests/sec_digests_soft.c b/alg/digests/sec_digests_soft.c deleted file mode 100644 index 8cbe855..0000000 --- a/alg/digests/sec_digests_soft.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the implemenation for switch to soft digests - * - * 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 "sec_digests_soft.h" -#include "engine_opensslerr.h" -#include "engine_log.h" - -static const EVP_MD *sec_digests_soft_md(uint32_t e_nid) -{ - const EVP_MD *g_digest_md = NULL; - switch (e_nid) { - case NID_sm3: - g_digest_md = EVP_sm3(); - break; - case NID_md5: - g_digest_md = EVP_md5(); - break; - default: - break; - } - return g_digest_md; -} - -int sec_digests_soft_init(EVP_MD_CTX *ctx, uint32_t e_nid) -{ - const EVP_MD *digest_md = NULL; - digest_md = sec_digests_soft_md(e_nid); - if (digest_md == NULL) { - US_WARN("switch to soft:don't support by sec engine."); - return OPENSSL_FAIL; - } - int ctx_len = EVP_MD_meth_get_app_datasize(digest_md); - if (ctx->md_data == NULL) { - ctx->md_data = OPENSSL_malloc(ctx_len); - } - if (!ctx->md_data) { - KAEerr(KAE_F_DIGEST_SOFT_INIT, KAE_R_MALLOC_FAILURE); - US_ERR("malloc md_data failed"); - return OPENSSL_FAIL; - } - - return EVP_MD_meth_get_init (digest_md)(ctx); -} - -int sec_digests_soft_update(EVP_MD_CTX *ctx, const void *data, size_t data_len, uint32_t e_nid) -{ - const EVP_MD *digest_md = NULL; - digest_md = sec_digests_soft_md(e_nid); - if (digest_md == NULL) { - US_WARN("switch to soft:don't support by sec engine."); - return OPENSSL_FAIL; - } - return EVP_MD_meth_get_update (digest_md)(ctx, data, data_len); -} - -int sec_digests_soft_final(EVP_MD_CTX *ctx, unsigned char *digest, uint32_t e_nid) -{ - US_WARN_LIMIT("call sec_digest_soft_final"); - - const EVP_MD *digest_md = NULL; - digest_md = sec_digests_soft_md(e_nid); - if (digest_md == NULL) { - US_WARN("switch to soft:don't support by sec engine."); - return OPENSSL_FAIL; - } - int ret = EVP_MD_meth_get_final(digest_md)(ctx, digest); - if (ctx->md_data) { - OPENSSL_free(ctx->md_data); - } - - return ret; -} - -void sec_digests_soft_work(sec_digest_priv_t *md_ctx, int len, unsigned char *digest) -{ - if (md_ctx->soft_ctx == NULL) { - md_ctx->soft_ctx = EVP_MD_CTX_new(); - } - - (void)sec_digests_soft_init(md_ctx->soft_ctx, md_ctx->e_nid); - if (len != 0) { - (void)sec_digests_soft_update(md_ctx->soft_ctx, md_ctx->last_update_buff, len, md_ctx->e_nid); - } - (void)sec_digests_soft_final(md_ctx->soft_ctx, digest, md_ctx->e_nid); - - if (md_ctx->soft_ctx != NULL) { - EVP_MD_CTX_free(md_ctx->soft_ctx); - md_ctx->soft_ctx = NULL; - } - - return; -} - -void sec_digests_soft_cleanup(sec_digest_priv_t *md_ctx) -{ - if (md_ctx->soft_ctx != NULL) { - EVP_MD_CTX_free(md_ctx->soft_ctx); - md_ctx->soft_ctx = NULL; - } - return; -} - diff --git a/alg/digests/sec_digests_soft.h b/alg/digests/sec_digests_soft.h deleted file mode 100644 index 4caa90f..0000000 --- a/alg/digests/sec_digests_soft.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the digest interface for soft digests - * - * 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 SEC_DIGESTS_SOFT_H -#define SEC_DIGESTS_SOFT_H - -#include "sec_digests.h" - -struct evp_md_ctx_st { - const EVP_MD *digest; - ENGINE *engine; /* functional reference if 'digest' is - * ENGINE-provided */ - unsigned long flags; - void *md_data; - /* Public key context for sign/verify */ - EVP_PKEY_CTX *pctx; - /* Update function: usually copied from EVP_MD */ - int (*update)(EVP_MD_CTX *ctx, const void *data, size_t count); -} /* EVP_MD_CTX */; - -int sec_digests_soft_init(EVP_MD_CTX *ctx, uint32_t e_nid); -int sec_digests_soft_update(EVP_MD_CTX *ctx, const void *data, size_t data_len, uint32_t e_nid); -int sec_digests_soft_final(EVP_MD_CTX *ctx, unsigned char *digest, uint32_t e_nid); -void sec_digests_soft_work(sec_digest_priv_t *md_ctx, int len, unsigned char *digest); -void sec_digests_soft_cleanup(sec_digest_priv_t *md_ctx); - -#endif - diff --git a/alg/digests/sec_digests_wd.c b/alg/digests/sec_digests_wd.c deleted file mode 100644 index 8264cf0..0000000 --- a/alg/digests/sec_digests_wd.c +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the implemenation for KAE engine utils dealing with wrapdrive - * - * 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 "sec_digests_wd.h" -#include "wd_queue_memory.h" -#include "engine_utils.h" -#include "engine_types.h" -#include "engine_log.h" - -KAE_QUEUE_POOL_HEAD_S* g_sec_digests_qnode_pool = NULL; -static digest_engine_ctx_t* wd_digests_new_engine_ctx(KAE_QUEUE_DATA_NODE_S* q_node, sec_digest_priv_t* md_ctx); -static int wd_digests_init_engine_ctx(digest_engine_ctx_t *e_digest_ctx); - -void wd_digests_free_engine_ctx(void* digest_ctx) -{ - digest_engine_ctx_t* e_digest_ctx = (digest_engine_ctx_t *)digest_ctx; - if (e_digest_ctx == NULL) { - return; - } - - if (e_digest_ctx->op_data.in && e_digest_ctx->setup.br.usr) { - e_digest_ctx->setup.br.free(e_digest_ctx->setup.br.usr, (void *)e_digest_ctx->op_data.in); - e_digest_ctx->op_data.in = NULL; - } - - if (e_digest_ctx->op_data.out && e_digest_ctx->setup.br.usr) { - e_digest_ctx->setup.br.free(e_digest_ctx->setup.br.usr, (void *)e_digest_ctx->op_data.out); - e_digest_ctx->op_data.out = NULL; - } - - OPENSSL_free(e_digest_ctx); - e_digest_ctx = NULL; - - return; -} - -static digest_engine_ctx_t* wd_digests_new_engine_ctx(KAE_QUEUE_DATA_NODE_S* q_node, sec_digest_priv_t* md_ctx) -{ - digest_engine_ctx_t *e_digest_ctx = NULL; - e_digest_ctx = (digest_engine_ctx_t *)OPENSSL_malloc(sizeof(digest_engine_ctx_t)); - if (e_digest_ctx == NULL) { - US_ERR("digest engine_ctx malloc fail."); - return NULL; - } - kae_memset(e_digest_ctx, 0, sizeof(digest_engine_ctx_t)); - - e_digest_ctx->setup.br.alloc = kae_wd_alloc_blk; - e_digest_ctx->setup.br.free = kae_wd_free_blk; - e_digest_ctx->setup.br.iova_map = kae_dma_map; - e_digest_ctx->setup.br.iova_unmap = kae_dma_unmap; - e_digest_ctx->setup.br.usr = q_node->kae_queue_mem_pool; - - e_digest_ctx->op_data.in = e_digest_ctx->setup.br.alloc(e_digest_ctx->setup.br.usr, DIGEST_BLOCK_SIZE); - if (e_digest_ctx->op_data.in == NULL) { - US_ERR("alloc opdata in buf failed"); - goto err; - } - - e_digest_ctx->op_data.out = e_digest_ctx->setup.br.alloc(e_digest_ctx->setup.br.usr, DIGEST_BLOCK_SIZE); - if (e_digest_ctx->op_data.out == NULL) { - US_ERR("alloc opdata out buf failed"); - goto err; - } - - e_digest_ctx->md_ctx = md_ctx; // point to each other - e_digest_ctx->q_node = q_node; // point to each other - q_node->engine_ctx = e_digest_ctx; // point to each other - - return e_digest_ctx; - -err: - wd_digests_free_engine_ctx(e_digest_ctx); - - return NULL; -} - -static int wd_digests_init_engine_ctx(digest_engine_ctx_t *e_digest_ctx) -{ - struct wd_queue *q = e_digest_ctx->q_node->kae_wd_queue; - sec_digest_priv_t* md_ctx = e_digest_ctx->md_ctx; - - if (e_digest_ctx->wd_ctx != NULL) { - US_WARN("wd ctx is in used by other digests"); - return KAE_FAIL; - } - - e_digest_ctx->setup.alg = (enum wcrypto_digest_alg)md_ctx->d_alg; // for example: WD_SM3; - e_digest_ctx->setup.mode = WCRYPTO_DIGEST_NORMAL; - e_digest_ctx->setup.cb = (wcrypto_cb)sec_digests_cb; - e_digest_ctx->wd_ctx = wcrypto_create_digest_ctx(q, &e_digest_ctx->setup); - if (e_digest_ctx->wd_ctx == NULL) { - US_ERR("wd create sec digest ctx fail!"); - return KAE_FAIL; - } - - return KAE_SUCCESS; -} - -digest_engine_ctx_t* wd_digests_get_engine_ctx(sec_digest_priv_t* md_ctx) -{ - KAE_QUEUE_DATA_NODE_S *q_node = NULL; - digest_engine_ctx_t *e_digest_ctx = NULL; - - if (unlikely(md_ctx == NULL)) { - US_WARN("sec digest priv ctx NULL!"); - return NULL; - } - - q_node = kae_get_node_from_pool(g_sec_digests_qnode_pool); - if (q_node == NULL) { - US_ERR_LIMIT("failed to get hardware queue"); - return NULL; - } - - e_digest_ctx = (digest_engine_ctx_t *)q_node->engine_ctx; - if (e_digest_ctx == NULL) { - e_digest_ctx = wd_digests_new_engine_ctx(q_node, md_ctx); - if (e_digest_ctx == NULL) { - US_WARN("sec new engine ctx fail!"); - (void)kae_put_node_to_pool(g_sec_digests_qnode_pool, q_node); - return NULL; - } - } - - e_digest_ctx->md_ctx = md_ctx; - md_ctx->e_digest_ctx = e_digest_ctx; - - if (wd_digests_init_engine_ctx(e_digest_ctx) == KAE_FAIL) { - US_WARN("init engine ctx fail!"); - wd_digests_put_engine_ctx(e_digest_ctx); - return NULL; - } - - return e_digest_ctx; -} - -void wd_digests_put_engine_ctx(digest_engine_ctx_t* e_digest_ctx) -{ - if (unlikely(e_digest_ctx == NULL)) { - US_WARN("sec digest engine ctx NULL!"); - return; - } - - if (e_digest_ctx->wd_ctx != NULL) { - wcrypto_del_digest_ctx(e_digest_ctx->wd_ctx); - e_digest_ctx->wd_ctx = NULL; - } - - if (e_digest_ctx->q_node != NULL) { - (void)kae_put_node_to_pool(g_sec_digests_qnode_pool, e_digest_ctx->q_node); - } - - e_digest_ctx = NULL; - - return; -} - -int wd_digests_doimpl(digest_engine_ctx_t *e_digest_ctx) -{ - int ret; - int trycount = 0; - - if (unlikely(e_digest_ctx == NULL)) { - US_ERR("do digest ctx NULL!"); - return KAE_FAIL; - } - -again: - ret = wcrypto_do_digest(e_digest_ctx->wd_ctx, &e_digest_ctx->op_data, NULL); - if (ret != WD_SUCCESS) { - if (ret == -WD_EBUSY && trycount <= 5) { // try 5 times - US_WARN("do digest busy, retry again!"); - trycount++; - goto again; - } else { - US_ERR("do digest failed!"); - return KAE_FAIL; - } - } - - return KAE_SUCCESS; -} - -void wd_digests_set_input_data(digest_engine_ctx_t *e_digest_ctx) -{ - // fill engine ctx opdata - sec_digest_priv_t* md_ctx = e_digest_ctx->md_ctx; - - e_digest_ctx->op_data.in_bytes = md_ctx->do_digest_len; - e_digest_ctx->op_data.out_bytes = md_ctx->out_len; - - e_digest_ctx->op_data.has_next = (md_ctx->state == SEC_DIGEST_FINAL) ? false : true; -} - -inline void wd_digests_get_output_data(digest_engine_ctx_t *e_digest_ctx) -{ - sec_digest_priv_t* md_ctx = e_digest_ctx->md_ctx; - - // the real out data start at opdata.out + offset - if (e_digest_ctx->op_data.has_next == false) { - kae_memcpy(md_ctx->out, (uint8_t*)e_digest_ctx->op_data.out, md_ctx->out_len); - } -} - -inline uint32_t wd_digests_get_do_digest_len(digest_engine_ctx_t *e_digest_ctx, int leftlen) -{ - uint32_t do_digest_len = 0; - int max_input_datalen = DIGEST_BLOCK_SIZE; - /* - * Note: Small encrypted block can be encrypted once. - * or the last encrypted slice of a large encrypted block - */ - if (leftlen <= max_input_datalen) { - do_digest_len = leftlen; - } else { - do_digest_len = max_input_datalen; - } - - return do_digest_len; -} - -KAE_QUEUE_POOL_HEAD_S* wd_digests_get_qnode_pool(void) -{ - return g_sec_digests_qnode_pool; -} - -int wd_digests_init_qnode_pool(void) -{ - kae_queue_pool_destroy(g_sec_digests_qnode_pool, wd_digests_free_engine_ctx); - - g_sec_digests_qnode_pool = kae_init_queue_pool(WCRYPTO_DIGEST); - if (g_sec_digests_qnode_pool == NULL) { - US_ERR("do digest ctx NULL!"); - return KAE_FAIL; - } - - return KAE_SUCCESS; -} - -void wd_digests_uninit_qnode_pool(void) -{ - kae_queue_pool_destroy(g_sec_digests_qnode_pool, wd_digests_free_engine_ctx); - g_sec_digests_qnode_pool = NULL; -} \ No newline at end of file diff --git a/alg/digests/sec_digests_wd.h b/alg/digests/sec_digests_wd.h deleted file mode 100644 index 0429e9e..0000000 --- a/alg/digests/sec_digests_wd.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the digest interface for KAE digests using wd interface - * - * 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 SEC_DIGESTS_WD_H -#define SEC_DIGESTS_WD_H - -#include "sec_digests.h" - -extern KAE_QUEUE_POOL_HEAD_S *g_sec_digests_qnode_pool; - -digest_engine_ctx_t* wd_digests_get_engine_ctx(sec_digest_priv_t* md_ctx); -void wd_digests_put_engine_ctx(digest_engine_ctx_t* e_digest_ctx); -int wd_digests_doimpl(digest_engine_ctx_t *e_digest_ctx); - -inline void wd_digests_set_input_data(digest_engine_ctx_t *e_digest_ctx); -inline void wd_digests_get_output_data(digest_engine_ctx_t *e_digest_ctx); -inline uint32_t wd_digests_get_do_digest_len(digest_engine_ctx_t *e_digest_ctx, int leftlen); - -KAE_QUEUE_POOL_HEAD_S* wd_digests_get_qnode_pool(void); -int wd_digests_init_qnode_pool(void); -void wd_digests_uninit_qnode_pool(void); -void wd_digests_free_engine_ctx(void* digest_ctx); - -#endif - diff --git a/alg/pkey/hpre_rsa.c b/alg/pkey/hpre_rsa.c deleted file mode 100644 index 6894ac6..0000000 --- a/alg/pkey/hpre_rsa.c +++ /dev/null @@ -1,717 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the implemenation for KAE engine rsa - * - * 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 "hpre_rsa.h" -#include "hpre_wd.h" -#include "hpre_rsa_soft.h" -#include "async_poll.h" -#include "engine_types.h" -#include "engine_kae.h" -#include "hpre_rsa_utils.h" - -#ifndef OPENSSL_NO_RSA -const int RSAPKEYMETH_IDX = 0; -#else -const int RSAPKEYMETH_IDX = -1; -#endif - -const char *g_hpre_device = "hisi_hpre"; -static RSA_METHOD *g_hpre_rsa_method = NULL; -static RSA_METHOD *g_soft_rsa_method = NULL; -static EVP_PKEY_METHOD *g_hpre_pkey_meth = NULL; - -static int hpre_rsa_public_encrypt(int flen, const unsigned char *from, - unsigned char *to, RSA *rsa, int padding); - -static int hpre_rsa_private_encrypt(int flen, const unsigned char *from, - unsigned char *to, RSA *rsa, int padding); - -static int hpre_rsa_public_decrypt(int flen, const unsigned char *from, - unsigned char *to, RSA *rsa, int padding); - -static int hpre_rsa_private_decrypt(int flen, const unsigned char *from, - unsigned char *to, RSA *rsa, int padding); - -static int hpre_rsa_keygen(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb); - -static int hpre_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx); - -static int hpre_bn_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, - const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); - -RSA_METHOD *hpre_get_rsa_methods(void) -{ - int ret = 1; - if (g_hpre_rsa_method != NULL) { - return g_hpre_rsa_method; - } - if (g_soft_rsa_method != NULL) { - return g_soft_rsa_method; - } - if (!kae_get_device(g_hpre_device)) { - const RSA_METHOD *default_soft_method = RSA_PKCS1_OpenSSL(); - g_soft_rsa_method = RSA_meth_new("SOFT RSA METHOD", 0); - ret &= RSA_meth_set_pub_enc(g_soft_rsa_method, RSA_meth_get_pub_enc(default_soft_method)); - ret &= RSA_meth_set_priv_enc(g_soft_rsa_method, RSA_meth_get_priv_enc(default_soft_method)); - ret &= RSA_meth_set_pub_dec(g_soft_rsa_method, RSA_meth_get_pub_dec(default_soft_method)); - ret &= RSA_meth_set_priv_dec(g_soft_rsa_method, RSA_meth_get_priv_dec(default_soft_method)); - ret &= RSA_meth_set_keygen(g_soft_rsa_method, hpre_rsa_soft_genkey); - ret &= RSA_meth_set_mod_exp(g_soft_rsa_method, RSA_meth_get_mod_exp(default_soft_method)); - ret &= RSA_meth_set_bn_mod_exp(g_soft_rsa_method, RSA_meth_get_bn_mod_exp(default_soft_method)); - if (ret == 0) { - US_ERR("Failed to set SOFT RSA methods"); - return NULL; - } - return g_soft_rsa_method; - } - - g_hpre_rsa_method = RSA_meth_new("HPRE RSA method", 0); - if (g_hpre_rsa_method == NULL) { - KAEerr(KAE_F_HPRE_GET_RSA_METHODS, KAE_R_MALLOC_FAILURE); - US_ERR("Failed to allocate HPRE RSA methods"); - return NULL; - } - - ret &= RSA_meth_set_pub_enc(g_hpre_rsa_method, hpre_rsa_public_encrypt); - ret &= RSA_meth_set_pub_dec(g_hpre_rsa_method, hpre_rsa_public_decrypt); - ret &= RSA_meth_set_priv_enc(g_hpre_rsa_method, hpre_rsa_private_encrypt); - ret &= RSA_meth_set_priv_dec(g_hpre_rsa_method, hpre_rsa_private_decrypt); - ret &= RSA_meth_set_keygen(g_hpre_rsa_method, hpre_rsa_keygen); - ret &= RSA_meth_set_mod_exp(g_hpre_rsa_method, hpre_rsa_mod_exp); - ret &= RSA_meth_set_bn_mod_exp(g_hpre_rsa_method, hpre_bn_mod_exp); - if (ret == 0) { - KAEerr(KAE_F_HPRE_GET_RSA_METHODS, KAE_R_RSA_SET_METHODS_FAILURE); - US_ERR("Failed to set HPRE RSA methods"); - return NULL; - } - - return g_hpre_rsa_method; -} - -static void hpre_free_rsa_methods(void) -{ - if (g_hpre_rsa_method != NULL) { - RSA_meth_free(g_hpre_rsa_method); - g_hpre_rsa_method = NULL; - } - if (g_soft_rsa_method != NULL) { - RSA_meth_free(g_soft_rsa_method); - g_soft_rsa_method = NULL; - } -} - - -int hpre_engine_ctx_poll(void* engine_ctx) -{ - int ret; - hpre_engine_ctx_t *eng_ctx = (hpre_engine_ctx_t *)engine_ctx; - struct wd_queue *q = eng_ctx->qlist->kae_wd_queue; -poll_again: - ret = wcrypto_rsa_poll(q, 1); - if (!ret) { - goto poll_again; - } else if (ret < 0) { - US_ERR("rsa poll fail!\n"); - return ret; - } - return ret; -} - -int hpre_module_init() -{ - /* init queue */ - wd_hpre_init_qnode_pool(); - - (void)get_rsa_pkey_meth(); - (void)hpre_get_rsa_methods(); - - /* register async poll func */ - async_register_poll_fn(ASYNC_TASK_RSA, hpre_engine_ctx_poll); - - return 1; -} - -EVP_PKEY_METHOD *get_rsa_pkey_meth(void) -{ - const EVP_PKEY_METHOD *def_rsa = EVP_PKEY_meth_get0(RSAPKEYMETH_IDX); - if (g_hpre_pkey_meth == NULL) { - g_hpre_pkey_meth = EVP_PKEY_meth_new(EVP_PKEY_RSA, 0); - if (g_hpre_pkey_meth == NULL) { - US_ERR("failed to new pkey meth"); - return NULL; - } - - EVP_PKEY_meth_copy(g_hpre_pkey_meth, def_rsa); - } - - return g_hpre_pkey_meth; -} - -void hpre_destroy() -{ - hpre_free_rsa_methods(); -} - -//lint -save -e506 -#undef GOTOEND_IF -#define GOTOEND_IF(cond, mesg, f, r) \ - if (cond) { \ - KAEerr(f, r); \ - US_ERR(mesg); \ - ret = HPRE_CRYPTO_FAIL; \ - rsa_soft_mark = 1; \ - goto end;\ - } \ - - -static int hpre_rsa_check(const int flen, const BIGNUM *n, const BIGNUM *e, - int *num_bytes, RSA *rsa) -{ - int key_bits; - if (n == NULL || e == NULL) { - return HPRE_CRYPTO_FAIL; - } - - if (check_pubkey_param(n, e) != HPRE_CRYPTO_SUCC) { - return HPRE_CRYPTO_FAIL; - } - - *num_bytes = BN_num_bytes(n); - if (flen > *num_bytes) { - KAEerr(KAE_F_HPRE_RSA_PUBDEC, KAE_R_DATA_GREATER_THEN_MOD_LEN); - US_WARN("data length is large than num bytes of rsa->n"); - return HPRE_CRYPTO_FAIL; - } - - key_bits = RSA_bits(rsa); - if (!check_bit_useful(key_bits)) { - US_WARN("op sizes not supported by hpre engine then back to soft!"); - return HPRE_CRYPTO_FAIL; - } - - return HPRE_CRYPTO_SUCC; -} - -static int hpre_rsa_prepare_opdata(const BIGNUM *n, int flen, - const unsigned char *from, - BN_CTX **bn_ctx, - BIGNUM **bn_ret, BIGNUM **f_ret) -{ - BN_CTX *bn_ctx_tmp; - BIGNUM *bn_ret_tmp = NULL; - BIGNUM *f = NULL; - bn_ctx_tmp = BN_CTX_new(); - if (bn_ctx_tmp == NULL) { - KAEerr(KAE_F_HPRE_RSA_PUBDEC, KAE_R_MALLOC_FAILURE); - US_ERR("fail to new BN_CTX."); - return HPRE_CRYPTO_SOFT; - } - - BN_CTX_start(bn_ctx_tmp); - bn_ret_tmp = BN_CTX_get(bn_ctx_tmp); - f = BN_CTX_get(bn_ctx_tmp); - if (bn_ret_tmp == NULL || f == NULL) { - KAEerr(KAE_F_HPRE_RSA_PUBDEC, KAE_R_MALLOC_FAILURE); - US_ERR("fail to get BN_CTX."); - return HPRE_CRYPTO_SOFT; - } - - if (BN_bin2bn(from, flen, f) == NULL) { - KAEerr(KAE_F_HPRE_RSA_PUBDEC, KAE_R_ERR_LIB_BN); - US_ERR("fail to bin2bn"); - return HPRE_CRYPTO_SOFT; - } - - if (BN_ucmp(f, n) >= 0) { - KAEerr(KAE_F_HPRE_RSA_PUBDEC, KAE_R_DATA_TOO_LARGE_FOR_MODULUS); - US_ERR("data is too large"); - return HPRE_CRYPTO_SOFT; - } - *bn_ctx = bn_ctx_tmp; - *bn_ret = bn_ret_tmp; - *f_ret = f; - return HPRE_CRYPTO_SUCC; -} - - -static int hpre_rsa_public_encrypt(int flen, const unsigned char *from, - unsigned char *to, RSA *rsa, int padding) -{ - int rsa_soft_mark = 0; - const BIGNUM *n = NULL; - const BIGNUM *e = NULL; - const BIGNUM *d = NULL; - BIGNUM *ret_bn = NULL; - hpre_engine_ctx_t *eng_ctx = NULL; - unsigned char *in_buf = NULL; - - if (hpre_rsa_check_para(flen, from, to, rsa) != HPRE_CRYPTO_SUCC) { - return HPRE_CRYPTO_FAIL; - } - int key_bits = RSA_bits(rsa); - if (!check_bit_useful(key_bits)) { - US_WARN("op sizes not supported by hpre engine then back to soft!"); - return hpre_rsa_soft_calc(flen, from, to, rsa, padding, PUB_ENC); - } - - eng_ctx = hpre_get_eng_ctx(rsa, 0); - if (eng_ctx == NULL) { - US_WARN("get eng ctx fail then switch to soft!"); - rsa_soft_mark = 1; - goto end_soft; - } - - RSA_get0_key(rsa, &n, &e, &d); - int ret = check_pubkey_param(n, e); - GOTOEND_IF(ret != HPRE_CRYPTO_SUCC, "check public key fail", - KAE_F_HPRE_RSA_PUBENC, KAE_R_PUBLIC_KEY_INVALID); - - BN_CTX *bn_ctx = BN_CTX_new(); - GOTOEND_IF(bn_ctx == NULL, "bn_ctx MALLOC FAILED!", - KAE_F_HPRE_RSA_PUBENC, KAE_R_MALLOC_FAILURE); - - BN_CTX_start(bn_ctx); - ret_bn = BN_CTX_get(bn_ctx); - int num_bytes = BN_num_bytes(n); - in_buf = (unsigned char *)OPENSSL_malloc(num_bytes); - GOTOEND_IF(ret_bn == NULL || in_buf == NULL, "PUBLIC_ENCRYPT RSA MALLOC FAILED!", - KAE_F_HPRE_RSA_PUBENC, KAE_R_MALLOC_FAILURE); - - ret = hpre_rsa_padding(flen, from, in_buf, num_bytes, padding, PUB_ENC); - GOTOEND_IF(ret == HPRE_CRYPTO_FAIL, "RSA PADDING FAILED", - KAE_F_HPRE_RSA_PUBENC, KAE_R_RSA_PADDING_FAILURE); - - hpre_rsa_fill_pubkey(e, n, eng_ctx); - eng_ctx->opdata.in_bytes = eng_ctx->priv_ctx.key_size; - eng_ctx->opdata.op_type = WCRYPTO_RSA_VERIFY; - eng_ctx->opdata.in = eng_ctx->rsa_setup.br.alloc(eng_ctx->qlist->kae_queue_mem_pool, - eng_ctx->qlist->kae_queue_mem_pool->block_size); - eng_ctx->opdata.out = eng_ctx->rsa_setup.br.alloc(eng_ctx->qlist->kae_queue_mem_pool, - eng_ctx->qlist->kae_queue_mem_pool->block_size); - kae_memcpy(eng_ctx->opdata.in, in_buf, eng_ctx->opdata.in_bytes); - - ret = hpre_rsa_crypto(eng_ctx, &eng_ctx->opdata); - GOTOEND_IF(HPRE_CRYPTO_FAIL == ret, "hpre rsa pub encrypt failed!", - KAE_F_HPRE_RSA_PUBENC, KAE_R_PUBLIC_ENCRYPTO_FAILURE); - - BN_bin2bn((const unsigned char *)eng_ctx->opdata.out, eng_ctx->opdata.out_bytes, ret_bn); - ret = BN_bn2binpad(ret_bn, to, num_bytes); - - US_DEBUG("hpre rsa public encrypt success!"); - -end: - hpre_free_bn_ctx_buf(bn_ctx, in_buf, num_bytes); - hpre_free_eng_ctx(eng_ctx); - -end_soft: - if (rsa_soft_mark == 1) { - ret = hpre_rsa_soft_calc(flen, from, to, rsa, padding, PUB_ENC); - } - - return ret; -} - - -static int hpre_rsa_private_encrypt(int flen, const unsigned char *from, - unsigned char *to, RSA *rsa, int padding) -{ - int ret = HPRE_CRYPTO_FAIL; - int rsa_soft_mark = 0; - hpre_engine_ctx_t *eng_ctx = NULL; - BIGNUM *f = (BIGNUM *)NULL; - BIGNUM *bn_ret = (BIGNUM *)NULL; - BIGNUM *res = (BIGNUM *)NULL; - const BIGNUM *n = (const BIGNUM *)NULL; - const BIGNUM *e = (const BIGNUM *)NULL; - const BIGNUM *d = (const BIGNUM *)NULL; - const BIGNUM *p = (const BIGNUM *)NULL; - const BIGNUM *q = (const BIGNUM *)NULL; - const BIGNUM *dmp1 = (const BIGNUM *)NULL; - const BIGNUM *dmq1 = (const BIGNUM *)NULL; - const BIGNUM *iqmp = (const BIGNUM *)NULL; - unsigned char *in_buf = (unsigned char *)NULL; - - if (hpre_rsa_check_para(flen, from, to, rsa) != HPRE_CRYPTO_SUCC) { - return HPRE_CRYPTO_FAIL; - } - - int key_bits = RSA_bits(rsa); - if (!check_bit_useful(key_bits)) { - US_WARN("op sizes not supported by hpre engine then back to soft!"); - return hpre_rsa_soft_calc(flen, from, to, rsa, padding, PRI_ENC); - } - - eng_ctx = hpre_get_eng_ctx(rsa, 0); - if (eng_ctx == NULL) { - US_WARN("get eng ctx fail then switch to soft!"); - rsa_soft_mark = 1; - goto end_soft; - } - - BN_CTX *bn_ctx = BN_CTX_new(); - GOTOEND_IF(bn_ctx == NULL, "PRI_ENC MALLOC_FAILURE ", - KAE_F_HPRE_RSA_PRIENC, KAE_R_MALLOC_FAILURE); - - BN_CTX_start(bn_ctx); - f = BN_CTX_get(bn_ctx); - bn_ret = BN_CTX_get(bn_ctx); - RSA_get0_factors(rsa, &p, &q); - RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp); - int version = RSA_get_version(rsa); - RSA_get0_key(rsa, &n, &e, &d); - int num_bytes = BN_num_bytes(n); - in_buf = (unsigned char *)OPENSSL_malloc(num_bytes); - GOTOEND_IF(bn_ret == NULL || in_buf == NULL, "OpenSSL malloc failure", - KAE_F_HPRE_RSA_PRIENC, KAE_R_MALLOC_FAILURE); - - ret = hpre_rsa_padding(flen, from, in_buf, num_bytes, padding, PRI_ENC); - GOTOEND_IF(ret == HPRE_CRYPTO_FAIL, "RSA PADDING FAILED!", - KAE_F_HPRE_RSA_PRIENC, KAE_R_RSA_PADDING_FAILURE); - - GOTOEND_IF(NULL == BN_bin2bn(in_buf, num_bytes, f), "BN_bin2bn failure", - KAE_F_HPRE_RSA_PRIENC, KAE_R_ERR_LIB_BN); - - ret = BN_ucmp(f, n); - GOTOEND_IF(ret >= 0, "RSA PADDING FAILED!", - KAE_F_HPRE_RSA_PRIENC, KAE_R_DATA_TOO_LARGE_FOR_MODULUS); - - hpre_rsa_fill_pubkey(e, n, eng_ctx); - hpre_rsa_fill_prikey(rsa, eng_ctx, version, p, q, dmp1, dmq1, iqmp); - - eng_ctx->opdata.in_bytes = eng_ctx->priv_ctx.key_size; - eng_ctx->opdata.op_type = WCRYPTO_RSA_SIGN; - eng_ctx->opdata.in = eng_ctx->rsa_setup.br.alloc(eng_ctx->qlist->kae_queue_mem_pool, - eng_ctx->qlist->kae_queue_mem_pool->block_size); - eng_ctx->opdata.out = eng_ctx->rsa_setup.br.alloc(eng_ctx->qlist->kae_queue_mem_pool, - eng_ctx->qlist->kae_queue_mem_pool->block_size); - kae_memcpy(eng_ctx->opdata.in, in_buf, eng_ctx->opdata.in_bytes); - - ret = hpre_rsa_crypto(eng_ctx, &eng_ctx->opdata); - if (ret == HPRE_CRYPTO_FAIL) { - US_WARN("hpre rsa priv encrypt failed!"); - rsa_soft_mark = 1; - goto end; - } - - BN_bin2bn((const unsigned char *)eng_ctx->opdata.out, eng_ctx->opdata.out_bytes, bn_ret); - - if (hpre_get_prienc_res(padding, f, n, bn_ret, &res) == HPRE_CRYPTO_FAIL) { - goto end; - } - - ret = BN_bn2binpad(res, to, num_bytes); - - US_DEBUG("hpre rsa priv encrypt success!"); - - end: - hpre_free_bn_ctx_buf(bn_ctx, in_buf, num_bytes); - hpre_free_eng_ctx(eng_ctx); - - end_soft: - if (rsa_soft_mark == 1) { - ret = hpre_rsa_soft_calc(flen, from, to, rsa, padding, PRI_ENC); - } - - return ret; -} - -static int hpre_rsa_public_decrypt(int flen, const unsigned char *from, - unsigned char *to, RSA *rsa, int padding) -{ - hpre_engine_ctx_t *eng_ctx = NULL; - BIGNUM *bn_ret = NULL; - BIGNUM *f = NULL; - BN_CTX *bn_ctx = NULL; - const BIGNUM *n = NULL; - const BIGNUM *e = NULL; - const BIGNUM *d = NULL; - - int num_bytes = 0; - int rsa_soft_mark = 0; - unsigned char *buf = NULL; - - if (hpre_rsa_check_para(flen, from, to, rsa) != HPRE_CRYPTO_SUCC) { - return HPRE_CRYPTO_FAIL; - } - - RSA_get0_key(rsa, &n, &e, &d); - int ret = hpre_rsa_check(flen, n, e, &num_bytes, rsa); - if (ret == HPRE_CRYPTO_FAIL) { - rsa_soft_mark = 1; - goto end_soft; - } - - eng_ctx = hpre_get_eng_ctx(rsa, 0); - if (eng_ctx == NULL) { - US_WARN("get eng ctx fail then switch to soft!"); - rsa_soft_mark = 1; - goto end_soft; - } - - buf = (unsigned char *)OPENSSL_malloc(num_bytes); - if (buf == NULL) { - rsa_soft_mark = 1; - goto end; - } - - ret = hpre_rsa_prepare_opdata(n, flen, from, &bn_ctx, &bn_ret, &f); - if (ret == HPRE_CRYPTO_SOFT) { - rsa_soft_mark = 1; - goto end; - } - - hpre_rsa_fill_pubkey(e, n, eng_ctx); - eng_ctx->opdata.in_bytes = eng_ctx->priv_ctx.key_size; - eng_ctx->opdata.op_type = WCRYPTO_RSA_VERIFY; - eng_ctx->opdata.in = eng_ctx->rsa_setup.br.alloc(eng_ctx->qlist->kae_queue_mem_pool, - eng_ctx->qlist->kae_queue_mem_pool->block_size); - eng_ctx->opdata.out = eng_ctx->rsa_setup.br.alloc(eng_ctx->qlist->kae_queue_mem_pool, - eng_ctx->qlist->kae_queue_mem_pool->block_size); - kae_memcpy(eng_ctx->opdata.in, from, eng_ctx->opdata.in_bytes); - - ret = hpre_rsa_crypto(eng_ctx, &eng_ctx->opdata); - GOTOEND_IF(HPRE_CRYPTO_FAIL == ret, "hpre rsa pub decrypt failed!", - KAE_F_HPRE_RSA_PUBDEC, KAE_R_PUBLIC_DECRYPTO_FAILURE); - - BN_bin2bn((const unsigned char *)eng_ctx->opdata.out, eng_ctx->opdata.out_bytes, bn_ret); - if ((padding == RSA_X931_PADDING) && ((bn_get_words(bn_ret)[0] & 0xf) != 12)) { // not 12 then BN_sub - GOTOEND_IF(!BN_sub(bn_ret, n, bn_ret), "BN_sub failed", - KAE_F_HPRE_RSA_PUBDEC, KAE_R_ERR_LIB_BN); - } - int len = BN_bn2binpad(bn_ret, buf, num_bytes); - ret = check_rsa_padding(to, num_bytes, buf, len, padding, PUB_DEC); - if (ret == HPRE_CRYPTO_FAIL) { - US_WARN("hpre rsa check padding failed.switch to soft"); - rsa_soft_mark = 1; - goto end; - } - - US_DEBUG("hpre rsa public decrypt success!"); - -end: - hpre_free_bn_ctx_buf(bn_ctx, buf, num_bytes); - hpre_free_eng_ctx(eng_ctx); - -end_soft: - if (rsa_soft_mark == 1) { - ret = hpre_rsa_soft_calc(flen, from, to, rsa, padding, PUB_DEC); - } - - return ret; -} - -static int hpre_rsa_private_decrypt(int flen, const unsigned char *from, - unsigned char *to, RSA *rsa, int padding) -{ - int ret = HPRE_CRYPTO_FAIL; - const BIGNUM *n = (const BIGNUM *)NULL; - const BIGNUM *e = (const BIGNUM *)NULL; - const BIGNUM *d = (const BIGNUM *)NULL; - const BIGNUM *p = (const BIGNUM *)NULL; - const BIGNUM *q = (const BIGNUM *)NULL; - const BIGNUM *dmp1 = (const BIGNUM *)NULL; - const BIGNUM *dmq1 = (const BIGNUM *)NULL; - const BIGNUM *iqmp = (const BIGNUM *)NULL; - BIGNUM *f = (BIGNUM *)NULL; - BIGNUM *bn_ret = (BIGNUM *)NULL; - int len; - int rsa_soft_mark = 0; - unsigned char *buf = (unsigned char *)NULL; - BN_CTX *bn_ctx = NULL; - - if (hpre_rsa_check_para(flen, from, to, rsa) != HPRE_CRYPTO_SUCC) { - return HPRE_CRYPTO_FAIL; - } - - RSA_get0_key(rsa, &n, &e, &d); - int num_bytes = BN_num_bytes(n); - if (flen > num_bytes) { - KAEerr(KAE_F_HPRE_RSA_PRIDEC, KAE_R_DATA_GREATER_THEN_MOD_LEN); - US_ERR("PRIVATE_DECRYPT DATA_GREATER_THAN_MOD_LEN"); - return HPRE_CRYPTO_FAIL; - } - - int key_bits = RSA_bits(rsa); - if (!check_bit_useful(key_bits)) { - US_WARN("op sizes not supported by hpre engine then back to soft!"); - return hpre_rsa_soft_calc(flen, from, to, rsa, padding, PRI_DEC); - } - - hpre_engine_ctx_t *eng_ctx = hpre_get_eng_ctx(rsa, 0); - if (eng_ctx == NULL) { - US_WARN("get eng ctx fail then switch to soft!"); - rsa_soft_mark = 1; - goto end_soft; - } - - bn_ctx = BN_CTX_new(); - GOTOEND_IF(bn_ctx == NULL, "bn_ctx MALLOC FAILED!", - KAE_F_HPRE_RSA_PRIDEC, KAE_R_ERR_LIB_BN); - - BN_CTX_start(bn_ctx); - f = BN_CTX_get(bn_ctx); - bn_ret = BN_CTX_get(bn_ctx); - RSA_get0_factors(rsa, &p, &q); - RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp); - int version = RSA_get_version(rsa); - buf = (unsigned char *)OPENSSL_malloc(num_bytes); - GOTOEND_IF(bn_ret == NULL || buf == NULL, "PRIVATE_DECRYPT ERR_R_MALLOC_FAILURE", - KAE_F_HPRE_RSA_PRIDEC, KAE_R_MALLOC_FAILURE); - - GOTOEND_IF(BN_bin2bn(from, (int) flen, f) == NULL, "BN_bin2bn failure", - KAE_F_HPRE_RSA_PRIDEC, KAE_R_ERR_LIB_BN); - - GOTOEND_IF(BN_ucmp(f, n) >= 0, "PRIVATE_DECRYPT, RSA_R_DATA_TOO_LARGE_FOR_MODULUS", - KAE_F_HPRE_RSA_PRIDEC, KAE_R_DATA_TOO_LARGE_FOR_MODULUS); - - hpre_rsa_fill_pubkey(e, n, eng_ctx); - hpre_rsa_fill_prikey(rsa, eng_ctx, version, p, q, dmp1, dmq1, iqmp); - - eng_ctx->opdata.in_bytes = eng_ctx->priv_ctx.key_size; - eng_ctx->opdata.op_type = WCRYPTO_RSA_SIGN; - eng_ctx->opdata.in = eng_ctx->rsa_setup.br.alloc(eng_ctx->qlist->kae_queue_mem_pool, - eng_ctx->qlist->kae_queue_mem_pool->block_size); - eng_ctx->opdata.out = eng_ctx->rsa_setup.br.alloc(eng_ctx->qlist->kae_queue_mem_pool, - eng_ctx->qlist->kae_queue_mem_pool->block_size); - kae_memcpy(eng_ctx->opdata.in, from, eng_ctx->opdata.in_bytes); - - ret = hpre_rsa_crypto(eng_ctx, &eng_ctx->opdata); - if (ret == HPRE_CRYPTO_FAIL) { - US_WARN("hpre rsa priv decrypt failed.switch to soft"); - rsa_soft_mark = 1; - goto end; - } - - BN_bin2bn((const unsigned char *)eng_ctx->opdata.out, eng_ctx->opdata.out_bytes, bn_ret); - len = BN_bn2binpad(bn_ret, buf, num_bytes); - ret = check_rsa_padding(to, num_bytes, buf, len, padding, PRI_DEC); - if (ret == HPRE_CRYPTO_FAIL) { - US_WARN("hpre rsa check padding failed.switch to soft"); - rsa_soft_mark = 1; - goto end; - } - - US_DEBUG("hpre rsa priv decrypt success!"); - -end: - hpre_free_bn_ctx_buf(bn_ctx, buf, num_bytes); - hpre_free_eng_ctx(eng_ctx); - -end_soft: - if (rsa_soft_mark == 1) { - ret = hpre_rsa_soft_calc(flen, from, to, rsa, padding, PRI_DEC); - } - return ret; -} - -static int hpre_rsa_keygen(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb) -{ - int ret = HPRE_CRYPTO_FAIL; - int rsa_soft_mark = 0; - struct wcrypto_rsa_pubkey *pubkey = NULL; - struct wcrypto_rsa_prikey *prikey = NULL; - struct wd_dtb *wd_e = NULL; - struct wd_dtb *wd_p = NULL; - struct wd_dtb *wd_q = NULL; - - if (bits < RSA_MIN_MODULUS_BITS) { - KAEerr(KAE_F_HPRE_RSA_KEYGEN, KAE_R_RSA_KEY_SIZE_TOO_SMALL); - US_ERR("RSA_BUILTIN_KEYGEN RSA_R_KEY_SIZE_TOO_SMALL"); - return HPRE_CRYPTO_FAIL; - } - - if (!check_bit_useful(bits)) { - US_WARN("op sizes not supported by hpre engine then back to soft!"); - return hpre_rsa_soft_genkey(rsa, bits, e, cb); - } - - hpre_engine_ctx_t *eng_ctx = hpre_get_eng_ctx(rsa, bits); - if (eng_ctx == NULL) { - US_WARN("get eng ctx fail then switch to soft!"); - rsa_soft_mark = 1; - goto end_soft; - } - - BIGNUM *e_value = BN_new(); - BIGNUM *p = BN_new(); - BIGNUM *q = BN_new(); - GOTOEND_IF(e_value == NULL || p == NULL || q == NULL, "e_value or p or q MALLOC FAILED.", - KAE_F_HPRE_RSA_KEYGEN, KAE_R_ERR_LIB_BN); - - GOTOEND_IF(hpre_rsa_primegen(bits, e, p, q, cb) == OPENSSL_FAIL, "hisi_rsa_primegen failed", - KAE_F_HPRE_RSA_KEYGEN, KAE_R_GET_PRIMEKEY_FAILURE); - - GOTOEND_IF(BN_copy(e_value, e) == NULL, "copy e failed", - KAE_F_HPRE_RSA_KEYGEN, KAE_R_ERR_LIB_BN); - - wcrypto_get_rsa_pubkey(eng_ctx->ctx, &pubkey); - wcrypto_get_rsa_pubkey_params(pubkey, &wd_e, NULL); - wd_e->dsize = BN_bn2bin(e_value, (unsigned char *)wd_e->data); - wcrypto_get_rsa_prikey(eng_ctx->ctx, &prikey); - wcrypto_get_rsa_crt_prikey_params(prikey, NULL, NULL, NULL, &wd_q, &wd_p); - wd_q->dsize = BN_bn2bin(q, (unsigned char *)wd_q->data); - wd_p->dsize = BN_bn2bin(p, (unsigned char *)wd_p->data); - - eng_ctx->opdata.in_bytes = eng_ctx->priv_ctx.key_size; - eng_ctx->opdata.op_type = WCRYPTO_RSA_GENKEY; - ret = hpre_fill_keygen_opdata(eng_ctx->ctx, &eng_ctx->opdata); - if (ret != KAE_SUCCESS) { - US_WARN("hpre_fill_keygen_opdata failed"); - rsa_soft_mark = 1; - goto end; - } - ret = hpre_rsa_sync(eng_ctx->ctx, &eng_ctx->opdata); - if (ret == HPRE_CRYPTO_FAIL) { - US_WARN("hpre generate rsa key failed.switch to soft"); - rsa_soft_mark = 1; - goto end; - } - ret = hpre_rsa_get_keygen_param(&eng_ctx->opdata, eng_ctx->ctx, rsa, - e_value, p, q); - - US_DEBUG("hpre rsa keygen success!"); - -end: - hpre_free_eng_ctx(eng_ctx); - -end_soft: - if (rsa_soft_mark == 1) { - ret = hpre_rsa_soft_genkey(rsa, bits, e, cb); - } - return ret; -} - -static int hpre_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) -{ - US_DEBUG("- Started\n"); - return RSA_meth_get_mod_exp(RSA_PKCS1_OpenSSL()) - (r0, I, rsa, ctx); -} - -static int hpre_bn_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, - const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) -{ - US_DEBUG("- Started\n"); - return RSA_meth_get_bn_mod_exp(RSA_PKCS1_OpenSSL()) - (r, a, p, m, ctx, m_ctx); -} - diff --git a/alg/pkey/hpre_rsa.h b/alg/pkey/hpre_rsa.h deleted file mode 100644 index 8b1ffc2..0000000 --- a/alg/pkey/hpre_rsa.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the implemenation for KAE rsa using wd interface - * - * 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_RSA_H -#define HPRE_RSA_H - -#include -#include - -#include -#include -#include -#include -#include - -#include "../utils/engine_utils.h" -#include "../utils/engine_opensslerr.h" - -#define RSA_MIN_MODULUS_BITS 512 - -#define RSA1024BITS 1024 -#define RSA2048BITS 2048 -#define RSA3072BITS 3072 -#define RSA4096BITS 4096 - -#define HPRE_CONT (-1) -#define HPRE_CRYPTO_SUCC 1 -#define HPRE_CRYPTO_FAIL 0 -#define HPRE_CRYPTO_SOFT (-1) - - -enum { - INVAID = 0, - PUB_ENC, - PUB_DEC, - PRI_ENC, - PRI_DEC, - MAX_CODE, -}; - -struct bignum_st { - BN_ULONG *d; - int top; - int dmax; - int neg; - int flags; -}; - -RSA_METHOD *hpre_get_rsa_methods(void); - -int hpre_module_init(); - -void hpre_destroy(); - -EVP_PKEY_METHOD *get_rsa_pkey_meth(void); - -#endif - diff --git a/alg/pkey/hpre_rsa_soft.c b/alg/pkey/hpre_rsa_soft.c deleted file mode 100644 index f0fb278..0000000 --- a/alg/pkey/hpre_rsa_soft.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the implemenation for switch to soft rsa - * - * 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 "hpre_rsa.h" -#include "engine_log.h" - -/** - * succ: > 0 - * fail: 0 - */ -int hpre_rsa_soft_calc(int flen, const unsigned char *from, unsigned char *to, - RSA *rsa, int padding, int type) -{ - US_DEBUG("hpre_rsa_soft_calc.\n"); - int ret = 0; - const RSA_METHOD *soft_rsa = RSA_PKCS1_OpenSSL(); - switch (type) { - case PUB_ENC: - ret = RSA_meth_get_pub_enc(soft_rsa)(flen, from, to, rsa, padding); - break; - case PUB_DEC: - ret = RSA_meth_get_pub_dec(soft_rsa)(flen, from, to, rsa, padding); - break; - case PRI_ENC: - ret = RSA_meth_get_priv_enc(soft_rsa)(flen, from, to, rsa, padding); - break; - case PRI_DEC: - ret = RSA_meth_get_priv_dec(soft_rsa)(flen, from, to, rsa, padding); - break; - default: - return 0; - } - return ret; -} - -/** - * succ: 1 - * fail: 0 - */ -int hpre_rsa_soft_genkey(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb) -{ - US_DEBUG("hpre_rsa_soft_genkey.\n"); - UNUSED(cb); - const RSA_METHOD *default_meth = RSA_PKCS1_OpenSSL(); - RSA_set_method(rsa, default_meth); - int ret = RSA_generate_key_ex(rsa, bits, e, (BN_GENCB *)NULL); - if (ret != 1) { - US_ERR("rsa soft key generate fail!"); - return 0; - } - - return 1; -} diff --git a/alg/pkey/hpre_rsa_soft.h b/alg/pkey/hpre_rsa_soft.h deleted file mode 100644 index 9bfeab5..0000000 --- a/alg/pkey/hpre_rsa_soft.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the rsa interface for soft rsa - * - * 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_RSA_SOFT_H -#define HPRE_RSA_SOFT_H - -#include - -int hpre_rsa_soft_calc(int flen, const unsigned char *from, unsigned char *to, - RSA *rsa, int padding, int type); - -int hpre_rsa_soft_genkey(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb); - -#endif diff --git a/alg/pkey/hpre_rsa_utils.c b/alg/pkey/hpre_rsa_utils.c deleted file mode 100644 index 902455d..0000000 --- a/alg/pkey/hpre_rsa_utils.c +++ /dev/null @@ -1,562 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the implemenation for KAE engine utils dealing with wrapdrive - * - * 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 "engine_types.h" -#include "engine_log.h" -#include "hpre_rsa.h" -#include "hpre_wd.h" -#include "wd_rsa.h" - -BN_ULONG *bn_get_words(const BIGNUM *a) -{ - return a->d; -} - -void hpre_free_bn_ctx_buf(BN_CTX *bn_ctx, unsigned char *in_buf, int num) -{ - if (bn_ctx != NULL) { - BN_CTX_end(bn_ctx); - } - BN_CTX_free(bn_ctx); - if (in_buf != NULL) { - OPENSSL_clear_free(in_buf, num); - } -} - -/* check parameter */ -int hpre_rsa_check_para(int flen, const unsigned char *from, - unsigned char *to, RSA *rsa) -{ - if ((rsa == NULL || from == NULL || to == NULL || flen <= 0)) { - US_ERR("RSA key %p, input %p or output %p are NULL, \ - or flen invalid length.\n", rsa, from, to); - return HPRE_CRYPTO_FAIL; - } - return HPRE_CRYPTO_SUCC; -} - -int hpre_get_prienc_res(int padding, BIGNUM *f, const BIGNUM *n, BIGNUM *bn_ret, BIGNUM **res) -{ - if (padding == RSA_X931_PADDING) { - if (!BN_sub(f, n, bn_ret)) { - return HPRE_CRYPTO_FAIL; - } - if (BN_cmp(bn_ret, f) > 0) { - *res = f; - } else { - *res = bn_ret; - } - } else { - *res = bn_ret; - } - return HPRE_CRYPTO_SUCC; -} - -/** - * func: - * desc: - * Check HPRE rsa bits - * - * @param bit :rsa bit - * @return - * succ: 1 - * fail: 0 - */ -int check_bit_useful(const int bit) -{ - switch (bit) { - case RSA1024BITS: - case RSA2048BITS: - case RSA3072BITS: - case RSA4096BITS: - return 1; - default: - break; - } - return 0; -} - -/** - * - * @param n - * @param e - * @return success 1 / failed 0 - */ -int check_pubkey_param(const BIGNUM *n, const BIGNUM *e) -{ - if (BN_num_bits(n) > OPENSSL_RSA_MAX_MODULUS_BITS) { - KAEerr(KAE_F_CHECK_PUBKEY_PARAM, KAE_R_MODULE_TOO_LARGE); - US_ERR("RSA MODULUS TOO LARGE!"); - return HPRE_CRYPTO_FAIL; - } - - if (BN_ucmp(n, e) <= 0) { - KAEerr(KAE_F_CHECK_PUBKEY_PARAM, KAE_R_INVAILED_E_VALUE); - US_ERR("RSA E VALUE IS NOT VALID!"); - return HPRE_CRYPTO_FAIL; - } - - /* for large moduli, enforce exponent limit */ - if (BN_num_bits(n) > OPENSSL_RSA_SMALL_MODULUS_BITS) { - if (BN_num_bits(e) > OPENSSL_RSA_MAX_PUBEXP_BITS) { - KAEerr(KAE_F_CHECK_PUBKEY_PARAM, KAE_R_INVAILED_E_VALUE); - US_ERR("RSA E VALUE IS NOT VALID!"); - return HPRE_CRYPTO_FAIL; - } - } - return HPRE_CRYPTO_SUCC; -} - -static int hpre_pubenc_padding(int flen, const unsigned char *from, - unsigned char *buf, int num, int padding) -{ - int ret = HPRE_CRYPTO_FAIL; - - switch (padding) { - case RSA_PKCS1_PADDING: - ret = RSA_padding_add_PKCS1_type_2(buf, num, from, flen); - break; - case RSA_PKCS1_OAEP_PADDING: - ret = RSA_padding_add_PKCS1_OAEP(buf, num, from, flen, - NULL, 0); - break; - case RSA_SSLV23_PADDING: - ret = RSA_padding_add_SSLv23(buf, num, from, flen); - break; - case RSA_NO_PADDING: - ret = RSA_padding_add_none(buf, num, from, flen); - break; - default: - KAEerr(KAE_F_HPRE_PUBENC_PADDING, KAE_R_UNKNOW_PADDING_TYPE); - US_ERR("RSA UNKNOWN PADDING TYPE!"); - ret = HPRE_CRYPTO_FAIL; - } - if (ret <= 0) { - US_ERR("padding error: ret = %d", ret); - ret = HPRE_CRYPTO_FAIL; - } else { - ret = HPRE_CRYPTO_SUCC; - } - return ret; -} - -static int hpre_prienc_padding(int flen, const unsigned char *from, - unsigned char *buf, int num, int padding) -{ - int ret = HPRE_CRYPTO_FAIL; - - switch (padding) { - case RSA_PKCS1_PADDING: - ret = RSA_padding_add_PKCS1_type_1(buf, num, from, flen); - break; - case RSA_X931_PADDING: - ret = RSA_padding_add_X931(buf, num, from, flen); - break; - case RSA_NO_PADDING: - ret = RSA_padding_add_none(buf, num, from, flen); - break; - default: - KAEerr(KAE_F_HPRE_PRIENC_PADDING, KAE_R_UNKNOW_PADDING_TYPE); - US_ERR("RSA UNKNOWN PADDING TYPE!"); - ret = HPRE_CRYPTO_FAIL; - } - if (ret <= 0) { - US_DEBUG("padding error: ret = %d", ret); - ret = HPRE_CRYPTO_FAIL; - } else { - ret = HPRE_CRYPTO_SUCC; - } - return ret; -} - -/** - * func: - * - * @param flen [IN] - size in bytes of input - * @param from [IN] - pointer to the input - * @param buf [OUT] - pointer to output data - * @param num [IN] - pointer to public key structure - * @param padding [IN] - Padding scheme - * @param type [IN] - Padding type - * @return - * SUCCESS: 1 - * FAIL: 0 - * desc: - * rsa encrypt padding. - * - */ -int hpre_rsa_padding(int flen, const unsigned char *from, unsigned char *buf, - int num, int padding, int type) -{ - int ret = HPRE_CRYPTO_FAIL; - - if (type == PUB_ENC) { - return hpre_pubenc_padding(flen, from, buf, num, padding); - } else if (type == PRI_ENC) { - return hpre_prienc_padding(flen, from, buf, num, padding); - } - - US_ERR("hpre rsa padding type error."); - return ret; -} - -static int hpre_check_pubdec_padding(unsigned char *to, int num, - const unsigned char *buf, int len, int padding) -{ - int ret = HPRE_CRYPTO_FAIL; - - switch (padding) { - case RSA_PKCS1_PADDING: - ret = RSA_padding_check_PKCS1_type_1(to, num, buf, len, num); - break; - case RSA_X931_PADDING: - ret = RSA_padding_check_X931(to, num, buf, len, num); - break; - case RSA_NO_PADDING: - kae_memcpy(to, buf, len); - ret = len; - break; - default: - KAEerr(KAE_F_CHECK_HPRE_PUBDEC_PADDING, KAE_R_UNKNOW_PADDING_TYPE); - US_ERR("RSA UNKNOWN PADDING TYPE!"); - ret = HPRE_CRYPTO_FAIL; - } - - if (ret == -1) { - US_ERR("FAIL ret = %d.", ret); - ret = HPRE_CRYPTO_FAIL; - } - return ret; -} - -static int hpre_check_pridec_padding(unsigned char *to, int num, - const unsigned char *buf, int len, int padding) -{ - int ret = HPRE_CRYPTO_FAIL; - switch (padding) { - case RSA_PKCS1_PADDING: - ret = RSA_padding_check_PKCS1_type_2(to, num, buf, len, num); - break; - case RSA_PKCS1_OAEP_PADDING: - ret = RSA_padding_check_PKCS1_OAEP(to, num, buf, len, num, - NULL, 0); - break; - case RSA_SSLV23_PADDING: - ret = RSA_padding_check_SSLv23(to, num, buf, len, num); - break; - case RSA_NO_PADDING: - kae_memcpy(to, buf, len); - ret = len; - break; - default: - KAEerr(KAE_F_CHECK_HPRE_PRIDEC_PADDING, KAE_R_UNKNOW_PADDING_TYPE); - US_ERR("RSA UNKNOWN PADDING TYPE!"); - ret = HPRE_CRYPTO_FAIL; - } - - if (ret == -1) { - US_ERR("FAIL ret = %d.", ret); - ret = HPRE_CRYPTO_FAIL; - } - return ret; -} - -/** - * func: - * - * @param len [IN] - size in bytes of output - * @param to [IN] - pointer to the output - * @param buf [OUT] - pointer to output data - * @param num [IN] - pointer to public key structure - * @param padding [IN] - Padding scheme - * @param type [IN] - Padding type - * @return - * SUCCESS: 1 - * FAIL: 0 - * desc: - * rsa decrypt padding. - * - */ -int check_rsa_padding(unsigned char *to, int num, - const unsigned char *buf, int len, int padding, int type) -{ - int ret = HPRE_CRYPTO_FAIL; - - if (type == PUB_DEC) { - return hpre_check_pubdec_padding(to, num, buf, len, padding); - } else if (type == PRI_DEC) { - return hpre_check_pridec_padding(to, num, buf, len, padding); - } - - US_ERR("hpre rsa padding type error."); - return ret; -} - -static int check_primeequal(int i, BIGNUM *rsa_p, BIGNUM *rsa_q, BIGNUM *prime) -{ - int j; - - for (j = 0; j < i; j++) { - BIGNUM *prev_prime = NULL; - - if (j == 0) { - prev_prime = rsa_p; - } else { - prev_prime = rsa_q; - } - - if (!BN_cmp(prime, prev_prime)) { - return KAE_FAIL; - } - } - return KAE_SUCCESS; -} - -static int prime_mul_res(int i, BIGNUM *rsa_p, BIGNUM *rsa_q, BIGNUM *r1, BN_CTX *ctx, BN_GENCB *cb) -{ - if (i == 1) { - /* we get at least 2 primes */ - if (!BN_mul(r1, rsa_p, rsa_q, ctx)) { - goto err; - } - } else { - /* i == 0, do nothing */ - if (!BN_GENCB_call(cb, 3, i)) { // When a random p has been found, call BN_GENCB_call(cb, 3, *i) - goto err; - } - goto cont; - } - return KAE_SUCCESS; -err: - return -1; -cont: - return 1; -} -static int check_prime_sufficient(int *i, int *bitsr, int *bitse, int *n, BIGNUM *rsa_p, BIGNUM *rsa_q, - BIGNUM *r1, BIGNUM *r2, BN_CTX *ctx, BN_GENCB *cb) -{ - BN_ULONG bitst; - static int retries = 0; - - /* calculate n immediately to see if it's sufficient */ - int ret = prime_mul_res(*i, rsa_p, rsa_q, r1, ctx, cb); - if (ret != KAE_SUCCESS) { - return ret; - } - if (!BN_rshift(r2, r1, *bitse - 4)) { // right shift *bitse - 4 - goto err; - } - bitst = BN_get_word(r2); - if (bitst < 0x9 || bitst > 0xF) { - *bitse -= bitsr[*i]; - if (!BN_GENCB_call(cb, 2, *n++)) { // When the n-th is rejected, call BN_GENCB_call(cb, 2, n) - goto err; - } - if (retries == 4) { // retries max is 4 - *i = -1; - *bitse = 0; - retries = 0; - goto cont; - } - retries++; - goto redo; - } - - if (!BN_GENCB_call(cb, 3, *i)) { // When a random p has been found, call BN_GENCB_call(cb, 3, *i) - goto err; - } - retries = 0; - return 0; -err: - return -1; -redo: - return -2; // if redo return -2 -cont: - return 1; -} -static void set_primes(int i, BIGNUM *rsa_p, BIGNUM *rsa_q, BIGNUM **prime) -{ - if (i == 0) { - *prime = rsa_p; - } else { - *prime = rsa_q; - } - BN_set_flags(*prime, BN_FLG_CONSTTIME); -} -static int check_prime_useful(int *n, BIGNUM *prime, BIGNUM *r1, BIGNUM *r2, - BIGNUM *e_value, BN_CTX *ctx, BN_GENCB *cb) -{ - if (!BN_sub(r2, prime, BN_value_one())) { - goto err; - } - ERR_set_mark(); - BN_set_flags(r2, BN_FLG_CONSTTIME); - if (BN_mod_inverse(r1, r2, e_value, ctx) != NULL) { - goto br; - } - unsigned long error = ERR_peek_last_error(); - if (ERR_GET_LIB(error) == ERR_LIB_BN - && ERR_GET_REASON(error) == BN_R_NO_INVERSE) { - ERR_pop_to_mark(); - } else { - goto err; - } - if (!BN_GENCB_call(cb, 2, *n++)) { // When the n-th is rejected, call BN_GENCB_call(cb, 2, n) - goto err; - } - return 0; -err: - return -1; -br: - return 1; -} -static void switch_p_q(BIGNUM *rsa_p, BIGNUM *rsa_q, BIGNUM *p, BIGNUM *q) -{ - BIGNUM *tmp = (BIGNUM *)NULL; - - if (BN_cmp(rsa_p, rsa_q) < 0) { - tmp = rsa_p; - rsa_p = rsa_q; - rsa_q = tmp; - } - BN_copy(q, rsa_q); - BN_copy(p, rsa_p); -} -static int hpre_get_prime_once(int i, const int *bitsr, int *n, BIGNUM *prime, BIGNUM *rsa_p, BIGNUM *rsa_q, - BIGNUM *r1, BIGNUM *r2, BIGNUM *e_value, BN_CTX *ctx, BN_GENCB *cb) -{ - int adj = 0; - int ret = KAE_FAIL; - - for (;;) { -redo: - if (!BN_generate_prime_ex(prime, bitsr[i] + adj, 0, (const BIGNUM *)NULL, (const BIGNUM *)NULL, cb)) { - goto err; - } - /* - * prime should not be equal to p, q, r_3... - * (those primes prior to this one) - */ - if (check_primeequal(i, rsa_p, rsa_q, prime) == KAE_FAIL) { - goto redo; - } - - ret = check_prime_useful(n, prime, r1, r2, e_value, ctx, cb); - if (ret == KAE_FAIL) { - goto err; - } else if (ret == 1) { - break; - } - } - return ret; -err: - return KAE_FAIL; -} - -int hpre_rsa_primegen(int bits, BIGNUM *e_value, BIGNUM *p, BIGNUM *q, BN_GENCB *cb) -{ - int ok = -1; - int primes = 2; - int n = 0; - int bitse = 0; - int i = 0; - int bitsr[2]; // 2 bits - BN_CTX *ctx = (BN_CTX *)NULL; - BIGNUM *r1 = (BIGNUM *)NULL; - BIGNUM *r2 = (BIGNUM *)NULL; - BIGNUM *prime = (BIGNUM *)NULL; - BIGNUM *rsa_p, *rsa_q; - - ctx = BN_CTX_new(); - if (ctx == NULL) { - goto err; - } - BN_CTX_start(ctx); - r1 = BN_CTX_get(ctx); - r2 = BN_CTX_get(ctx); - rsa_p = BN_CTX_get(ctx); - rsa_q = BN_CTX_get(ctx); - if (rsa_q == NULL) { - goto err; - } - /* divide bits into 'primes' pieces evenly */ - int quo = bits / primes; - bitsr[0] = quo; - bitsr[1] = quo; - /* generate p, q and other primes (if any) */ - for (i = 0; i < primes; i++) { - set_primes(i, rsa_p, rsa_q, &prime); -redo: - if (hpre_get_prime_once(i, bitsr, &n, prime, rsa_p, rsa_q, r1, r2, e_value, ctx, cb) == KAE_FAIL) { - goto err; - } - - bitse += bitsr[i]; - int ret = check_prime_sufficient(&i, bitsr, &bitse, &n, rsa_p, rsa_q, r1, r2, ctx, cb); - if (ret == -1) { - goto err; - } else if (ret == -2) { // ret = -2 goto redo - goto redo; - } else if (ret == 1) { - continue; - } - } - switch_p_q(rsa_p, rsa_q, p, q); - ok = 1; - err: - if (ok == -1) { - KAEerr(KAE_F_HPRE_RSA_PRIMEGEN, KAE_R_ERR_LIB_BN); - US_ERR("rsa prime gen failed"); - ok = 0; - } - hpre_free_bn_ctx_buf(ctx, NULL, 0); - return ok; -} - -int hpre_rsa_iscrt(RSA *rsa) -{ - if (unlikely(rsa == NULL)) { - return 0; - } - - if (RSA_test_flags(rsa, RSA_FLAG_EXT_PKEY)) { - return 1; - } - - int version = RSA_get_version(rsa); - if (version == RSA_ASN1_VERSION_MULTI) { - return 1; - } - - const BIGNUM *p = NULL; - const BIGNUM *q = NULL; - const BIGNUM *dmp1 = NULL; - const BIGNUM *dmq1 = NULL; - const BIGNUM *iqmp = NULL; - RSA_get0_factors(rsa, &p, &q); - RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp); - if ((p != NULL) && (q != NULL) && (dmp1 != NULL) && (dmq1 != NULL) && (iqmp != NULL)) { - return 1; - } - - return 0; -} \ No newline at end of file diff --git a/alg/pkey/hpre_rsa_utils.h b/alg/pkey/hpre_rsa_utils.h deleted file mode 100644 index 843fcd4..0000000 --- a/alg/pkey/hpre_rsa_utils.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the rsa interface for KAE engine utils dealing - * - * 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_RSA_UTILS_H -#define HPRE_RSA_UTILS_H - -BN_ULONG *bn_get_words(const BIGNUM *a); - -void hpre_free_bn_ctx_buf(BN_CTX *bn_ctx, unsigned char *in_buf, int num); - -int hpre_rsa_check_para(int flen, const unsigned char *from, - unsigned char *to, RSA *rsa); - -int hpre_get_prienc_res(int padding, BIGNUM *f, const BIGNUM *n, BIGNUM *bn_ret, BIGNUM **res); - -int check_bit_useful(const int bit); - -int check_pubkey_param(const BIGNUM *n, const BIGNUM *e); - -int hpre_rsa_padding(int flen, const unsigned char *from, unsigned char *buf, - int num, int padding, int type); - -int check_rsa_padding(unsigned char *to, int num, - const unsigned char *buf, int len, int padding, int type); - -int hpre_rsa_primegen(int bits, BIGNUM *e_value, BIGNUM *p, BIGNUM *q, BN_GENCB *cb); - -int hpre_rsa_iscrt(RSA *rsa); - -#endif diff --git a/alg/pkey/hpre_wd.c b/alg/pkey/hpre_wd.c deleted file mode 100644 index e5e43ac..0000000 --- a/alg/pkey/hpre_wd.c +++ /dev/null @@ -1,464 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the implemenation for KAE rsa using wd interface - * - * 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 -#include - -#include "hpre_wd.h" -#include "wd_rsa.h" -#include "async_callback.h" -#include "async_task_queue.h" -#include "async_event.h" -#include "wd_queue_memory.h" -#include "engine_types.h" -#include "hpre_rsa_utils.h" -#include "utils/engine_check.h" - -static void hpre_rsa_cb(const void *message, void *tag); - -KAE_QUEUE_POOL_HEAD_S *g_hpre_rsa_qnode_pool = NULL; - -void wd_hpre_uninit_qnode_pool(void) -{ - kae_queue_pool_destroy(g_hpre_rsa_qnode_pool, NULL); - g_hpre_rsa_qnode_pool = NULL; -} - -int wd_hpre_init_qnode_pool(void) -{ - kae_queue_pool_destroy(g_hpre_rsa_qnode_pool, NULL); - - g_hpre_rsa_qnode_pool = kae_init_queue_pool(WCRYPTO_RSA); - if (g_hpre_rsa_qnode_pool == NULL) { - US_ERR("hpre rsa qnode poll init fail!\n"); - return KAE_FAIL; - } - - return KAE_SUCCESS; -} - -KAE_QUEUE_POOL_HEAD_S *wd_hpre_get_qnode_pool() -{ - return g_hpre_rsa_qnode_pool; -} - -static hpre_engine_ctx_t *hpre_new_eng_ctx(RSA *rsa_alg) -{ - hpre_engine_ctx_t *eng_ctx = NULL; - eng_ctx = (hpre_engine_ctx_t *)OPENSSL_malloc(sizeof(hpre_engine_ctx_t)); - if (eng_ctx == NULL) { - US_ERR("hpre engine_ctx malloc fail"); - return NULL; - } - kae_memset(eng_ctx, 0, sizeof(hpre_engine_ctx_t)); - - eng_ctx->priv_ctx.ssl_alg = rsa_alg; - eng_ctx->qlist = kae_get_node_from_pool(g_hpre_rsa_qnode_pool); - if (eng_ctx->qlist == NULL) { - US_ERR_LIMIT("error. get hardware queue failed"); - OPENSSL_free(eng_ctx); - eng_ctx = NULL; - return NULL; - } - eng_ctx->priv_ctx.is_privkey_ready = UNSET; - eng_ctx->priv_ctx.is_pubkey_ready = UNSET; - return eng_ctx; -} - -static int hpre_init_eng_ctx(hpre_engine_ctx_t *eng_ctx, int bits) -{ - struct wd_queue *q = eng_ctx->qlist->kae_wd_queue; - struct wd_queue_mempool *pool = eng_ctx->qlist->kae_queue_mem_pool; - - // this is for ctx is in use.we dont need to re create ctx->ctx again - if (eng_ctx->ctx && eng_ctx->opdata.in) { - kae_memset(eng_ctx->opdata.in, 0, eng_ctx->opdata.in_bytes); - return OPENSSL_SUCCESS; - } - if (eng_ctx->ctx == NULL) { - if (bits == 0) { - eng_ctx->priv_ctx.key_size = RSA_size(eng_ctx->priv_ctx.ssl_alg); - } else { - eng_ctx->priv_ctx.key_size = bits >> BIT_BYTES_SHIFT; - } - eng_ctx->rsa_setup.key_bits = eng_ctx->priv_ctx.key_size << BIT_BYTES_SHIFT; - - eng_ctx->rsa_setup.is_crt = ISSET; - - eng_ctx->rsa_setup.cb = (wcrypto_cb)hpre_rsa_cb; - eng_ctx->rsa_setup.br.alloc = kae_wd_alloc_blk; - eng_ctx->rsa_setup.br.free = kae_wd_free_blk; - eng_ctx->rsa_setup.br.iova_map = kae_dma_map; - eng_ctx->rsa_setup.br.iova_unmap = kae_dma_unmap; - eng_ctx->rsa_setup.br.usr = pool; - eng_ctx->ctx = wcrypto_create_rsa_ctx(q, &eng_ctx->rsa_setup); - if (eng_ctx->ctx == NULL) { - US_ERR("create rsa ctx fail!"); - return OPENSSL_FAIL; - } - } - - return OPENSSL_SUCCESS; -} - -hpre_engine_ctx_t *hpre_get_eng_ctx(RSA *rsa, int bits) -{ - hpre_engine_ctx_t *eng_ctx = hpre_new_eng_ctx(rsa); - if (eng_ctx == NULL) { - US_WARN("new eng ctx fail then switch to soft!"); - return NULL; - } - - if (hpre_init_eng_ctx(eng_ctx, bits) == 0) { - hpre_free_eng_ctx(eng_ctx); - US_WARN("init eng ctx fail then switch to soft!"); - return NULL; - } - return eng_ctx; -} - -void hpre_free_eng_ctx(hpre_engine_ctx_t *eng_ctx) -{ - US_DEBUG("hpre rsa free engine ctx start!"); - if (eng_ctx == NULL) { - US_DEBUG("no eng_ctx to free"); - return; - } - - if (eng_ctx->opdata.op_type != WCRYPTO_RSA_GENKEY) { - if (eng_ctx->opdata.in) { - eng_ctx->rsa_setup.br.free(eng_ctx->qlist->kae_queue_mem_pool, eng_ctx->opdata.in); - } - if (eng_ctx->opdata.out) { - if (eng_ctx->qlist != NULL) { - eng_ctx->rsa_setup.br.free(eng_ctx->qlist->kae_queue_mem_pool, eng_ctx->opdata.out); - } - } - } else { - if (eng_ctx->opdata.in) { - wcrypto_del_kg_in(eng_ctx->ctx, (struct wcrypto_rsa_kg_in *)eng_ctx->opdata.in); - } - if (eng_ctx->opdata.out) { - wcrypto_del_kg_out(eng_ctx->ctx, (struct wcrypto_rsa_kg_out *)eng_ctx->opdata.out); - } - } - - if (eng_ctx->qlist != NULL) { - hpre_free_rsa_ctx(eng_ctx->ctx); - kae_put_node_to_pool(g_hpre_rsa_qnode_pool, eng_ctx->qlist); - } - - eng_ctx->priv_ctx.ssl_alg = NULL; - eng_ctx->qlist = NULL; - eng_ctx->ctx = NULL; - eng_ctx->opdata.in = NULL; - eng_ctx->opdata.out = NULL; - eng_ctx->priv_ctx.is_privkey_ready = UNSET; - eng_ctx->priv_ctx.is_pubkey_ready = UNSET; - OPENSSL_free(eng_ctx); - eng_ctx = NULL; - - return; -} - -void hpre_free_rsa_ctx(void *ctx) -{ - if (ctx != NULL) { - wcrypto_del_rsa_ctx(ctx); - ctx = NULL; - } -} - -void hpre_rsa_fill_pubkey(const BIGNUM *e, const BIGNUM *n, hpre_engine_ctx_t *eng_ctx) -{ - struct wcrypto_rsa_pubkey *pubkey = NULL; - struct wd_dtb *wd_e = NULL; - struct wd_dtb *wd_n = NULL; - - wcrypto_get_rsa_pubkey(eng_ctx->ctx, &pubkey); - wcrypto_get_rsa_pubkey_params(pubkey, &wd_e, &wd_n); - if (!eng_ctx->priv_ctx.is_pubkey_ready) { - wd_e->dsize = BN_bn2bin(e, (unsigned char *)wd_e->data); - wd_n->dsize = BN_bn2bin(n, (unsigned char *)wd_n->data); - eng_ctx->priv_ctx.is_pubkey_ready = ISSET; - } - return; -} - -/** - * FILL prikey to rsa_ctx in normal mode - * @param rsa get prikey from rsa - * @param rsa_ctx - */ -static void hpre_rsa_fill_prikey1(RSA *rsa, hpre_engine_ctx_t *eng_ctx) -{ - struct wcrypto_rsa_prikey *prikey = NULL; - struct wd_dtb *wd_d = NULL; - struct wd_dtb *wd_n = NULL; - const BIGNUM *n = (const BIGNUM *)NULL; - const BIGNUM *e = (const BIGNUM *)NULL; - const BIGNUM *d = (const BIGNUM *)NULL; - - RSA_get0_key(rsa, &n, &e, &d); - wcrypto_get_rsa_prikey(eng_ctx->ctx, &prikey); - wcrypto_get_rsa_prikey_params(prikey, &wd_d, &wd_n); - - if (!eng_ctx->priv_ctx.is_privkey_ready) { - wd_d->dsize = BN_bn2bin(d, (unsigned char *)wd_d->data); - wd_n->dsize = BN_bn2bin(n, (unsigned char *)wd_n->data); - eng_ctx->priv_ctx.is_privkey_ready = ISSET; - } - return ; -} - -/** - * FILL prikey to rsa_ctx in crt mode - * @param rsa get prikey from rsa - * @param rsa_ctx - */ -static void hpre_rsa_fill_prikey2(RSA *rsa, hpre_engine_ctx_t *eng_ctx) -{ - struct wcrypto_rsa_prikey *prikey = NULL; - struct wd_dtb *wd_dq, *wd_dp, *wd_q, *wd_p, *wd_qinv; - const BIGNUM *p = NULL; - const BIGNUM *q = NULL; - const BIGNUM *dmp1 = NULL; - const BIGNUM *dmq1 = NULL; - const BIGNUM *iqmp = NULL; - - RSA_get0_factors(rsa, &p, &q); - RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp); - wcrypto_get_rsa_prikey(eng_ctx->ctx, &prikey); - wcrypto_get_rsa_crt_prikey_params(prikey, &wd_dq, &wd_dp, &wd_qinv, &wd_q, &wd_p); - if (!eng_ctx->priv_ctx.is_privkey_ready) { - wd_dq->dsize = BN_bn2bin(dmq1, (unsigned char *)wd_dq->data); - wd_dp->dsize = BN_bn2bin(dmp1, (unsigned char *)wd_dp->data); - wd_q->dsize = BN_bn2bin(q, (unsigned char *)wd_q->data); - wd_p->dsize = BN_bn2bin(p, (unsigned char *)wd_p->data); - wd_qinv->dsize = BN_bn2bin(iqmp, (unsigned char *)wd_qinv->data); - eng_ctx->priv_ctx.is_privkey_ready = ISSET; - } - return ; -} - -void hpre_rsa_fill_prikey(RSA *rsa, hpre_engine_ctx_t *eng_ctx, int version, const BIGNUM *p, const BIGNUM *q, - const BIGNUM *dmp1, const BIGNUM *dmq1, const BIGNUM *iqmp) -{ - if (hpre_rsa_iscrt(rsa)) { - hpre_rsa_fill_prikey2(rsa, eng_ctx); - } else { - hpre_rsa_fill_prikey1(rsa, eng_ctx); - } -} - -int hpre_fill_keygen_opdata(void *ctx, - struct wcrypto_rsa_op_data *opdata) -{ - struct wd_dtb *wd_e = NULL; - struct wd_dtb *wd_p = NULL; - struct wd_dtb *wd_q = NULL; - struct wcrypto_rsa_pubkey *pubkey = NULL; - struct wcrypto_rsa_prikey *prikey = NULL; - - wcrypto_get_rsa_pubkey(ctx, &pubkey); - wcrypto_get_rsa_pubkey_params(pubkey, &wd_e, NULL); - wcrypto_get_rsa_prikey(ctx, &prikey); - wcrypto_get_rsa_crt_prikey_params(prikey, NULL, NULL, NULL, &wd_q, &wd_p); - opdata->in = wcrypto_new_kg_in(ctx, wd_e, wd_p, wd_q); - if (!opdata->in) { - US_ERR("create rsa kgen in fail!\n"); - return -ENOMEM; - } - opdata->out = wcrypto_new_kg_out(ctx); - if (!opdata->out) { - wcrypto_del_kg_in(ctx, (struct wcrypto_rsa_kg_in *)opdata->in); - US_ERR("create rsa kgen out fail\n"); - return -ENOMEM; - } - - return 0; -} - -int hpre_rsa_get_keygen_param(struct wcrypto_rsa_op_data *opdata, void *ctx, - RSA *rsa, BIGNUM *e_value, BIGNUM *p, BIGNUM *q) -{ - BIGNUM *n = BN_new(); - BIGNUM *d = BN_new(); - BIGNUM *dmp1 = BN_new(); - BIGNUM *dmq1 = BN_new(); - BIGNUM *iqmp = BN_new(); - struct wd_dtb wd_d; - struct wd_dtb wd_n; - struct wd_dtb wd_qinv; - struct wd_dtb wd_dq; - struct wd_dtb wd_dp; - unsigned int key_bits, key_size; - struct wcrypto_rsa_kg_out *out = (struct wcrypto_rsa_kg_out *)opdata->out; - - key_bits = wcrypto_rsa_key_bits(ctx); - key_size = key_bits >> BIT_BYTES_SHIFT; - wcrypto_get_rsa_kg_out_params(out, &wd_d, &wd_n); - wcrypto_get_rsa_kg_out_crt_params(out, &wd_qinv, &wd_dq, &wd_dp); - - BN_bin2bn((unsigned char *)wd_d.data, key_size, d); - BN_bin2bn((unsigned char *)wd_n.data, key_size, n); - BN_bin2bn((unsigned char *)wd_qinv.data, wd_qinv.dsize, iqmp); - BN_bin2bn((unsigned char *)wd_dq.data, wd_dq.dsize, dmq1); - BN_bin2bn((unsigned char *)wd_dp.data, wd_dp.dsize, dmp1); - - if (!(RSA_set0_key(rsa, n, e_value, d) && RSA_set0_factors(rsa, p, q) && - RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp))) { - KAEerr(KAE_F_RSA_FILL_KENGEN_PARAM, KAE_R_RSA_KEY_NOT_COMPELET); - US_ERR("set key failed!"); - return OPENSSL_FAIL; - } else { - return OPENSSL_SUCCESS; - } -} - -static void hpre_rsa_cb(const void *message, void *tag) -{ - if (!message || !tag) { - US_ERR("hpre cb params err!\n"); - return; - } - struct wcrypto_rsa_msg *msg = (struct wcrypto_rsa_msg *)message; - hpre_engine_ctx_t *eng_ctx = (hpre_engine_ctx_t *)tag; - eng_ctx->opdata.out = msg->out; - eng_ctx->opdata.out_bytes = msg->out_bytes; - eng_ctx->opdata.status = msg->result; -} - -int hpre_rsa_sync(void *ctx, struct wcrypto_rsa_op_data *opdata) -{ - void *tag = NULL; - - if (!ctx || !opdata) { - US_ERR("sync params err!"); - return HPRE_CRYPTO_FAIL; - } - - int ret = wcrypto_do_rsa(ctx, opdata, tag); - if (ret != WD_SUCCESS) { - US_ERR("hpre do rsa fail!"); - return HPRE_CRYPTO_FAIL; - } else { - US_DEBUG("hpre do rsa success!"); - return HPRE_CRYPTO_SUCC; - } -} - -int hpre_rsa_async(hpre_engine_ctx_t *eng_ctx, - struct wcrypto_rsa_op_data *opdata, op_done_t *op_done) -{ - int ret = 0; - int cnt = 0; - enum task_type type = ASYNC_TASK_RSA; - void *tag = eng_ctx; - do { - if (cnt > MAX_SEND_TRY_CNTS) { - break; - } - ret = wcrypto_do_rsa(eng_ctx->ctx, opdata, tag); - if (ret == WD_STATUS_BUSY) { - if ((async_wake_job(op_done->job, ASYNC_STATUS_EAGAIN) == 0 || - (async_pause_job(op_done->job, ASYNC_STATUS_EAGAIN) == 0))) { - US_ERR("hpre wake job or hpre pause job fail!"); - ret = 0; - break; - } - cnt++; - } - } while (ret == WD_STATUS_BUSY); - - if (ret != WD_SUCCESS) { - return HPRE_CRYPTO_FAIL; - } - - if (async_add_poll_task(eng_ctx, op_done, type) == 0) { - return HPRE_CRYPTO_FAIL; - } - - return HPRE_CRYPTO_SUCC; -} - -int hpre_rsa_crypto(hpre_engine_ctx_t *eng_ctx, struct wcrypto_rsa_op_data *opdata) -{ - int job_ret; - op_done_t op_done; - - async_init_op_done(&op_done); - - if (op_done.job != NULL && kae_is_async_enabled()) { - if (async_setup_async_event_notification(0) == 0) { - US_ERR("hpre async event notifying failed"); - async_cleanup_op_done(&op_done); - return HPRE_CRYPTO_FAIL; - } - } else { - US_DEBUG("hpre rsa no async Job or async disable, back to sync!"); - async_cleanup_op_done(&op_done); - return hpre_rsa_sync(eng_ctx->ctx, opdata); - } - - if (hpre_rsa_async(eng_ctx, opdata, &op_done) == HPRE_CRYPTO_FAIL) - goto err; - - do { - job_ret = async_pause_job(op_done.job, ASYNC_STATUS_OK); - if (job_ret == 0) { - US_DEBUG("- pthread_yidle -"); - kae_pthread_yield(); - } - } - - while (!op_done.flag || - ASYNC_CHK_JOB_RESUMED_UNEXPECTEDLY(job_ret)); - - if (op_done.verifyRst <= 0) { - US_ERR("hpre rsa verify result failed with %d", op_done.verifyRst); - async_cleanup_op_done(&op_done); - return HPRE_CRYPTO_FAIL; - } - - async_cleanup_op_done(&op_done); - - US_DEBUG("hpre rsa do async job success!"); - return HPRE_CRYPTO_SUCC; - -err: - US_ERR("hpre rsa do async job err"); - (void)async_clear_async_event_notification(); - async_cleanup_op_done(&op_done); - return HPRE_CRYPTO_FAIL; -} - diff --git a/alg/pkey/hpre_wd.h b/alg/pkey/hpre_wd.h deleted file mode 100644 index 0c7139e..0000000 --- a/alg/pkey/hpre_wd.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the rsa interface for KAE rsa using wd interface - * - * 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_WD_H -#define HPRE_WD_H - -#include - -#include "hpre_rsa.h" -#include "wd_rsa.h" -#include "../wdmngr/wd_queue_memory.h" -#include "wd_rsa.h" - - -#define UNSET 0 -#define ISSET 1 -#define BIT_BYTES_SHIFT 3 - -#define BN_ULONG unsigned long -#define MAX_SEND_TRY_CNTS 50 -#define MAX_RECV_TRY_CNTS 3000 - -#define RSA_BALANCE_TIMES 1280 - -#define WD_STATUS_BUSY (-EBUSY) - -struct hpre_priv_ctx { - RSA *ssl_alg; - int is_pubkey_ready; - int is_privkey_ready; - int key_size; -}; - -typedef struct hpre_priv_ctx hpre_priv_ctx_t; - -struct hpre_engine_ctx { - void *ctx; - struct wcrypto_rsa_op_data opdata; - struct wcrypto_rsa_ctx_setup rsa_setup; - struct KAE_QUEUE_DATA_NODE *qlist; - hpre_priv_ctx_t priv_ctx; -}; - -typedef struct hpre_engine_ctx hpre_engine_ctx_t; - -extern KAE_QUEUE_POOL_HEAD_S *g_hpre_rsa_qnode_pool; - -int wd_hpre_init_qnode_pool(void); -void wd_hpre_uninit_qnode_pool(void); - -KAE_QUEUE_POOL_HEAD_S *wd_hpre_get_qnode_pool(); - -hpre_engine_ctx_t *hpre_get_eng_ctx(RSA *rsa, int bits); - -void hpre_free_eng_ctx(hpre_engine_ctx_t *eng_ctx); - -void hpre_free_rsa_ctx(void *ctx); - -void hpre_rsa_fill_pubkey(const BIGNUM *e, const BIGNUM *n, hpre_engine_ctx_t *rsa_ctx); - -void hpre_rsa_fill_prikey(RSA *rsa, hpre_engine_ctx_t *eng_ctx, int version, - const BIGNUM *p, const BIGNUM *q, const BIGNUM *dmp1, - const BIGNUM *dmq1, const BIGNUM *iqmp); - -int hpre_fill_keygen_opdata(void *ctx, - struct wcrypto_rsa_op_data *opdata); - -int hpre_rsa_get_keygen_param(struct wcrypto_rsa_op_data *opdata, void *ctx, - RSA *rsa, BIGNUM *e_value, BIGNUM *p, BIGNUM *q); - -int hpre_rsa_sync(void *ctx, struct wcrypto_rsa_op_data *opdata); - -int hpre_rsa_crypto(hpre_engine_ctx_t *eng_ctx, struct wcrypto_rsa_op_data *opdata); - -#endif - diff --git a/async/async_callback.c b/async/async_callback.c deleted file mode 100644 index 528a8f8..0000000 --- a/async/async_callback.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides implementation for callback in KAE engine - * - * 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 _GNU_SOURCE -# define _GNU_SOURCE -#endif - -#ifndef __USE_GNU -# define __USE_GNU -#endif - -#include -#include -#include -#include - -#include "async_callback.h" -#include "engine_log.h" - -#include - -void async_init_op_done(op_done_t *op_done) -{ - if ((op_done == NULL)) { - US_ERR("error! paramater is NULL."); - return ; - } - - op_done->flag = 0; - op_done->verifyRst = 0; - op_done->job = ASYNC_get_current_job(); -} - -void async_cleanup_op_done(op_done_t *op_done) -{ - if ((op_done == NULL)) { - US_ERR("error! paramater is NULL."); - return; - } - - op_done->verifyRst = 0; - - if (op_done->job) { - op_done->job = NULL; - } - - return; -} -/*lint -e(10)*/ - diff --git a/async/async_callback.h b/async/async_callback.h deleted file mode 100644 index 030b1cd..0000000 --- a/async/async_callback.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides interface for callback in KAE engine - * - * 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 ASYNC_CALLBACK_H -#define ASYNC_CALLBACK_H - -#include - -#include - - -typedef struct { - volatile int flag; - volatile int verifyRst; - volatile ASYNC_JOB *job; -} op_done_t; - -void async_init_op_done(op_done_t *op_done); - -void async_cleanup_op_done(op_done_t *op_done); - -#endif - diff --git a/async/async_event.c b/async/async_event.c deleted file mode 100644 index 1fdd509..0000000 --- a/async/async_event.c +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides implementation for async events in KAE engine - * - * 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 _GNU_SOURCE -# define _GNU_SOURCE -#endif - -#ifndef _USE_GNU -# define _USE_GNU -#endif - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "async_event.h" -#include "engine_kae.h" - -static void async_fd_cleanup(ASYNC_WAIT_CTX *ctx, const void *key, OSSL_ASYNC_FD readfd, void *custom) -{ - (void)ctx; - (void)key; - (void)custom; - if (close(readfd) != 0) { - US_WARN("Failed to close fd: %d - error: %d\n", readfd, errno); - } -} - -int async_setup_async_event_notification(int jobStatus) -{ - (void)jobStatus; - ASYNC_JOB *job; - ASYNC_WAIT_CTX *waitctx; - OSSL_ASYNC_FD efd; - void *custom = NULL; - - job = ASYNC_get_current_job(); - if (job == NULL) { - US_ERR("Could not obtain current async job\n"); - return 0; - } - - waitctx = ASYNC_get_wait_ctx(job); - if (waitctx == NULL) { - US_ERR("current job has no waitctx."); - return 0; - } - - if (ASYNC_WAIT_CTX_get_fd(waitctx, g_engine_kae_id, &efd, - &custom) == 0) { - efd = eventfd(0, EFD_NONBLOCK); - if (efd == -1) { - US_ERR("efd error."); - return 0; - } - - if (ASYNC_WAIT_CTX_set_wait_fd(waitctx, g_engine_kae_id, efd, - custom, async_fd_cleanup) == 0) { - US_ERR("set wait fd error."); - async_fd_cleanup(waitctx, g_engine_kae_id, efd, NULL); - return 0; - } - } - return 1; -} - -int async_clear_async_event_notification() -{ - ASYNC_JOB *job; - ASYNC_WAIT_CTX *waitctx; - OSSL_ASYNC_FD efd; - size_t num_add_fds = 0; - size_t num_del_fds = 0; - void *custom = NULL; - - job = ASYNC_get_current_job(); - if (job == NULL) { - US_ERR("no async job."); - return 0; - } - - waitctx = ASYNC_get_wait_ctx(job); - if (waitctx == NULL) { - US_ERR("The job has no waitctx"); - return 0; - } - - if (ASYNC_WAIT_CTX_get_changed_fds(waitctx, NULL, &num_add_fds, NULL, &num_del_fds) == 0) { - US_ERR("no add fds."); - return 0; - } - - if (num_add_fds > 0) { - if (ASYNC_WAIT_CTX_get_fd(waitctx, g_engine_kae_id, &efd, &custom) == 0) { - US_ERR("no fd."); - return 0; - } - - async_fd_cleanup(waitctx, g_engine_kae_id, efd, NULL); - - if (ASYNC_WAIT_CTX_clear_fd(waitctx, g_engine_kae_id) == 0) { - US_ERR("clear fd error."); - return 0; - } - } - - return 1; -} - -int async_pause_job(volatile ASYNC_JOB *job, int jobStatus) -{ - (void)jobStatus; - - ASYNC_WAIT_CTX *waitctx; - OSSL_ASYNC_FD efd; - void *custom = NULL; - uint64_t buf = 0; - int ret = 0; - - waitctx = ASYNC_get_wait_ctx((ASYNC_JOB *)job); - if (waitctx == NULL) { - US_ERR("error. waitctx is NULL\n"); - return ret; - } - - if (ASYNC_pause_job() == 0) { - US_ERR("Failed to pause the job\n"); - return ret; - } - - ret = ASYNC_WAIT_CTX_get_fd(waitctx, g_engine_kae_id, &efd, &custom); - if (ret > 0) { - if (read(efd, &buf, sizeof(uint64_t)) == -1) { - if (errno != EAGAIN) { - US_WARN("Failed to read from fd: %d - error: %d\n", efd, errno); - } - /* Not resumed by the expected async_wake_job() */ - return ASYNC_JOB_RESUMED_UNEXPECTEDLY; - } - } - - return ret; -} - - -int async_wake_job(volatile ASYNC_JOB *job, int jobStatus) -{ - (void)jobStatus; - - ASYNC_WAIT_CTX *waitctx; - OSSL_ASYNC_FD efd; - void *custom = NULL; - uint64_t buf = 1; - int ret = 0; - - waitctx = ASYNC_get_wait_ctx((ASYNC_JOB *)job); - if (waitctx == NULL) { - US_ERR("error. waitctx is NULL\n"); - return ret; - } - - ret = ASYNC_WAIT_CTX_get_fd(waitctx, g_engine_kae_id, &efd, &custom); - if (ret > 0) { - if (write(efd, &buf, sizeof(uint64_t)) == -1) { - US_ERR("Failed to write to fd: %d - error: %d\n", efd, errno); - } - } - - US_DEBUG("- async wake job success - "); - return ret; -} -/*lint -e(10)*/ - diff --git a/async/async_event.h b/async/async_event.h deleted file mode 100644 index 5f42449..0000000 --- a/async/async_event.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides interface for async events in KAE engine - * - * 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 __ASYNC_EVENTS_H__ -#define __ASYNC_EVENTS_H__ - -#include - -#include - - -#define ASYNC_JOB_RESUMED_UNEXPECTEDLY (-1) -#define ASYNC_CHK_JOB_RESUMED_UNEXPECTEDLY(x) \ - ((x) == ASYNC_JOB_RESUMED_UNEXPECTEDLY) - -#define ASYNC_STATUS_UNSUPPORTED 0 -#define ASYNC_STATUS_ERR 1 -#define ASYNC_STATUS_OK 2 -#define ASYNC_STATUS_EAGAIN 3 - -int async_setup_async_event_notification(int jobStatus); -int async_clear_async_event_notification(); -int async_pause_job(volatile ASYNC_JOB *job, int jobStatus); -int async_wake_job(volatile ASYNC_JOB *job, int jobStatus); - -#endif - diff --git a/async/async_poll.c b/async/async_poll.c deleted file mode 100644 index 4d5d245..0000000 --- a/async/async_poll.c +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the implemenation for the KAE engine thread polling - * - * 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 _GNU_SOURCE -# define _GNU_SOURCE -#endif - -#ifndef __USE_GNU -# define __USE_GNU -#endif - -#include -#include -#include -#include -#include -#include - -#include "engine_check.h" -#include "async_poll.h" -#include "async_event.h" -#include "async_task_queue.h" -#include "engine_utils.h" - -#include - -#define ASYNC_POLL_TASK_NUM 1024 - -static void async_polling_thread_destroy(); - -static void *async_poll_process_func(void *args) -{ - (void)args; - int ret; - async_poll_task *task; - void *eng_ctx; - int type; - op_done_t *op_done; - - while (1) { - if (sem_wait(&g_async_poll_queue.full_sem) != 0) { - if (errno == EINTR) { - /* sem_wait is interrupted by interrupt, continue */ - continue; - } - US_ERR("wait async full_sem failed, errno:%d", errno); //lint !e666 - } - - task = async_get_queue_task(); - if (task == NULL) { - usleep(1); - continue; - } - - eng_ctx = task->eng_ctx; - op_done = task->op_done; - type = task->type; - - US_DEBUG("async poll thread start to recv result."); - - ret = g_async_recv_func[type](eng_ctx); - - op_done->verifyRst = ret; - - op_done->flag = 1; - if (op_done->job) { - async_wake_job(op_done->job, ASYNC_STATUS_OK); - } - - US_DEBUG("process task done."); - } - - US_DEBUG("polling thread exit."); - return NULL; -} - -void async_polling_thread_reset() -{ - g_async_poll_queue.init_mark = 0; - kae_memset(&g_async_poll_queue, 0, sizeof(g_async_poll_queue)); -} - -int async_polling_thread_init() -{ - US_DEBUG("init polling thread."); - if (g_async_poll_queue.init_mark == INITED) return 1; - - kae_memset(&g_async_poll_queue, 0, sizeof(async_poll_queue_t)); - - if (pthread_mutex_init(&(g_async_poll_queue.async_task_mutex), NULL) < 0) { - US_ERR("init queue mutex failed, errno:%d", errno); //lint !e666 - } - - if (!async_poll_task_init()) { - US_ERR("init poll task queue failed."); - return 0; - } - - pthread_t thread_id; - if (kae_create_thread(&thread_id, NULL, async_poll_process_func, NULL) == 0) { - US_DEBUG("fail to create polling thread"); - goto _err; - } - - g_async_poll_queue.thread_id = thread_id; - g_async_poll_queue.init_mark = INITED; - (void)OPENSSL_atexit(async_polling_thread_destroy); - - return 1; - -_err: - async_poll_task_free(); - return 0; -} - -static void async_polling_thread_destroy() -{ - if (g_async_poll_queue.exit_mark == 1) return; - - async_poll_task_free(); - - g_async_poll_queue.exit_mark = 1; - - return; -} - -void async_module_init() -{ - if (kae_is_async_enabled()) { - async_poll_task_free(); - - async_polling_thread_reset(); - if (!async_polling_thread_init()) { - kae_disable_async(); - } - } -} -/*lint -e(10)*/ - diff --git a/async/async_poll.h b/async/async_poll.h deleted file mode 100644 index f0e3bf0..0000000 --- a/async/async_poll.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides interface for the KAE engine thread polling - * - * 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 ASYNC_POLLING_H -#define ASYNC_POLLING_H -#include -#include "async_callback.h" -#include "async_task_queue.h" - -void async_module_init(); - -#endif - diff --git a/async/async_task_queue.c b/async/async_task_queue.c deleted file mode 100644 index 5ebbf59..0000000 --- a/async/async_task_queue.c +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the implemenation for the KAE engine async task queue - * - * 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 _GNU_SOURCE -# define _GNU_SOURCE -#endif - -#ifndef __USE_GNU -# define __USE_GNU -#endif - -#include -#include -#include -#include -#include -#include -#include - -#include "async_task_queue.h" -#include "engine_utils.h" - -#define ASYNC_POLL_TASK_NUM 4096 - -async_poll_queue_t g_async_poll_queue = { - .init_mark = 0, -}; - -async_recv_t g_async_recv_func[MAX_ALG_SIZE]; - -int async_register_poll_fn(int type, async_recv_t func) -{ - if (type < 0 || type >= MAX_ALG_SIZE) { - return -1; - } - - g_async_recv_func[type] = func; - return 0; -} - -int async_poll_task_init() -{ - kae_memset(&g_async_poll_queue, 0, sizeof(g_async_poll_queue)); - - g_async_poll_queue.async_poll_task_queue_head = - (async_poll_task*)malloc(sizeof(async_poll_task) * ASYNC_POLL_TASK_NUM); - if (g_async_poll_queue.async_poll_task_queue_head == NULL) { - US_ERR("no enough memory for task queue, errno=%d", errno); //lint !e666 - return 0; - } - kae_memset(g_async_poll_queue.async_poll_task_queue_head, 0, - sizeof(async_poll_task) * ASYNC_POLL_TASK_NUM); - g_async_poll_queue.left_task = ASYNC_POLL_TASK_NUM; - - int ret = sem_init(&g_async_poll_queue.empty_sem, 0, (unsigned int)g_async_poll_queue.left_task); - if (ret != 0) { - US_ERR("fail to init empty semaphore, errno=%d", errno); //lint !e666 - goto _err; - } - - if (sem_init(&g_async_poll_queue.full_sem, 0, 0) != 0) { - US_ERR("fail to init full semaphore, errno=%d", errno); //lint !e666 - goto _err; - } - - US_DEBUG("async poll task init done."); - return 1; -_err: - async_poll_task_free(); - return 0; -} - -async_poll_task* async_get_queue_task() -{ - async_poll_task *task_queue; - async_poll_task *cur_task; - int tail_pos; - - if (pthread_mutex_lock(&g_async_poll_queue.async_task_mutex) != 0) { - US_ERR("lock queue mutex failed, errno:%d", errno); //lint !e666 - return NULL; - } - - tail_pos = g_async_poll_queue.tail_pos; - task_queue = g_async_poll_queue.async_poll_task_queue_head; - cur_task = &task_queue[tail_pos]; - - g_async_poll_queue.tail_pos = (tail_pos + 1) % ASYNC_POLL_TASK_NUM; - g_async_poll_queue.cur_task--; - g_async_poll_queue.left_task++; - - if (pthread_mutex_unlock(&g_async_poll_queue.async_task_mutex) != 0) { - US_ERR("unlock queue mutex failed, errno:%d", errno); //lint !e666 - } - - if (sem_post(&g_async_poll_queue.empty_sem) != 0) { - US_ERR("post empty sem failed, errno:%d", errno); //lint !e666 - } - - US_DEBUG("get task end"); - return cur_task; -} - -static int async_add_queue_task(void *eng_ctx, op_done_t *op_done, enum task_type type) -{ - async_poll_task *task_queue; - async_poll_task *task; - int head_pos; - - if (sem_wait(&g_async_poll_queue.empty_sem) != 0) { - US_ERR("wait empty sem failed, errno:%d", errno); //lint !e666 - return 0; - } - - if (pthread_mutex_lock(&g_async_poll_queue.async_task_mutex) != 0) { - US_ERR("lock queue mutex failed, errno:%d", errno); //lint !e666 - } - - head_pos = g_async_poll_queue.head_pos; - task_queue = g_async_poll_queue.async_poll_task_queue_head; - task = &task_queue[head_pos]; - task->eng_ctx = eng_ctx; - task->op_done = op_done; - task->type = type; - - head_pos = (head_pos + 1) % ASYNC_POLL_TASK_NUM; - g_async_poll_queue.head_pos = head_pos; - g_async_poll_queue.cur_task++; - g_async_poll_queue.left_task--; - - if (pthread_mutex_unlock(&g_async_poll_queue.async_task_mutex) != 0) { - US_ERR("unlock queue mutex failed, errno:%d", errno); //lint !e666 - } - - if (sem_post(&g_async_poll_queue.full_sem) != 0) { - US_ERR("post full sem failed, errno:%d", errno); //lint !e666 - } - - US_DEBUG("add task success"); - return 1; -} - -static void async_poll_queue_free() -{ - async_poll_task *task = g_async_poll_queue.async_poll_task_queue_head; - if (task != NULL) { - OPENSSL_free(task); - } - g_async_poll_queue.async_poll_task_queue_head = NULL; -} - -int async_add_poll_task(void *eng_ctx, op_done_t *op_done, enum task_type type) -{ - US_DEBUG("start to add task to poll queue"); - return async_add_queue_task(eng_ctx, op_done, type); -} - -void async_poll_task_free() -{ - int error; - error = pthread_mutex_lock(&g_async_poll_queue.async_task_mutex); - if (error != 0) { - US_ERR("lock mutex failed, errno=%d", errno); //lint !e666 - return ; - } - async_poll_queue_free(); - pthread_mutex_unlock(&g_async_poll_queue.async_task_mutex); - - sem_destroy(&g_async_poll_queue.empty_sem); - sem_destroy(&g_async_poll_queue.full_sem); - pthread_mutex_destroy(&g_async_poll_queue.async_task_mutex); - - US_DEBUG("async task free succ"); - return; -} -/*lint -e(10)*/ - diff --git a/async/async_task_queue.h b/async/async_task_queue.h deleted file mode 100644 index 0bbba31..0000000 --- a/async/async_task_queue.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides interface for the KAE engine async task queue - * - * 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 ASYNC_TASK_QUEUE_H -#define ASYNC_TASK_QUEUE_H -#include -#include "../engine_kae.h" -#include "async_callback.h" -#include "wd.h" - -#include - -#define MAX_ALG_SIZE 6 - -typedef int (*async_recv_t)(void* engine_ctx); - -enum task_type { - ASYNC_TASK_CIPHER, - ASYNC_TASK_DIGEST, - ASYNC_TASK_RSA, - ASYNC_TASK_DH -}; - -struct async_wd_polling_arg { - enum task_type type; - void *eng_ctx; - op_done_t *op_done; -}; -typedef struct async_wd_polling_arg async_poll_task; - -typedef struct async_poll_queue_t { - async_poll_task* async_poll_task_queue_head; - int head_pos; - int tail_pos; - int cur_task; - int left_task; - int shutdown; - sem_t empty_sem; - sem_t full_sem; - pthread_mutex_t async_task_mutex; - pthread_t thread_id; - int init_mark; - int exit_mark; -} async_poll_queue_t; - -extern async_poll_queue_t g_async_poll_queue; -extern async_recv_t g_async_recv_func[MAX_ALG_SIZE]; - -int async_register_poll_fn(int type, async_recv_t async_recv); -int async_poll_task_init(); -async_poll_task* async_get_queue_task(); - -int async_add_poll_task(void *ctx, op_done_t *op_done, enum task_type type); -void async_poll_task_free(); - -#endif - diff --git a/configure b/configure deleted file mode 100755 index 18833ad..0000000 --- a/configure +++ /dev/null @@ -1,92 +0,0 @@ -#! /bin/bash -if [[ $# == 0 ]]; then - openssl_path=/usr/local - wd_path=/usr/local -elif [[ $# == 1 ]]; then - if [[ $1 == --openssl_path=* ]]; then - openssl_path=${1#*=} - wd_path=/usr/local - elif [[ $1 == --wd_path=* ]]; then - openssl_path=/usr/local - wd_path=${1#*=} - else - echo "usage: ./configure [--openssl_path] [--wd_path=]" - exit 1; - fi -elif [[ $# == 2 ]]; then - if [ ${1%%=*} == --openssl_path ] && [ ${2%=*} == --wd_path ]; then - openssl_path=${1#*=} - wd_path=${2##*=} - elif [ ${1%%=*} == --wd_path ] && [ ${2%=*} == --openssl_path ]; then - wd_path=${1#*=} - openssl_path=${2##*=} - else - echo "usage: ./configure [--openssl_path=] [--wd_path=]" - exit 1; - fi -else - echo "Too many options, option numbers less than or equal 2" - exit 1; -fi - -if [ -d $openssl_path ]; then - echo "checking openssl install path... ok" -else - echo "No such file or directory" - exit 1; -fi - -if [ -d $wd_path ]; then - echo "checking wd install path... ok" -else - echo "No such file or directory" - exit 1; -fi - -grep -n "OPENSSL_WORK_PATH" Makefile > /dev/null -if [ $? = 0 ]; then - sed -i "1d" Makefile - sed -i "1i\export OPENSSL_WORK_PATH=$openssl_path" Makefile -else - sed -i "1i\export OPENSSL_WORK_PATH=$openssl_path" Makefile -fi -grep -n "LDFLAGS += -Wl,-rpath*" Makefile > /dev/null -if [ $? = 0 ]; then - line=($(grep -n "LDFLAGS += -Wl,-rpath*" Makefile | cut -d ':' -f 1)) - sed -i "${line}d" Makefile - sed -i "${line}i\LDFLAGS += -Wl,-rpath,$openssl_path/lib:$wd_path/lib" Makefile -else - line=($(grep -n "LDFLAGS += -Wl,-z,relro,-z,now,-z,noexecstack" Makefile | cut -d ':' -f 1)) - sed -i "${line}a\LDFLAGS += -Wl,-rpath,$openssl_path/lib:$wd_path/lib" Makefile -fi - -WD_PATH=./../drivers/warpdrive -WD_SOURCE_PATH=/usr/local/include/warpdrive -WD_RPM_PATH=/usr/include/warpdrive -grep -n "INCDIR += -I ${WD_PATH} -I ${WD_PATH}/include" Makefile > /dev/null -if [ $? = 0 ]; then - include_line=($(grep -n "INCDIR += -I ${WD_PATH} -I ${WD_PATH}/include" Makefile | cut -d ':' -f 1)) - sed -i "${include_line}d" Makefile -fi -grep -n "INCDIR += -I ${WD_RPM_PATH} -I ${WD_RPM_PATH}/include" Makefile > /dev/null -if [ $? = 0 ]; then - include_line=($(grep -n "INCDIR += -I ${WD_RPM_PATH} -I ${WD_RPM_PATH}/include" Makefile | cut -d ':' -f 1)) - sed -i "${include_line}d" Makefile -fi -grep -n "INCDIR += -I ${WD_SOURCE_PATH} -I ${WD_SOURCE_PATH}/include" Makefile > /dev/null -if [ $? = 0 ]; then - include_line=($(grep -n "INCDIR += -I ${WD_SOURCE_PATH} -I ${WD_SOURCE_PATH}/include" Makefile | cut -d ':' -f 1)) - sed -i "${include_line}d" Makefile -fi - -include_line=($(grep -n "INCDIR += -I \$(OPENSSL_WORK_PATH)/include" Makefile | cut -d ':' -f 1)) -if [ -f ${WD_PATH}/wd.h ]; then - sed -i "${include_line}a\INCDIR += -I ${WD_PATH} -I ${WD_PATH}/include" Makefile -elif [ -f ${WD_RPM_PATH}/wd.h ]; then - sed -i "${include_line}a\INCDIR += -I ${WD_RPM_PATH} -I ${WD_RPM_PATH}/include" Makefile -elif [ -f ${WD_SOURCE_PATH}/wd.h ]; then - sed -i "${include_line}a\INCDIR += -I ${WD_SOURCE_PATH} -I ${WD_SOURCE_PATH}/include" Makefile -else - echo "Warpdrive have not installed!" -fi - diff --git a/engine_kae.c b/engine_kae.c deleted file mode 100644 index 1398679..0000000 --- a/engine_kae.c +++ /dev/null @@ -1,392 +0,0 @@ -/* - * Copyright (c) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the implemenation for an OpenSSL KAE engine - * - * 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 _GNU_SOURCE -#define _GNU_SOURCE -#endif - -#ifndef __USE_GNU -#define __USE_GNU -#endif - -#include -#include -#include - -#include "engine_kae.h" -#include "engine_check.h" -#include "engine_fork.h" -#include "engine_utils.h" -#include "async_poll.h" -#include "sec_ciphers.h" -#include "sec_digests.h" -#include "hpre_rsa.h" -#include "hpre_dh.h" - -#define KAE_CMD_ENABLE_ASYNC ENGINE_CMD_BASE -#define KAE_CMD_ENABLE_SM3 ENGINE_CMD_BASE + 1 -#define KAE_CMD_ENABLE_SM4 ENGINE_CMD_BASE + 2 -#define PKEY_METHOD_TYPE_NUM 3 - -/* Engine id */ -const char *g_engine_kae_id = "kae"; -/* Engine name */ -const char *g_engine_kae_name = "Kunpeng Accelerator Engine"; -/* Support pkey method types */ -const int g_pkey_method_types[PKEY_METHOD_TYPE_NUM] = {EVP_PKEY_RSA, EVP_PKEY_DH, EVP_PKEY_DHX}; - -static int g_bind_ref_count = 0; - -static int hpre_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth, - const int **pnids, int nid); - -static const ENGINE_CMD_DEFN g_kae_cmd_defns[] = { - { - KAE_CMD_ENABLE_ASYNC, - "KAE_CMD_ENABLE_ASYNC", - "Enable or Disable the engine async interface.", - ENGINE_CMD_FLAG_NUMERIC}, - { - KAE_CMD_ENABLE_SM3, - "KAE_CMD_ENABLE_SM3", - "Enable or Disable the SM3.", - ENGINE_CMD_FLAG_NUMERIC}, - { - KAE_CMD_ENABLE_SM4, - "KAE_CMD_ENABLE_SM4", - "Enable or Disable the SM4.", - ENGINE_CMD_FLAG_NUMERIC}, - { - 0, NULL, NULL, 0 - } -}; - -/****************************************************************************** -* function: -* kae_engine_ctrl(ENGINE *e, int cmd, long i,void *p, void (*f)(void)) -* -* @param e [IN] - OpenSSL engine pointer -* @param cmd [IN] - Control Command -* @param i [IN] - Input Parameters for the command -* @param p [IN] - Parameters for the command -* @param f [IN] - Callback function -* -* description: -* Qat engine control functions. -* Note: KAE_CMD_ENABLE_ASYNC should be called at the following -* point during startup: -* ENGINE_by_id -* ---> ENGINE_ctrl_cmd(KAE_CMD_ENABLE_ASYNC) -* ENGINE_init -******************************************************************************/ -static int kae_engine_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void)) -{ - int ret = 1; - (void)p; - (void)f; - - if (unlikely(e == NULL)) { - US_ERR("Null Enigne\n"); - return 0; - } - - switch (cmd) { - case KAE_CMD_ENABLE_ASYNC: - US_DEBUG("%s async polling\n", i == 0 ? "Disable" : "Enable"); - if (i == 0) { - kae_disable_async(); - } else { - kae_enable_async(); - } - break; - case KAE_CMD_ENABLE_SM3: - US_DEBUG("%s SM3\n", i == 0 ? "Disable" : "Enable"); - if (i == 0) { - sec_digests_set_enabled(NID_sm3, 0); - } else { - sec_digests_set_enabled(NID_sm3, 1); - } - break; - case KAE_CMD_ENABLE_SM4: - US_DEBUG("%s SM4\n", i == 0 ? "Disable" : "Enable"); - if (i == 0) { - sec_ciphers_set_enabled(NID_sm4_ctr, 0); - sec_ciphers_set_enabled(NID_sm4_cbc, 0); - sec_ciphers_set_enabled(NID_sm4_ofb128, 0); - sec_ciphers_set_enabled(NID_sm4_ecb, 0); - } else { - sec_ciphers_set_enabled(NID_sm4_ctr, 1); - sec_ciphers_set_enabled(NID_sm4_cbc, 1); - sec_ciphers_set_enabled(NID_sm4_ofb128, 1); - sec_ciphers_set_enabled(NID_sm4_ecb, 1); - } - break; - default: - US_WARN("CTRL command not implemented\n"); - ret = 0; - break; - } - - return ret; -} - -static int kae_engine_init(ENGINE *e) -{ - UNUSED(e); - return 1; -} - -static int kae_engine_destroy(ENGINE *e) -{ - UNUSED(e); - - if (__sync_sub_and_fetch(&g_bind_ref_count, 1) <= 0) { - hpre_destroy(); - hpre_dh_destroy(); - sec_ciphers_free_ciphers(); - sec_digests_free_methods(); - err_unload_kae_strings(); - kae_debug_close_log(); - - __sync_and_and_fetch(&g_bind_ref_count, 0); - } - - return 1; -} - -static int kae_engine_finish(ENGINE *e) -{ - UNUSED(e); - return 1; -} - -static int kae_engine_setup(void) -{ - if (__sync_add_and_fetch(&g_bind_ref_count, 1) == 1) { - kae_debug_init_log(); - /* Ensure the kae error handling is set up */ - err_load_kae_strings(); - - if (!cipher_module_init()) { - __sync_and_and_fetch(&g_bind_ref_count, 0); - return 0; - } - - if (!digest_module_init()) { - __sync_and_and_fetch(&g_bind_ref_count, 0); - return 0; - } - - if (!hpre_module_init()) { - __sync_and_and_fetch(&g_bind_ref_count, 0); - return 0; - } - - if (!hpre_module_dh_init()) { - __sync_and_and_fetch(&g_bind_ref_count, 0); - return 0; - } - - if (!kae_checking_q_thread_init()) { - __sync_and_and_fetch(&g_bind_ref_count, 0); - return 0; - } - - async_module_init(); - pthread_atfork(engine_do_before_fork_handler, engine_init_parent_at_fork_handler, - engine_init_child_at_fork_handler); - } - - return 1; -} - -int kae_get_device(const char* dev) -{ - struct dirent *device = NULL; - DIR *wd_class = NULL; - int found = 0; - const char* uacce_path = "/sys/class/uacce"; - - if (access(uacce_path, 0) != 0 || (dev == NULL)) { - US_WARN("WD framework is not enabled on the system!\n"); - return 0; - } - - wd_class = opendir(uacce_path); - if (wd_class == NULL) { - US_WARN("uacce_path cant be opened!\n"); - return 0; - } - - while ((device = readdir(wd_class)) != NULL) { - if (strstr(device->d_name, dev)) { - found = 1; - break; - } - } - closedir(wd_class); - - return found == 1 ? 1 : 0; -} - -static int hpre_check_meth_args(EVP_PKEY_METHOD **pmeth, - const int **pnids, int nid) -{ - if ((pnids == NULL) && ((pmeth == NULL) || (nid < 0))) { - KAEerr(KAE_F_HPRE_PKEY_METHS, KAE_R_INPUT_PARAM_ERR); - US_ERR("wd_engine_digests invalid input param."); - if (pmeth != NULL) { - *pmeth = NULL; - } - return OPENSSL_FAIL; - } - if (pmeth == NULL && pnids != NULL) { - *pnids = g_pkey_method_types; - return PKEY_METHOD_TYPE_NUM; - } - if (pmeth == NULL) { - return OPENSSL_FAIL; - } - - return HPRE_CONT; -} - -static int hpre_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth, - const int **pnids, int nid) -{ - UNUSED(e); - int ret = hpre_check_meth_args(pmeth, pnids, nid); - if (ret != HPRE_CONT) { - return ret; - } - - switch (nid) { - case EVP_PKEY_RSA: - *pmeth = get_rsa_pkey_meth(); - break; - case EVP_PKEY_DH: - *pmeth = get_dh_pkey_meth(); - break; - case EVP_PKEY_DHX: - *pmeth = (EVP_PKEY_METHOD *)EVP_PKEY_meth_find(EVP_PKEY_DHX); - break; - default: - *pmeth = NULL; - break; - } - - return (*pmeth != NULL); -} - -/****************************************************************************** -* function: -* bind_helper(ENGINE *e, -* const char *id) -* -* @param e [IN] - OpenSSL engine pointer -* @param id [IN] - engine id -* -* description: -* Connect KAE engine to OpenSSL engine library -******************************************************************************/ -static int bind_kae(ENGINE *e, const char *id) -{ - int ret; - (void)id; - const char *sec_device = "hisi_sec"; - static int loaded = 0; - if (loaded) { - US_ERR("ENGINE defined already!\n"); - KAEerr(KAE_F_BIND_HELPER, KAE_R_ENGINE_ALREADY_DEFINED); - return 0; - } - loaded = 1; - -#undef RETURN_FAIL_IF -#define RETURN_FAIL_IF(cond, mesg, f, r) \ - if (cond) { \ - KAEerr(f, r); \ - US_ERR(mesg); \ - return 0; \ - }\ - - if (!kae_engine_setup()) { - US_ERR("ENGINE setup failed\n"); - return 0; - } - - ret = ENGINE_set_id(e, g_engine_kae_id); - RETURN_FAIL_IF(ret != 1, "ENGINE_set_id failed.", - KAE_F_BIND_HELPER, KAE_R_SET_ID_FAILURE); - - ret = ENGINE_set_name(e, g_engine_kae_name); - RETURN_FAIL_IF(ret != 1, "ENGINE_set_name failed.", - KAE_F_BIND_HELPER, KAE_R_SET_NAME_FAILURE); - - ret = kae_get_device(sec_device); - if (ret != 0) { -#ifndef KAE_NO_CIPHER_METH - ret = ENGINE_set_ciphers(e, sec_engine_ciphers); - RETURN_FAIL_IF(ret != 1, "ENGINE_set_ciphers failed.", - KAE_F_BIND_HELPER, KAE_R_SET_CIPHERS_FAILURE); -#endif -#ifndef KAE_NO_DIGEST_METH - ret = ENGINE_set_digests(e, sec_engine_digests); - RETURN_FAIL_IF(ret != 1, "ENGINE_set_digests failed.", - KAE_F_BIND_HELPER, KAE_R_SET_DIGESTS_FAILURE); -#endif - } - - ret = ENGINE_set_pkey_meths(e, hpre_pkey_meths); - RETURN_FAIL_IF(ret != 1, "ENGINE_set_finish_function failed", - KAE_F_BIND_HELPER, KAE_R_SET_PKEYMETH_FAILURE); -#ifndef KAE_NO_RSA_METH - ret = ENGINE_set_RSA(e, hpre_get_rsa_methods()); - RETURN_FAIL_IF(ret != 1, "ENGINE_set_RSA failed.", - KAE_F_BIND_HELPER, KAE_R_SET_RSA_FAILURE); -#endif -#ifndef KAE_NO_DH_METH - ret = ENGINE_set_DH(e, hpre_get_dh_methods()); - RETURN_FAIL_IF(ret != 1, "ENGINE_set_DH failed.", - KAE_F_BIND_HELPER, KAE_R_SET_DH_FAILURE); -#endif - ret = ENGINE_set_destroy_function(e, kae_engine_destroy); - RETURN_FAIL_IF(ret != 1, "ENGINE_set_destroy_function failed.", - KAE_F_BIND_HELPER, KAE_R_SET_DESTORY_FAILURE); - - ret = ENGINE_set_init_function(e, kae_engine_init); - RETURN_FAIL_IF(ret != 1, "ENGINE_set_init_function failed.", - KAE_F_BIND_HELPER, KAE_R_SET_INIT_FAILURE); - - ret = ENGINE_set_finish_function(e, kae_engine_finish); - RETURN_FAIL_IF(ret != 1, "ENGINE_set_finish_function failed.", - KAE_F_BIND_HELPER, KAE_R_SET_FINISH_FAILURE); - - ret &= ENGINE_set_ctrl_function(e, kae_engine_ctrl); - ret &= ENGINE_set_cmd_defns(e, g_kae_cmd_defns); - if (ret != 1) { - US_ERR("Engine set ctrl function or defines failed\n"); - return 0; - } - - return 1; -} - -IMPLEMENT_DYNAMIC_BIND_FN(bind_kae) -IMPLEMENT_DYNAMIC_CHECK_FN() -/*lint -e(10)*/ diff --git a/engine_kae.h b/engine_kae.h deleted file mode 100644 index f7956dc..0000000 --- a/engine_kae.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the interface for an OpenSSL KAE engine - * - * 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 ENGINE_KAE_H -#define ENGINE_KAE_H - -#include -#include -#include - -#include "engine_opensslerr.h" -#include "engine_log.h" - -/* Engine id */ -extern const char *g_engine_kae_id ; - -int kae_get_device(const char *dev); - -#endif // !ENGINE_KAE_H - diff --git a/utils/engine_check.c b/utils/engine_check.c deleted file mode 100644 index 02ba875..0000000 --- a/utils/engine_check.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the implemenation for an engine check thread - * - * 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 "sec_ciphers_wd.h" -#include "sec_digests_wd.h" -#include "hpre_wd.h" -#include "hpre_dh_wd.h" -#include "engine_check.h" -#include "engine_utils.h" -#include "engine_log.h" - -KAE_CHECK_Q_TASK g_kae_check_q_task = { - .init_flag = NOT_INIT, -}; -static pthread_once_t g_check_thread_is_initialized = PTHREAD_ONCE_INIT; - -static struct kae_spinlock g_kae_async_spinmtx = { - .lock = 0, -}; - -static unsigned int g_kae_async_enabled = 1; - -void kae_enable_async(void) -{ - KAE_SPIN_LOCK(g_kae_async_spinmtx); - g_kae_async_enabled = 1; - KAE_SPIN_UNLOCK(g_kae_async_spinmtx); -} - -void kae_disable_async(void) -{ - KAE_SPIN_LOCK(g_kae_async_spinmtx); - g_kae_async_enabled = 0; - KAE_SPIN_UNLOCK(g_kae_async_spinmtx); -} - -int kae_is_async_enabled(void) -{ - return g_kae_async_enabled; -} - -static void kae_set_exit_flag() -{ - g_kae_check_q_task.exit_flag = 1; -} - -static void *kae_checking_q_loop_fn(void *args) -{ - (void)args; - - while (1) { - if (g_kae_check_q_task.exit_flag) { - break; - } - - usleep(KAE_QUEUE_CHECKING_INTERVAL); - if (g_kae_check_q_task.exit_flag) { - break; // double check - } - - kae_queue_pool_check_and_release(wd_ciphers_get_qnode_pool(), wd_ciphers_free_engine_ctx); - kae_queue_pool_check_and_release(wd_digests_get_qnode_pool(), wd_digests_free_engine_ctx); - kae_queue_pool_check_and_release(wd_hpre_get_qnode_pool(), NULL); - kae_queue_pool_check_and_release(wd_hpre_dh_get_qnode_pool(), NULL); - } - US_INFO("check thread exit normally."); - - return NULL; // lint !e527 -} - -static void kae_checking_q_thread_destroy(void) -{ - kae_set_exit_flag(); - (void)kae_join_thread(g_kae_check_q_task.thread_id, NULL); - - (void)wd_digests_uninit_qnode_pool(); - (void)wd_ciphers_uninit_qnode_pool(); - (void)wd_hpre_dh_uninit_qnode_pool(); - (void)wd_hpre_uninit_qnode_pool(); - - return; -} - -static void kae_check_thread_init() -{ - if (g_kae_check_q_task.init_flag == INITED) return; - - pthread_t thread_id; - if (!kae_create_thread_joinable(&thread_id, NULL, kae_checking_q_loop_fn, NULL)) { - US_ERR("fail to create check thread"); - return; - } - - g_kae_check_q_task.thread_id = thread_id; - g_kae_check_q_task.init_flag = INITED; - - (void)OPENSSL_atexit(kae_checking_q_thread_destroy); - return; -} - -int kae_checking_q_thread_init(void) -{ - US_DEBUG("check queue thread init begin"); - - if (g_kae_check_q_task.init_flag == INITED) - return 1; - - pthread_once(&g_check_thread_is_initialized, kae_check_thread_init); - - if (g_kae_check_q_task.init_flag != INITED) { - US_ERR("check thread init failed"); - g_check_thread_is_initialized = PTHREAD_ONCE_INIT; - return 0; - } - - return 1; -} - -void kae_check_thread_reset() -{ - kae_memset(&g_kae_check_q_task, 0, sizeof(KAE_CHECK_Q_TASK)); - g_check_thread_is_initialized = PTHREAD_ONCE_INIT; -} - diff --git a/utils/engine_check.h b/utils/engine_check.h deleted file mode 100644 index e7b2d28..0000000 --- a/utils/engine_check.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the interface for an engine check thread - * - * 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 ENGINE_CHECK_H -#define ENGINE_CHECK_H - -#include - -#define KAE_QUEUE_CHECKING_INTERVAL 15000 - - -struct kae_check_q_task_s { - int init_flag; - int exit_flag; - pthread_t thread_id; -}; - -typedef struct kae_check_q_task_s KAE_CHECK_Q_TASK; - -void kae_enable_async(void); -void kae_disable_async(void); -int kae_is_async_enabled(void); -int kae_checking_q_thread_init(void); -void kae_check_thread_reset(); - -#endif // end of ENGINE_CHECK_H - diff --git a/utils/engine_config.c b/utils/engine_config.c deleted file mode 100644 index 8f1082a..0000000 --- a/utils/engine_config.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides implemenation of configuration file reading for the KAE engine - * - * 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 "engine_config.h" - -int kae_drv_findsection(FILE *stream, const char *v_pszSection) -{ - char line[256]; // array length:256 - char *pos = NULL; - size_t section_len = strlen(v_pszSection); - - while (!feof(stream)) { - if (fgets(line, sizeof(line), stream) == NULL) { - return -1; - } - - pos = line; - if (*(pos++) != '[') { - continue; - } - - if (memcmp(pos, v_pszSection, section_len) == 0) { - pos += section_len; - if (*pos == ']') { - return 0; - } - } - } - - return -1; -} - -void kae_drv_get_value(char *pos, char *v_pszValue) -{ - while (*pos != '\0') { - if (*pos == ' ') { - pos++; - continue; - } - - if (*pos == ';') { - *(v_pszValue++) = '\0'; - return; - } - - *(v_pszValue++) = *(pos++); - } -} - -int kae_drv_find_item(FILE *stream, const char *v_pszItem, char *v_pszValue) -{ - char line[256]; // array length:256 - char *pos = NULL; - - while (!feof(stream)) { - if (fgets(line, sizeof(line), stream) == NULL) { - return -1; - } - - if (strstr(line, v_pszItem) != NULL) { - pos = strstr(line, "="); - if (pos != NULL) { - pos++; - kae_drv_get_value(pos, v_pszValue); - return 0; - } - } - - if ('[' == line[0]) { - break; - } - } - - return -1; -} - -int kae_drv_get_item(const char *config_file, const char *v_pszSection, - const char *v_pszItem, char *v_pszValue) -{ - FILE *stream; - int retvalue = -1; - - stream = fopen(config_file, "r"); - if (stream == NULL) { - return -1; - } - - if (kae_drv_findsection(stream, v_pszSection) == 0) { - retvalue = kae_drv_find_item(stream, v_pszItem, v_pszValue); - } - - fclose(stream); - - return retvalue; -} diff --git a/utils/engine_config.h b/utils/engine_config.h deleted file mode 100644 index aa81d82..0000000 --- a/utils/engine_config.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides interface of configuration file reading for the KAE engine - * - * 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_ACC_OPENSSL_CONFIG_H -#define HISI_ACC_OPENSSL_CONFIG_H - -#include -#include -#include - -int kae_drv_get_item(const char *config_file, const char *v_pszSection, - const char *v_pszItem, char *v_pszValue); - -#endif // HISI_ACC_OPENSSL_CONFIG_H diff --git a/utils/engine_fork.c b/utils/engine_fork.c deleted file mode 100644 index 2d623f2..0000000 --- a/utils/engine_fork.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the inplemenation for a KAE engine fork - * - * 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 "engine_fork.h" -#include "engine_check.h" -#include "async_poll.h" -#include "hpre_rsa.h" -#include "hpre_dh.h" -#include "sec_ciphers.h" -#include "sec_digests.h" -#include "engine_log.h" -#include "hpre_wd.h" -#include "hpre_dh_wd.h" -#include "sec_ciphers_wd.h" -#include "sec_digests_wd.h" - -void engine_init_child_at_fork_handler(void) -{ - US_DEBUG("call engine_init_child_at_fork_handler"); - - if (g_sec_digests_qnode_pool) { - g_sec_digests_qnode_pool->pool_use_num = 0; - } - if (g_sec_ciphers_qnode_pool) { - g_sec_ciphers_qnode_pool->pool_use_num = 0; - } - if (g_hpre_rsa_qnode_pool) { - g_hpre_rsa_qnode_pool->pool_use_num = 0; - } - if (g_hpre_dh_qnode_pool) { - g_hpre_dh_qnode_pool->pool_use_num = 0; - } - - (void)hpre_module_init(); - (void)hpre_module_dh_init(); - (void)cipher_module_init(); - (void)digest_module_init(); - - kae_check_thread_reset(); - if (!kae_checking_q_thread_init()) { - US_WARN("kae queue check thread init failed"); - } - async_module_init(); - - return; -} - -void engine_do_before_fork_handler(void) -{ - return; -} - -void engine_init_parent_at_fork_handler(void) -{ - return; -} diff --git a/utils/engine_fork.h b/utils/engine_fork.h deleted file mode 100644 index 7157b70..0000000 --- a/utils/engine_fork.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the interface for a KAE engine fork - * - * 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_FORK_H -#define __HPRE_FORK_H - -void engine_init_child_at_fork_handler(void); -void engine_do_before_fork_handler(void); -void engine_init_parent_at_fork_handler(void); - -#endif diff --git a/utils/engine_log.c b/utils/engine_log.c deleted file mode 100644 index b9b5a59..0000000 --- a/utils/engine_log.c +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the implemenation for log module - * - * 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 "engine_log.h" -#include "engine_config.h" -#include "engine_utils.h" - -#define KAE_CONFIG_FILE_NAME "/kae.cnf" -#define MAX_LEVEL_LEN 10 -#define MAX_CONFIG_LEN 512 - -static const char *g_kae_conf_env = "KAE_CONF_ENV"; - -FILE *g_kae_debug_log_file = (FILE *)NULL; -pthread_mutex_t g_debug_file_mutex = PTHREAD_MUTEX_INITIALIZER; -int g_debug_file_ref_count = 0; -int g_log_init_times = 0; -int g_kae_log_level = 0; - -const char *g_log_level[] = { - "none", - "error", - "warning", - "info", - "debug", -}; - -static char *kae_getenv(const char *name) -{ - return getenv(name); -} - -static void kae_set_conf_debuglevel() -{ - char *conf_path = kae_getenv(g_kae_conf_env); - unsigned int i = 0; - const char *filename = KAE_CONFIG_FILE_NAME; - char *file_path = (char *)NULL; - char *debuglev = (char *)NULL; - if (conf_path == NULL || strlen(conf_path) > MAX_CONFIG_LEN) { - goto err; - } - file_path = (char *)kae_malloc(strlen(conf_path) + strlen(filename) + 1); - debuglev = (char *)kae_malloc(MAX_LEVEL_LEN); - if (!file_path || !debuglev) { - goto err; - } - memset(debuglev, 0, MAX_LEVEL_LEN); - memset(file_path, 0, sizeof(conf_path) + sizeof(filename) + 1); - strcat(file_path, conf_path); - strcat(file_path, filename); - int ret = kae_drv_get_item(file_path, "LogSection", "debug_level", debuglev); - if (ret != 0) { - goto err; - } - - for (i = 0; i < sizeof(g_log_level) / sizeof(g_log_level[0]); i++) { - if (strncmp(g_log_level[i], debuglev, strlen(debuglev) - 1) == 0) { - g_kae_log_level = i; - kae_free(file_path); - kae_free(debuglev); - return; - } - } - -err: - g_kae_log_level = KAE_ERROR; - if (debuglev != NULL) { - kae_free(debuglev); - debuglev = (char *)NULL; - } - if (file_path != NULL) { - kae_free(file_path); - file_path = (char *)NULL; - } - - return; -} - -void kae_debug_init_log() -{ - pthread_mutex_lock(&g_debug_file_mutex); - kae_set_conf_debuglevel(); - if (!g_debug_file_ref_count && g_kae_log_level != KAE_NONE) { - g_kae_debug_log_file = fopen(KAE_DEBUG_FILE_PATH, "a+"); - if (g_kae_debug_log_file == NULL) { - g_kae_debug_log_file = stderr; - fprintf(stderr, "unable to open %s, %s\n", KAE_DEBUG_FILE_PATH, strerror(errno)); - } else { - g_debug_file_ref_count++; - } - } - g_log_init_times++; - pthread_mutex_unlock(&g_debug_file_mutex); -} - -void kae_debug_close_log() -{ - pthread_mutex_lock(&g_debug_file_mutex); - g_log_init_times--; - if (g_debug_file_ref_count && (g_log_init_times == 0)) { - if (g_kae_debug_log_file != NULL) { - fclose(g_kae_debug_log_file); - g_debug_file_ref_count--; - g_kae_debug_log_file = stderr; - } - } - pthread_mutex_unlock(&g_debug_file_mutex); -} - -void ENGINE_LOG_LIMIT(int level, int times, int limit, const char *fmt, ...) -{ - struct tm *log_tm_p = (struct tm *)NULL; - static unsigned long ulpre = 0; - static int is_should_print = 5; - - if (level > g_kae_log_level) { - return; - } - // cppcheck-suppress * - va_list args1 = { 0 }; - va_start(args1, fmt); - time_t curr = time((time_t *)NULL); - if (difftime(curr, ulpre) > limit) { - is_should_print = times; - } - if (is_should_print <= 0) { - is_should_print = 0; - } - if (is_should_print-- > 0) { - log_tm_p = (struct tm *)localtime(&curr); - flock(g_kae_debug_log_file->_fileno, LOCK_EX); - pthread_mutex_lock(&g_debug_file_mutex); - fseek(g_kae_debug_log_file, 0, SEEK_END); - if (log_tm_p != NULL) { - fprintf(g_kae_debug_log_file, "[%4d-%02d-%02d %02d:%02d:%02d][%s][%s:%d:%s()] ", - (1900 + log_tm_p->tm_year), (1 + log_tm_p->tm_mon), log_tm_p->tm_mday, // base time 1900 year - log_tm_p->tm_hour, log_tm_p->tm_min, log_tm_p->tm_sec, - g_log_level[level], __FILE__, __LINE__, __func__); - } else { - fprintf(g_kae_debug_log_file, "[%s][%s:%d:%s()] ", - g_log_level[level], __FILE__, __LINE__, __func__); - } - vfprintf(g_kae_debug_log_file, fmt, args1); - fprintf(g_kae_debug_log_file, "\n"); - if (ftell(g_kae_debug_log_file) > KAE_LOG_MAX_SIZE) { - kae_save_log(g_kae_debug_log_file); - ftruncate(g_kae_debug_log_file->_fileno, 0); - fseek(g_kae_debug_log_file, 0, SEEK_SET); - } - pthread_mutex_unlock(&g_debug_file_mutex); - flock(g_kae_debug_log_file->_fileno, LOCK_UN); - ulpre = time((time_t *)NULL); - } - - va_end(args1); -} - -static int need_debug(void) -{ - if (g_kae_log_level >= KAE_DEBUG) { - return 1; - } else { - return 0; - } -} - -/* - * desc: print data for debug - * @param name the name of buf - * @param buf the buf msg when input - * @param len bd len - */ -void dump_data(const char *name, unsigned char *buf, unsigned int len) -{ - unsigned int i; - - if (need_debug()) { - US_DEBUG("DUMP ==> %s", name); - for (i = 0; i + 8 <= len; i += 8) { // buf length:8 - US_DEBUG("0x%llx: \t%02x %02x %02x %02x %02x %02x %02x %02x", - (unsigned long long)(buf + i), - *(buf + i), (*(buf + i + 1)), *(buf + i + 2), *(buf + i + 3), // buf offset:0,1,2,3 - *(buf + i + 4), *(buf + i + 5), *(buf + i + 6), *(buf + i + 7)); // buf offset:4,5,6,7 - } - - if (len % 8) { // remainder:divide by 8 - US_DEBUG ("0x%llx: \t", (unsigned long long)(buf + i)); - for (; i < len; i++) { - US_DEBUG("%02x ", buf[i]); - } - } - } -} - -/* - * desc: print bd for debug - * @param bd the buf msg when input - * @param len bd len - */ -void dump_bd(unsigned int *bd, unsigned int len) -{ - unsigned int i; - - if (need_debug()) { - for (i = 0; i < len; i++) { - US_DEBUG("Word[%d] 0x%08x", i, bd[i]); - } - } -} - -void kae_save_log(FILE *src) -{ - int size = 0; - char buf[1024] = {0}; // buf length:1024 - - if (src == NULL) { - return; - } - - FILE *dst = fopen(KAE_DEBUG_FILE_PATH_OLD, "w"); - if (dst == NULL) { - return; - } - - fseek(src, 0, SEEK_SET); - while (1) { - size = fread(buf, sizeof(char), 1024, src); // buf length:1024 - fwrite(buf, sizeof(char), size, dst); - if (!size) { - break; - } - } - - fclose(dst); -} - diff --git a/utils/engine_log.h b/utils/engine_log.h deleted file mode 100644 index 51cfb7b..0000000 --- a/utils/engine_log.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the interface for log module - * - * 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 KAE_ACC_ENGINE_LOG_H -#define KAE_ACC_ENGINE_LOG_H -#include -#include -#include -#include -#include - - -#define LOG_LEVEL_CONFIG KAE_NONE -#define KAE_DEBUG_FILE_PATH "/var/log/kae.log" -#define KAE_DEBUG_FILE_PATH_OLD "/var/log/kae.log.old" -#define KAE_LOG_MAX_SIZE 209715200 - -extern FILE *g_kae_debug_log_file; - -extern pthread_mutex_t g_debug_file_mutex; - -extern const char *g_log_level[]; - -extern int g_kae_log_level; - -enum KAE_LOG_LEVEL { - KAE_NONE = 0, - KAE_ERROR, - KAE_WARNING, - KAE_INFO, - KAE_DEBUG, -}; - -void ENGINE_LOG_LIMIT(int level, int times, int limit, const char *fmt, ...); - -#define CRYPTO(LEVEL, fmt, args...) \ - do { \ - if (LEVEL > g_kae_log_level) { \ - break; \ - } \ - struct tm *log_tm_p = NULL; \ - time_t timep = time((time_t *)NULL); \ - log_tm_p = localtime(&timep); \ - flock(g_kae_debug_log_file->_fileno, LOCK_EX); \ - pthread_mutex_lock(&g_debug_file_mutex); \ - fseek(g_kae_debug_log_file, 0, SEEK_END); \ - if (log_tm_p != NULL) { \ - fprintf(g_kae_debug_log_file, "[%4d-%02d-%02d %02d:%02d:%02d][%s][%s:%d:%s()] " fmt "\n", \ - (1900 + log_tm_p->tm_year), (1 + log_tm_p->tm_mon), log_tm_p->tm_mday, \ - log_tm_p->tm_hour, log_tm_p->tm_min, log_tm_p->tm_sec, \ - g_log_level[LEVEL], __FILE__, __LINE__, __func__, ##args); \ - } else { \ - fprintf(g_kae_debug_log_file, "[%s][%s:%d:%s()] " fmt "\n", \ - g_log_level[LEVEL], __FILE__, __LINE__, __func__, ##args); \ - } \ - if (ftell(g_kae_debug_log_file) > KAE_LOG_MAX_SIZE) { \ - kae_save_log(g_kae_debug_log_file); \ - ftruncate(g_kae_debug_log_file->_fileno, 0); \ - fseek(g_kae_debug_log_file, 0, SEEK_SET); \ - } \ - pthread_mutex_unlock(&g_debug_file_mutex); \ - flock(g_kae_debug_log_file->_fileno, LOCK_UN); \ - } while (0) - -#define US_ERR(fmt, args...) CRYPTO(KAE_ERROR, fmt, ##args) -#define US_WARN(fmt, args...) CRYPTO(KAE_WARNING, fmt, ##args) -#define US_INFO(fmt, args...) CRYPTO(KAE_INFO, fmt, ##args) -#define US_DEBUG(fmt, args...) CRYPTO(KAE_DEBUG, fmt, ##args) -#define US_WARN_LIMIT(fmt, args...) ENGINE_LOG_LIMIT(KAE_WARNING, 3, 30, fmt, ##args) -#define US_ERR_LIMIT(fmt, args...) ENGINE_LOG_LIMIT(KAE_ERROR, 3, 30, fmt, ##args) -#define US_INFO_LIMIT(fmt, args...) ENGINE_LOG_LIMIT(KAE_INFO, 3, 30, fmt, ##args) -#define US_DEBUG_LIMIT(fmt, args...) ENGINE_LOG_LIMIT(KAE_DEBUG, 3, 30, fmt, ##args) - -void kae_debug_init_log(); -void kae_debug_close_log(); -void kae_save_log(FILE *src); - -/* - * desc: print data for debug - * @param name the name of buf - * @param buf the buf msg when input - * @param len bd len - */ -void dump_data(const char *name, unsigned char *buf, unsigned int len); - -/* - * desc: print bd for debug - * @param bd the buf msg when input - * @param len bd len - */ -void dump_bd(unsigned int *bd, unsigned int len); - -#endif diff --git a/utils/engine_opensslerr.c b/utils/engine_opensslerr.c deleted file mode 100644 index 59f1ae7..0000000 --- a/utils/engine_opensslerr.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the implemenation for error module - * - * 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 "engine_opensslerr.h" - -#define ERR_FUNC(func) ERR_PACK(0, func, 0) -#define ERR_REASON(reason) ERR_PACK(0, 0, reason) - -static int g_kae_lib_error_code = 0; -static int g_kae_error_init = 1; - -static ERR_STRING_DATA g_kae_str_functs[] = { - { ERR_FUNC(KAE_F_HPRE_GET_RSA_METHODS), "hpre_get_RSA_methods" }, - { ERR_FUNC(KAE_F_CHANGRSAMETHOD), "changRsaMethod" }, - { ERR_FUNC(KAE_F_HPRE_PKEY_METHS), "hpre_pkey_meths" }, - { ERR_FUNC(KAE_F_BIND_HELPER), "bind_helper" }, - { ERR_FUNC(KAE_F_RSA_FILL_KENGEN_PARAM), "rsa_fill_keygen_param" }, - { ERR_FUNC(KAE_F_HPRE_RSA_PUBENC), "hpre_rsa_public_encrypt" }, - { ERR_FUNC(KAE_F_HPRE_RSA_PRIENC), "hpre_rsa_private_encrypt" }, - { ERR_FUNC(KAE_F_HPRE_RSA_PUBDEC), "hpre_rsa_public_decrypt" }, - { ERR_FUNC(KAE_F_HPRE_RSA_PRIDEC), "hpre_rsa_private_decrypt" }, - { ERR_FUNC(KAE_F_HPRE_RSA_PRIMEGEN), "hpre_rsa_primegen" }, - { ERR_FUNC(KAE_F_HPRE_RSA_KEYGEN), "hpre_rsa_keygen" }, - { ERR_FUNC(KAE_F_CHECK_PUBKEY_PARAM), "check_pubkey_param" }, - { ERR_FUNC(KAE_F_HPRE_PUBENC_PADDING), "hpre_pubenc_padding" }, - { ERR_FUNC(KAE_F_HPRE_PRIENC_PADDING), "hpre_prienc_padding" }, - { ERR_FUNC(KAE_F_CHECK_HPRE_PUBDEC_PADDING), "hpre_check_pubdec_padding" }, - { ERR_FUNC(KAE_F_CHECK_HPRE_PRIDEC_PADDING), "hpre_check_pridec_padding" }, - { ERR_FUNC(KAE_F_DIGEST_SOFT_INIT), "sec_digest_soft_init" }, - { 0, (const char *)NULL } -}; - -static ERR_STRING_DATA g_kae_str_reasons[] = { - { ERR_REASON(KAE_R_NO_MATCH_DEVICE), "get no match device.check the hw resource" }, - { ERR_REASON(KAE_R_MALLOC_FAILURE), "no system memory to alloc" }, - { ERR_REASON(KAE_R_HWMEM_MALLOC_FAILURE), "no hardware memory to alloc" }, - { ERR_REASON(KAE_R_INPUT_PARAM_ERR), "input param is invaild" }, - { ERR_REASON(KAE_R_SET_ID_FAILURE), "kae engine set id failure" }, - { ERR_REASON(KAE_R_SET_NAME_FAILURE), "kae engine set name failure" }, - { ERR_REASON(KAE_R_SET_PKEYMETH_FAILURE), "kae engine set pkeymeth function failure" }, - { ERR_REASON(KAE_R_SET_RSA_FAILURE), "kae engine set rsa failure" }, - { ERR_REASON(KAE_R_SET_DESTORY_FAILURE), "kae engine set destory function failure" }, - { ERR_REASON(KAE_R_SET_INIT_FAILURE), "kae engine set init function failure" }, - { ERR_REASON(KAE_R_SET_CTRL_FAILURE), "kae engine set ctrl function failure" }, - { ERR_REASON(KAE_R_SET_CMDDEF_FAILURE), "kae engine set cmd define failure" }, - { ERR_REASON(KAE_R_SET_FINISH_FAILURE), "kae engine set finish function failure" }, - { ERR_REASON(KAE_R_UNSUPPORT_HARDWARE_TYPE), "unsupported hardware type" }, - { ERR_REASON(KAE_R_TIMEOUT), "Operation timeout" }, - { ERR_REASON(KAE_R_RSARECV_FAILURE), "RSA receive failure" }, - { ERR_REASON(KAE_R_RSARECV_STATE_FAILURE), "RSA received but status is failure" }, - { ERR_REASON(KAE_R_RSASEND_FAILURE), "RSA send failure" }, - { ERR_REASON(KAE_R_GET_ALLOCED_HWMEM_FAILURE), "get memory from reserve memory failure" }, - { ERR_REASON(KAE_R_FREE_ALLOCED_HWMEM_FAILURE), "free memory to reserve memory failure" }, - { ERR_REASON(KAE_R_RSA_KEY_NOT_COMPELET), "rsa key param is not compeleted" }, - { ERR_REASON(KAE_R_RSA_PADDING_FAILURE), "rsa padding failed" }, - { ERR_REASON(KAE_R_DATA_TOO_LARGE_FOR_MODULUS), "data too large for modules" }, - { ERR_REASON(KAE_R_DATA_GREATER_THEN_MOD_LEN), "data greater than mod len" }, - { ERR_REASON(KAE_R_CHECKPADDING_FAILURE), "check rsa padding failure" }, - { ERR_REASON(KAE_R_ERR_LIB_BN), "err in BN operation" }, - { ERR_REASON(KAE_R_RSA_KEY_SIZE_TOO_SMALL), "data too small" }, - { ERR_REASON(KAE_R_MODULE_TOO_LARGE), "data too large" }, - { ERR_REASON(KAE_R_INVAILED_E_VALUE), "invailed e value" }, - { ERR_REASON(KAE_R_UNKNOW_PADDING_TYPE), "unknow padding type" }, - { ERR_REASON(KAE_R_INPUT_FIKE_LENGTH_ZERO), "input file length zero" }, - { ERR_REASON(KAE_R_NEW_ENGINE_FAILURE), "get new engine failure" }, - { ERR_REASON(KAE_R_BIND_ENGINE_FAILURE), "kae engine bind failure" }, - { ERR_REASON(KAE_R_RSA_SET_METHODS_FAILURE), "rsa set kae methods failure" }, - { ERR_REASON(KAE_R_PUBLIC_KEY_INVALID), "invalid public key" }, - { ERR_REASON(KAE_R_PUBLIC_ENCRYPTO_FAILURE), "rsa public key encrypto failure" }, - { ERR_REASON(KAE_R_PUBLIC_DECRYPTO_FAILURE), "rsa public key decrypto failure" }, - { ERR_REASON(KAE_R_GET_PRIMEKEY_FAILURE), "rsa prime key generate failure" }, - { ERR_REASON(KAE_R_ENGINE_ALREADY_DEFINED), "kae engine already defined, try to use engine id 'kae' instead." }, - { 0, (const char *)NULL } -}; - -int err_load_kae_strings(void) -{ - if (g_kae_lib_error_code == 0) { - g_kae_lib_error_code = ERR_get_next_error_library(); - } - - if (g_kae_error_init) { - g_kae_error_init = 0; - ERR_load_strings(g_kae_lib_error_code, g_kae_str_functs); - ERR_load_strings(g_kae_lib_error_code, g_kae_str_reasons); - } - return 1; -} - -void err_unload_kae_strings(void) -{ - if (g_kae_error_init == 0) { - ERR_unload_strings(g_kae_lib_error_code, g_kae_str_functs); - ERR_unload_strings(g_kae_lib_error_code, g_kae_str_reasons); - g_kae_error_init = 1; - } -} - -void err_kae_error(int function, int reason, char *engine_file, int line) -{ - if (g_kae_lib_error_code == 0) { - g_kae_lib_error_code = ERR_get_next_error_library(); - } - ERR_PUT_error(g_kae_lib_error_code, function, reason, engine_file, line); -} diff --git a/utils/engine_opensslerr.h b/utils/engine_opensslerr.h deleted file mode 100644 index ae20270..0000000 --- a/utils/engine_opensslerr.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the interface for error module - * - * 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_ACC_ENGINE_OPENSSLERR_H -#define HISI_ACC_ENGINE_OPENSSLERR_H - -int err_load_kae_strings(void); -void err_unload_kae_strings(void); -void err_kae_error(int function, int reason, char *engine_file, int line); -#define KAEerr(f, r) err_kae_error((f), (r), OPENSSL_FILE, OPENSSL_LINE) - -/* Function codes. */ -enum HISI_FUNC_CODE { - KAE_F_HPRE_GET_RSA_METHODS = 100, - KAE_F_CHANGRSAMETHOD, - KAE_F_HPRE_PKEY_METHS, - KAE_F_BIND_HELPER, - KAE_F_RSA_FILL_KENGEN_PARAM, - KAE_F_HPRE_RSA_PUBENC, - KAE_F_HPRE_RSA_PRIENC, - KAE_F_HPRE_RSA_PUBDEC, - KAE_F_HPRE_RSA_PRIDEC, - KAE_F_HPRE_RSA_PRIMEGEN, - KAE_F_HPRE_RSA_KEYGEN, - KAE_F_CHECK_PUBKEY_PARAM, - KAE_F_HPRE_PUBENC_PADDING, - KAE_F_HPRE_PRIENC_PADDING, - KAE_F_CHECK_HPRE_PUBDEC_PADDING, - KAE_F_CHECK_HPRE_PRIDEC_PADDING, - KAE_F_SEC_SM3_INIT, - KAE_F_SEC_SM3_FINAL, - KAE_F_DIGEST_SOFT_INIT, - KAE_F_ENGINE_WD, - KAE_F_BIND_FN, - KAE_F_CHECK_DATA_VALID, - KAE_F_CHECK_MALLOC_SUCC, - KAE_F_HPRE_GET_DH_METHODS, - KAE_F_HPRE_DH_KEYGEN, - KAE_F_HPRE_DH_KEYCOMP, - KAE_F_CHANGDHMETHOD -}; - -enum HISI_RESON_CODE { - KAE_R_NO_MATCH_DEVICE = 100, - KAE_R_MALLOC_FAILURE, - KAE_R_HWMEM_MALLOC_FAILURE, - KAE_R_INPUT_PARAM_ERR, - KAE_R_SET_ID_FAILURE, - KAE_R_SET_NAME_FAILURE, - KAE_R_SET_PKEYMETH_FAILURE, - KAE_R_SET_RSA_FAILURE, - KAE_R_SET_DESTORY_FAILURE, - KAE_R_SET_INIT_FAILURE, - KAE_R_SET_CTRL_FAILURE, - KAE_R_SET_CMDDEF_FAILURE, - KAE_R_SET_FINISH_FAILURE, - KAE_R_UNSUPPORT_HARDWARE_TYPE, - KAE_R_TIMEOUT, - KAE_R_RSARECV_FAILURE, - KAE_R_RSARECV_STATE_FAILURE, - KAE_R_RSASEND_FAILURE, - KAE_R_GET_ALLOCED_HWMEM_FAILURE, - KAE_R_FREE_ALLOCED_HWMEM_FAILURE, - KAE_R_RSA_KEY_NOT_COMPELET, - KAE_R_RSA_PADDING_FAILURE, - KAE_R_DATA_TOO_LARGE_FOR_MODULUS, - KAE_R_DATA_GREATER_THEN_MOD_LEN, - KAE_R_CHECKPADDING_FAILURE, - KAE_R_ERR_LIB_BN, - KAE_R_RSA_KEY_SIZE_TOO_SMALL, - KAE_R_MODULE_TOO_LARGE, - KAE_R_INVAILED_E_VALUE, - KAE_R_UNKNOW_PADDING_TYPE, - KAE_R_INPUT_FIKE_LENGTH_ZERO, - KAE_R_SET_CIPHERS_FAILURE, - KAE_R_SET_DIGESTS_FAILURE, - KAE_R_NEW_ENGINE_FAILURE, - KAE_R_BIND_ENGINE_FAILURE, - KAE_R_RSA_SET_METHODS_FAILURE, - KAE_R_PUBLIC_KEY_INVALID, - KAE_R_PUBLIC_ENCRYPTO_FAILURE, - KAE_R_PUBLIC_DECRYPTO_FAILURE, - KAE_R_GET_PRIMEKEY_FAILURE, - KAE_R_DH_SET_METHODS_FAILURE, - KAE_R_SET_DH_FAILURE, - KAE_R_DH_KEY_SIZE_TOO_LARGE, - KAE_R_DH_INVALID_PARAMETER, - KAE_R_ENGINE_ALREADY_DEFINED, -}; - -#endif // HISI_ACC_ENGINE_OPENSSLERR_H diff --git a/utils/engine_types.h b/utils/engine_types.h deleted file mode 100644 index e9026aa..0000000 --- a/utils/engine_types.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the implemenation for some base type or define for KAE - * - * 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 KAE_ENGINE_TYPES_H -#define KAE_ENGINE_TYPES_H - -#define OPENSSL_SUCCESS (1) -#define OPENSSL_FAIL (0) -#define KAE_SUCCESS (0) -#define KAE_FAIL (-1) - -#define NO_C_MODE (UINT_MAX) -#define NO_C_ALG (UINT_MAX) - -#endif - diff --git a/utils/engine_utils.c b/utils/engine_utils.c deleted file mode 100644 index 520eb6f..0000000 --- a/utils/engine_utils.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the implemenation for utis module - * - * 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 "engine_utils.h" -#include "engine_log.h" - -#define KAE_MEM_IMPROVE_THRESHOLD 1024 - -int kae_create_thread(pthread_t *thread_id, const pthread_attr_t *attr, - void *(*start_func)(void *), void *p_arg) -{ - (void)attr; - - pthread_attr_t thread_attr; - pthread_attr_init(&thread_attr); - pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED); - if (pthread_create(thread_id, &thread_attr, start_func, p_arg) != 0) { - US_ERR("fail to create thread, reason:%s", strerror(errno)); //lint !e666 - return 0; - } - - return 1; -} - -int kae_create_thread_joinable(pthread_t *thread_id, const pthread_attr_t *attr, - void *(*start_func)(void *), void *p_arg) -{ - (void)attr; - - pthread_attr_t thread_attr; - pthread_attr_init(&thread_attr); - pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE); - if (pthread_create(thread_id, &thread_attr, start_func, p_arg) != 0) { - US_ERR("fail to create thread, reason:%s", strerror(errno)); //lint !e666 - return 0; - } - return 1; -} - -inline int kae_join_thread(pthread_t threadId, void **retval) -{ - return pthread_join(threadId, retval); -} - -inline void* memcpy_large(void *dstpp, const void *srcpp, size_t len) -{ - __asm__ __volatile__( - "add x4, %[src], %[count] \n\t" - "add x5, %[res], %[count] \n\t" - "ldr q0, [%[src]] \n\t" - "str q0, [%[res]] \n\t" - "sub %[count], %[count], 80 \n\t" - "and x14, %[src], 15 \n\t" - "bic %[src], %[src], 15 \n\t" - "sub x3, %[res], x14 \n\t" - "add %[count], %[count], x14 \n\t" - - "1: \n\t" - "ldp q0, q1, [%[src], 16] \n\t" - "stp q0, q1, [x3, 16] \n\t" - "ldp q0, q1, [%[src], 48] \n\t" - "stp q0, q1, [x3, 48] \n\t" - "add %[src], %[src], 64 \n\t" - "add x3, x3, 64 \n\t" - "subs %[count], %[count], 64 \n\t" - "b.hi 1b \n\t" - - "ldp q0, q1, [x4, -64] \n\t" - "stp q0, q1, [x5, -64] \n\t" - "ldp q0, q1, [x4, -32] \n\t" - "stp q0, q1, [x5, -32] \n\t" - - :[res] "+r"(dstpp) - :[src] "r"(srcpp), [count] "r"(len) - :"x3", "x4", "x5", "x14", "q0", "q1" - ); - - return dstpp; -} - -void* kae_memcpy(void *dstpp, const void *srcpp, size_t len) -{ - if (len >= KAE_MEM_IMPROVE_THRESHOLD) { - return memcpy_large(dstpp, srcpp, len); - } else { - return memcpy(dstpp, srcpp, len); - } -} diff --git a/utils/engine_utils.h b/utils/engine_utils.h deleted file mode 100644 index dba23e1..0000000 --- a/utils/engine_utils.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the interface for utils module - * - * 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 KAE_ACC_ENGINE_UTILS_H -#define KAE_ACC_ENGINE_UTILS_H -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define gettid() syscall(SYS_gettid) -#define PRINTPID \ - US_DEBUG("pid=%d, ptid=%lu, tid=%d", getpid(), pthread_self(), gettid()) - -#define likely(x) __builtin_expect(!!(x), 1) -#define unlikely(x) __builtin_expect(!!(x), 0) - -#ifndef true -#define true (0 == 0) -#endif - -#ifndef false -#define false (0 == 1) -#endif - -enum KAE_Q_INIT_FLAG { - NOT_INIT = 0, - INITED, -}; - -#define UNUSED(x) (void)(x) - -#define BLOCKSIZES_OF(data) (sizeof((data)) / sizeof(((data)[0]))) - -#define KAE_SPIN_INIT(q) kae_spinlock_init(&(q)) -#define KAE_SPIN_LOCK(q) kae_spinlock_lock(&(q)) -#define KAE_SPIN_TRYLOCK(q) kae_spinlock_trylock(&(q)) -#define KAE_SPIN_UNLOCK(q) kae_spinlock_unlock(&(q)) - -#define kae_free(addr) \ - do { \ - if (addr != NULL) { \ - free(addr); \ - addr = NULL; \ - } \ - } while (0) - -struct kae_spinlock { - int lock; -}; - -static inline void kae_spinlock_init(struct kae_spinlock *lock) -{ - lock->lock = 0; -} - -static inline void kae_spinlock_lock(struct kae_spinlock *lock) -{ - while (__sync_lock_test_and_set(&lock->lock, 1)) {} -} - -static inline int kae_spinlock_trylock(struct kae_spinlock *lock) -{ - return __sync_lock_test_and_set(&lock->lock, 1) == 0; -} - -static inline void kae_spinlock_unlock(struct kae_spinlock *lock) -{ - __sync_lock_release(&lock->lock); -} - -static inline void *kae_malloc(unsigned int size) -{ - return malloc(size); -} - -static inline void *kae_realloc(void *mem_address, unsigned int newsize) -{ - return realloc(mem_address, newsize); -} - -static inline void *kae_calloc(unsigned int num, unsigned int size) -{ - return calloc(num, size); -} - -static inline int kae_strcmp(const char *src, const char *dst) -{ - return strcmp(src, dst); -} - -static inline void kae_memset(void *ptr, int value, int len) -{ - (void)memset(ptr, value, len); -} - -void* kae_memcpy(void *dstpp, const void *srcpp, size_t len); - -static inline void kae_pthread_yield() -{ - (void)pthread_yield(); //lint !e1055 -} - -int kae_create_thread(pthread_t *thread_id, const pthread_attr_t *attr, - void *(*start_func)(void *), void *p_arg); - -int kae_create_thread_joinable(pthread_t *thread_id, const pthread_attr_t *attr, - void *(*start_func)(void *), void *p_arg); - -inline int kae_join_thread(pthread_t thread_id, void **retval); - -#endif diff --git a/wdmngr/wd_alg_queue.c b/wdmngr/wd_alg_queue.c deleted file mode 100644 index bffd716..0000000 --- a/wdmngr/wd_alg_queue.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the wd queue management module - * - * 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 "wd_alg_queue.h" -#include "engine_log.h" - -struct wd_queue* wd_new_queue(int algtype) -{ - struct wd_queue* queue = (struct wd_queue *)kae_malloc(sizeof(struct wd_queue)); - if (queue == NULL) { - US_ERR("malloc failed"); - return NULL; - } - - kae_memset(queue, 0, sizeof(struct wd_queue)); - - switch (algtype) { - case WCRYPTO_RSA: - queue->capa.alg = "rsa"; - break; - case WCRYPTO_DH: - queue->capa.alg = "dh"; - break; - case WCRYPTO_CIPHER: - queue->capa.alg = "cipher"; - break; - case WCRYPTO_DIGEST: - queue->capa.alg = "digest"; - break; - case WCRYPTO_COMP: - case WCRYPTO_EC: - case WCRYPTO_RNG: - default: - US_WARN("not support algtype:%d", algtype); - kae_free(queue); - queue = NULL; - return NULL; - } - - int ret = wd_request_queue(queue); - if (ret) { - US_ERR("request wd queue fail!errno:%d", ret); - kae_free(queue); - queue = NULL; - return NULL; - } - - return queue; -} - -void wd_free_queue(struct wd_queue* queue) -{ - if (queue != NULL) { - wd_release_queue(queue); - kae_free(queue); - queue = NULL; - } -} - diff --git a/wdmngr/wd_alg_queue.h b/wdmngr/wd_alg_queue.h deleted file mode 100644 index 9b0995e..0000000 --- a/wdmngr/wd_alg_queue.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the interface for wd_alg_queue.c - * - * 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_ALG_QUEUE_H -#define __WD_ALG_QUEUE_H - -#include "wd.h" -#include "engine_utils.h" - -struct wd_queue* wd_new_queue(int algtype); - -void wd_free_queue(struct wd_queue* queue); - - -#endif - diff --git a/wdmngr/wd_queue_memory.c b/wdmngr/wd_queue_memory.c deleted file mode 100644 index 7414c11..0000000 --- a/wdmngr/wd_queue_memory.c +++ /dev/null @@ -1,569 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the implemenation for KAE engine of wd queue memory management - * - * 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 "wd_queue_memory.h" -#include "engine_utils.h" -#include "engine_log.h" -#include "wd_bmm.h" - -#define MAXBLOCKSIZE 0x90000 -#define MAXRSVMEM 0x400000 - -#define MAXBLOCKSIZE 0x90000 -#define MAXRSVMEM 0x400000 - -const char *g_alg_type[] = { - "rsa", - "dh", - "cipher", - "digest", -}; - -struct wd_queue_mempool *wd_queue_mempool_create(struct wd_queue *q, - unsigned int block_size, unsigned int block_num) -{ - void *addr = NULL; - unsigned long rsv_mm_sz; - struct wd_queue_mempool *pool = NULL; - unsigned int bitmap_sz; - const unsigned int BLOCKS_PER_BITMAP = 32; - - if (block_size > MAXBLOCKSIZE) { - US_ERR("error! current blk size is beyond 576k"); - return NULL; - } - - rsv_mm_sz = (unsigned long)block_size * (unsigned long)block_num; - if (rsv_mm_sz > (unsigned long)MAXRSVMEM) { - US_ERR("error! current mem size is beyond 4M"); - return NULL; - } - - addr = wd_reserve_memory(q, rsv_mm_sz); - if (addr == NULL) { - US_ERR("reserve_memory fail!"); - return NULL; - } - kae_memset(addr, 0, rsv_mm_sz); - - bitmap_sz = (block_num / BLOCKS_PER_BITMAP + 1) * sizeof(unsigned int); - pool = - (struct wd_queue_mempool *)kae_malloc(sizeof(struct wd_queue_mempool) + bitmap_sz); - if (pool == NULL) { - US_ERR("Alloc pool handle fail!"); - return NULL; - } - kae_memset(pool, 0, sizeof(struct wd_queue_mempool) + bitmap_sz); - - pool->base = addr; - sem_init(&pool->mempool_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; - pool->q = q; - - return pool; -} - -struct wd_queue_mempool *create_alg_wd_queue_mempool(int algtype, struct wd_queue *q) -{ - struct wd_queue_mempool *mempool = NULL; - unsigned int block_size; - unsigned int block_num; - - switch (algtype) { - case WCRYPTO_RSA: - block_size = RSA_BLOCK_SIZE; - block_num = RSA_BLOCK_NUM; - break; - case WCRYPTO_DH: - block_size = DH_BLOCK_SIZE; - block_num = DH_BLOCK_NUM; - break; - case WCRYPTO_CIPHER: - block_size = CIPHER_BLOCK_SIZE; - block_num = CIPHER_BLOCK_NUM; - break; - case WCRYPTO_DIGEST: - block_size = DIGEST_BLOCK_SIZE; - block_num = DIGEST_BLOCK_NUM; - break; - case WCRYPTO_COMP: - case WCRYPTO_EC: - case WCRYPTO_RNG: - default: - US_WARN("create_alg_wd_queue_mempool not support algtype:%d", algtype); - return NULL; - } - -#ifdef NO_WD_BLK_POOL - mempool = wd_queue_mempool_create(q, block_size, block_num); -#else - struct wd_blkpool_setup setup; - - kae_memset(&setup, 0, sizeof(setup)); - setup.block_size = block_size; - setup.block_num = block_num; - setup.align_size = 64; // align with 64 - - mempool = (struct wd_queue_mempool *)wd_blkpool_create(q, &setup); -#endif - - return mempool; -} - -void wd_queue_mempool_destroy(struct wd_queue_mempool *pool) -{ -#ifdef NO_WD_BLK_POOL - kae_free(pool); -#else - wd_blkpool_destroy(pool); -#endif - - return; -} - -void *kae_dma_map(void *usr, void *va, size_t sz) -{ -#ifdef NO_WD_BLK_POOL - struct wd_queue_mempool *pool = (struct wd_queue_mempool *)usr; - - return wd_dma_map(pool->q, va, sz); -#else - return wd_blk_iova_map(usr, va); -#endif -} - -void kae_dma_unmap(void *usr, void *va, void *dma, size_t sz) -{ -#ifdef NO_WD_BLK_POOL - struct wd_queue_mempool *pool = (struct wd_queue_mempool *)usr; - - return wd_dma_unmap(pool->q, va, dma, sz); -#else - return wd_blk_iova_unmap(usr, dma, va); -#endif -} - -#ifdef NO_WD_BLK_POOL -static void *wd_queue_pool_alloc_buf(struct wd_queue_mempool *pool) -{ - __u64 i = 0; - __u64 j = 0; - - (void) sem_wait(&pool->mempool_sem); - __u32 *pbm = pool->bitmap; - __u64 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->mempool_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->mempool_sem); - return (void*)((char *) pool->base + (tmp * pool->block_size)); - } - } - (void) sem_post(&pool->mempool_sem); - US_ERR("no reserve mem available!"); - - return NULL; -} - -static void wd_queue_pool_free_buf(struct wd_queue_mempool *pool, void *pbuf) -{ - __u32 *pbm = pool->bitmap; - - kae_memset(pbuf, 0, pool->block_size); - - __u64 offset = (__u64)((unsigned long) pbuf - (unsigned long) pool->base); - offset = offset / pool->block_size; - if (pool->block_num <= offset) { - US_ERR("offset = %lld, virtual address err!", offset); - return; - } - __u32 bit_mask = ~(0x1u << (offset & 31)); - (void) sem_wait(&pool->mempool_sem); - pbm[(offset >> 5)] &= bit_mask; - (void) sem_post(&pool->mempool_sem); -} -#endif - -void *kae_wd_alloc_blk(void *pool, size_t size) -{ - if (pool == NULL) { - US_ERR("mem pool empty!"); - return NULL; - } - -#ifdef NO_WD_BLK_POOL - struct wd_queue_mempool *mempool = (struct wd_queue_mempool *)pool; - if (size > (size_t)mempool->block_size) { - US_ERR("alloc size error, over one block size."); - return NULL; - } - return wd_queue_pool_alloc_buf((struct wd_queue_mempool *)pool); -#else - return wd_alloc_blk(pool); -#endif -} - -void kae_wd_free_blk(void *pool, void *blk) -{ -#ifdef NO_WD_BLK_POOL - wd_queue_pool_free_buf((struct wd_queue_mempool *)pool, blk); -#else - wd_free_blk(pool, blk); -#endif -} - -KAE_QUEUE_POOL_HEAD_S* kae_init_queue_pool(int algtype) -{ - KAE_QUEUE_POOL_HEAD_S *kae_pool = NULL; - - kae_pool = (KAE_QUEUE_POOL_HEAD_S *)kae_malloc(sizeof(KAE_QUEUE_POOL_HEAD_S)); - if (kae_pool == NULL) { - US_ERR("malloc pool head fail!"); - return NULL; - } - - /* fill data of head */ - kae_pool->algtype = algtype; - kae_pool->next = NULL; - kae_pool->pool_use_num = 0; - - /* malloc a pool */ - kae_pool->kae_queue_pool = (KAE_QUEUE_POOL_NODE_S *) - kae_malloc(KAE_QUEUE_POOL_MAX_SIZE * sizeof(KAE_QUEUE_POOL_NODE_S)); - if (kae_pool->kae_queue_pool == NULL) { - US_ERR("malloc failed"); - kae_free(kae_pool); - return NULL; - } - kae_memset(kae_pool->kae_queue_pool, 0, KAE_QUEUE_POOL_MAX_SIZE * sizeof(KAE_QUEUE_POOL_NODE_S)); - - pthread_mutex_init(&kae_pool->kae_queue_mutex, NULL); - pthread_mutex_init(&kae_pool->destroy_mutex, NULL); - - US_DEBUG("kae init %s queue success", g_alg_type[algtype]); - - return kae_pool; -} - -static KAE_QUEUE_DATA_NODE_S* kae_get_queue_data_from_list(KAE_QUEUE_POOL_HEAD_S* pool_head) -{ - int i = 0; - KAE_QUEUE_DATA_NODE_S *queue_data_node = NULL; - KAE_QUEUE_POOL_HEAD_S *temp_pool = pool_head; - - US_DEBUG("kae get queue node from pool start."); - - if ((pool_head->pool_use_num == 0) && (pool_head->next == NULL)) { - return queue_data_node; - } - - while (temp_pool != NULL) { - for (i = 0; i < temp_pool->pool_use_num; i++) { - if (temp_pool->kae_queue_pool[i].node_data == NULL) { - continue; - } - - if (KAE_SPIN_TRYLOCK(temp_pool->kae_queue_pool[i].spinlock)) { - if (temp_pool->kae_queue_pool[i].node_data == NULL) { - KAE_SPIN_UNLOCK(temp_pool->kae_queue_pool[i].spinlock); - continue; - } else { - queue_data_node = temp_pool->kae_queue_pool[i].node_data; - temp_pool->kae_queue_pool[i].node_data = (KAE_QUEUE_DATA_NODE_S *)NULL; - KAE_SPIN_UNLOCK(temp_pool->kae_queue_pool[i].spinlock); - - US_DEBUG("kae queue pool first success. queue_data_node=%p queue_node id =%d", queue_data_node, i); - return queue_data_node; - } - } - } - /* next pool */ - temp_pool = temp_pool->next; - } - - return queue_data_node; -} - -static void kae_free_wd_queue_memory(KAE_QUEUE_DATA_NODE_S *queue_node, release_engine_ctx_cb release_fn) -{ - if (queue_node != NULL) { - if (release_fn != NULL && queue_node->engine_ctx != NULL) { - release_fn(queue_node->engine_ctx); - queue_node->engine_ctx = NULL; - } - - if (queue_node->kae_queue_mem_pool != NULL) { - wd_queue_mempool_destroy(queue_node->kae_queue_mem_pool); - queue_node->kae_queue_mem_pool = NULL; - } - if (queue_node->kae_wd_queue != NULL) { - wd_free_queue(queue_node->kae_wd_queue); - queue_node->kae_wd_queue = NULL; - } - - kae_free(queue_node); - queue_node = NULL; - } - - US_DEBUG("free wd queue success"); -} - -static KAE_QUEUE_DATA_NODE_S* kae_new_wd_queue_memory(int algtype) -{ - KAE_QUEUE_DATA_NODE_S *queue_node = NULL; - - queue_node = (KAE_QUEUE_DATA_NODE_S *)kae_malloc(sizeof(KAE_QUEUE_DATA_NODE_S)); - if (queue_node == NULL) { - US_ERR("malloc failed"); - return NULL; - } - kae_memset(queue_node, 0, sizeof(KAE_QUEUE_DATA_NODE_S)); - - queue_node->kae_wd_queue = wd_new_queue(algtype); - if (queue_node->kae_wd_queue == NULL) { - US_ERR("new wd queue fail"); - goto err; - } - - queue_node->kae_queue_mem_pool = create_alg_wd_queue_mempool(algtype, queue_node->kae_wd_queue); - if (queue_node->kae_queue_mem_pool == NULL) { - US_ERR("request mempool fail!"); - goto err; - } - - return queue_node; - -err: - kae_free_wd_queue_memory(queue_node, NULL); - return NULL; -} - -KAE_QUEUE_DATA_NODE_S* kae_get_node_from_pool(KAE_QUEUE_POOL_HEAD_S* pool_head) -{ - KAE_QUEUE_DATA_NODE_S *queue_data_node = NULL; - - if (pool_head == NULL) { - US_ERR("input params pool_head is null"); - return NULL; - } - - queue_data_node = kae_get_queue_data_from_list(pool_head); - if (queue_data_node == NULL) { - queue_data_node = kae_new_wd_queue_memory(pool_head->algtype); - } - - return queue_data_node; -} - -static void kae_set_pool_use_num(KAE_QUEUE_POOL_HEAD_S *pool, int set_num) -{ - pthread_mutex_lock(&pool->kae_queue_mutex); - if (set_num > pool->pool_use_num) { - pool->pool_use_num = set_num; - } - (void)pthread_mutex_unlock(&pool->kae_queue_mutex); -} - -int kae_put_node_to_pool(KAE_QUEUE_POOL_HEAD_S* pool_head, KAE_QUEUE_DATA_NODE_S* node_data) -{ - int i = 0; - KAE_QUEUE_POOL_HEAD_S *temp_pool = pool_head; - KAE_QUEUE_POOL_HEAD_S *last_pool = NULL; - - if (node_data == NULL || pool_head == NULL) { - return 0; - } - - US_DEBUG("Add nodedata to pool"); - - while (temp_pool != NULL) { - for (i = 0; i < KAE_QUEUE_POOL_MAX_SIZE; i++) { - if (temp_pool->kae_queue_pool[i].node_data) { - continue; - } - - if (KAE_SPIN_TRYLOCK(temp_pool->kae_queue_pool[i].spinlock)) { - if (temp_pool->kae_queue_pool[i].node_data) { - KAE_SPIN_UNLOCK(temp_pool->kae_queue_pool[i].spinlock); - continue; - } else { - temp_pool->kae_queue_pool[i].node_data = node_data; - temp_pool->kae_queue_pool[i].add_time = time((time_t *)NULL); - KAE_SPIN_UNLOCK(temp_pool->kae_queue_pool[i].spinlock); - if (i >= temp_pool->pool_use_num) { - kae_set_pool_use_num(temp_pool, i + 1); - } - - US_DEBUG("kae put queue node to pool, queue_node id is %d.", i); - return 1; - } - } - } - last_pool = temp_pool; - temp_pool = temp_pool->next; - /* if no empty pool to add,new a pool */ - if (temp_pool == NULL) { - pthread_mutex_lock(&last_pool->destroy_mutex); - if (last_pool->next == NULL) { - temp_pool = kae_init_queue_pool(last_pool->algtype); - if (temp_pool == NULL) { - (void)pthread_mutex_unlock(&last_pool->destroy_mutex); - break; - } - last_pool->next = temp_pool; - } - (void)pthread_mutex_unlock(&last_pool->destroy_mutex); - } - } - /* if not added,free it */ - kae_free_wd_queue_memory(node_data, NULL); - return 0; -} - -void kae_queue_pool_reset(KAE_QUEUE_POOL_HEAD_S* pool_head) -{ - (void)pool_head; - return; -} - -void kae_queue_pool_destroy(KAE_QUEUE_POOL_HEAD_S* pool_head, release_engine_ctx_cb release_fn) -{ - int error = 0; - int i = 0; - KAE_QUEUE_DATA_NODE_S *queue_data_node = (KAE_QUEUE_DATA_NODE_S *)NULL; - KAE_QUEUE_POOL_HEAD_S *temp_pool = NULL; - KAE_QUEUE_POOL_HEAD_S *cur_pool = pool_head; - - while (cur_pool != NULL) { - error = pthread_mutex_lock(&cur_pool->destroy_mutex); - if (error != 0) { - (void)pthread_mutex_unlock(&cur_pool->destroy_mutex); - return; - } - - error = pthread_mutex_lock(&cur_pool->kae_queue_mutex); - if (error != 0) { - (void)pthread_mutex_unlock(&cur_pool->destroy_mutex); - return; - } - for (i = 0; i < cur_pool->pool_use_num; i++) { - queue_data_node = cur_pool->kae_queue_pool[i].node_data; - if (queue_data_node != NULL) { - kae_free_wd_queue_memory(queue_data_node, release_fn); - US_DEBUG("kae queue node destroy success. queue_node id =%d", i); - cur_pool->kae_queue_pool[i].node_data = NULL; - } - } - US_DEBUG("pool use num :%d.", cur_pool->pool_use_num); - - kae_free(cur_pool->kae_queue_pool); - - (void)pthread_mutex_unlock(&cur_pool->kae_queue_mutex); - (void)pthread_mutex_unlock(&cur_pool->destroy_mutex); - - pthread_mutex_destroy(&cur_pool->kae_queue_mutex); - pthread_mutex_destroy(&cur_pool->destroy_mutex); - - temp_pool = cur_pool; - - kae_free(cur_pool); - - cur_pool = temp_pool->next; - } - - US_DEBUG("kae queue pool destory success."); - return; -} - -void kae_queue_pool_check_and_release(KAE_QUEUE_POOL_HEAD_S* pool_head, release_engine_ctx_cb release_fn) -{ - int i = 0; - int error; - time_t current_time; - KAE_QUEUE_DATA_NODE_S *queue_data_node = NULL; - KAE_QUEUE_POOL_HEAD_S *cur_pool = pool_head; - - current_time = time((time_t *)NULL); - - while (cur_pool != NULL) { - error = pthread_mutex_lock(&cur_pool->destroy_mutex); - if (error != 0) { - cur_pool = cur_pool->next; - (void)pthread_mutex_unlock(&cur_pool->destroy_mutex); - continue; - } - if (cur_pool->kae_queue_pool == NULL) { - (void)pthread_mutex_unlock(&cur_pool->destroy_mutex); - cur_pool = cur_pool->next; - continue; - } - - for (i = cur_pool->pool_use_num - 1; i >= 0; i--) { - if (cur_pool->kae_queue_pool[i].node_data == NULL) { - continue; - } - - if (difftime(current_time, cur_pool->kae_queue_pool[i].add_time) < CHECK_QUEUE_TIME_SECONDS) { - continue; - } - - if (KAE_SPIN_TRYLOCK(cur_pool->kae_queue_pool[i].spinlock)) { - if ((cur_pool->kae_queue_pool[i].node_data == NULL) || - (difftime(current_time, cur_pool->kae_queue_pool[i].add_time) < CHECK_QUEUE_TIME_SECONDS)) { - KAE_SPIN_UNLOCK(cur_pool->kae_queue_pool[i].spinlock); - continue; - } else { - queue_data_node = cur_pool->kae_queue_pool[i].node_data; - cur_pool->kae_queue_pool[i].node_data = (KAE_QUEUE_DATA_NODE_S *)NULL; - KAE_SPIN_UNLOCK(cur_pool->kae_queue_pool[i].spinlock); - - kae_free_wd_queue_memory(queue_data_node, release_fn); - - US_DEBUG("hpre queue list release success. queue node id =%d", i); - } - } - } - - (void)pthread_mutex_unlock(&cur_pool->destroy_mutex); - cur_pool = cur_pool->next; - } - - return; -} - diff --git a/wdmngr/wd_queue_memory.h b/wdmngr/wd_queue_memory.h deleted file mode 100644 index 7dc0f23..0000000 --- a/wdmngr/wd_queue_memory.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2019. Huawei Technologies Co.,Ltd.All rights reserved. - * - * Description: This file provides the interface for wd_queue_memory.c - * - * 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_QUEUE_MEMORY_H -#define __WD_QUEUE_MEMORY_H - -#include -#include "wd.h" -#include "wd_alg_queue.h" -#include "engine_utils.h" - -#define KAE_QUEUE_POOL_MAX_SIZE 512 -#define CHECK_QUEUE_TIME_SECONDS 5 // seconds - -/* - * once use 3 block for ctx&pubkey*prikey. - * the max Concurrent num = HPRE_BLOCK_NUM/3 - * when use 4096bit rsa. block use max is 3576. - * 3576 = sizeof(ctx)(248)+ pubkey_size(1024) + prikey_size(2304) - * that means max block used is 2304. set 4096 for reserve - */ -#define RSA_BLOCK_NUM 16 -#define RSA_BLOCK_SIZE 4096 - -#define DH_BLOCK_NUM 16 -#define DH_BLOCK_SIZE 4096 - -#define CIPHER_BLOCK_NUM 4 -#define CIPHER_BLOCK_SIZE (272*1024) - -#define DIGEST_BLOCK_NUM 4 -#define DIGEST_BLOCK_SIZE (512 * 1024) - -typedef void (*release_engine_ctx_cb)(void* engine_ctx); - -typedef struct KAE_QUEUE_DATA_NODE { - struct wd_queue *kae_wd_queue; - struct wd_queue_mempool *kae_queue_mem_pool; - void *engine_ctx; -} KAE_QUEUE_DATA_NODE_S; - -typedef struct KAE_QUEUE_POOL_NODE { - // int using_flag; /* used:true,nouse:false */ - struct kae_spinlock spinlock; - time_t add_time; - // int index; /* index of node,init:-1 */ - KAE_QUEUE_DATA_NODE_S *node_data; - // KAE_QUEUE_POOL_NODE_S *next; -} KAE_QUEUE_POOL_NODE_S; - -typedef struct KAE_QUEUE_POOL_HEAD { - // int init_flag; - int pool_use_num; - int algtype; /* alg type,just init at init pool */ - pthread_mutex_t destroy_mutex; - pthread_mutex_t kae_queue_mutex; - struct KAE_QUEUE_POOL_HEAD *next; /* next pool */ - KAE_QUEUE_POOL_NODE_S *kae_queue_pool; /* point to a attray */ -} KAE_QUEUE_POOL_HEAD_S; - -struct wd_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 mempool_sem; - int dev; -}; - -struct wd_queue_mempool *wd_queue_mempool_create(struct wd_queue *q, unsigned int block_size, unsigned int block_num); - -void wd_queue_mempool_destroy(struct wd_queue_mempool *pool); - -void kae_wd_free_blk(void *pool, void *blk); -void *kae_wd_alloc_blk(void *pool, size_t size); - -void *kae_dma_map(void *usr, void *va, size_t sz); - -void kae_dma_unmap(void *usr, void *va, void *dma, size_t sz); - -KAE_QUEUE_POOL_HEAD_S* kae_init_queue_pool (int algtype); -KAE_QUEUE_DATA_NODE_S* kae_get_node_from_pool(KAE_QUEUE_POOL_HEAD_S* pool_head); -int kae_put_node_to_pool (KAE_QUEUE_POOL_HEAD_S* pool_head, KAE_QUEUE_DATA_NODE_S* node_data); -void kae_queue_pool_reset(KAE_QUEUE_POOL_HEAD_S* pool_head); -void kae_queue_pool_destroy(KAE_QUEUE_POOL_HEAD_S* pool_head, release_engine_ctx_cb release_fn); -void kae_queue_pool_check_and_release(KAE_QUEUE_POOL_HEAD_S* pool_head, release_engine_ctx_cb release_ectx_fn); - -#endif - -- Gitee From f13e3df0f0ba19f7e0ffcdf90bed6fc05a608e12 Mon Sep 17 00:00:00 2001 From: wuliaokanke Date: Sat, 3 Dec 2022 17:10:56 +0800 Subject: [PATCH 3/4] add kae2 readme --- README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..cf02b10 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +kae2 -- Gitee From bf27af1f6fefd6f707b7e7d5cb00b76ba02d6167 Mon Sep 17 00:00:00 2001 From: wuliaokanke Date: Sat, 3 Dec 2022 17:22:31 +0800 Subject: [PATCH 4/4] push uadk 2.3.38 --- 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 +++ 193 files changed, 121280 insertions(+) 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/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